Revert "Remove abandoned implementation."

Revert submission 3242160-remove-messaging-package

Reason for revert: Droidmonitor created revert due to b/364617310, b/364626927, b/364617560

Reverted changes: /q/submissionid:3241481-remove-messaging-package

This reverts commit 93b5e63726ab8f47a8266ed1cccf7c9c281bf0e0.

Change-Id: I182cbf1758988d9a4950d39354266a5fb3aaabce
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..fd0ed55
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,104 @@
+//  Copyright (C) 2015 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "Android-Apache-2.0",
+    ],
+}
+
+soong_config_module_type {
+    name: "messaging_java_defaults",
+    module_type: "java_defaults",
+    config_namespace: "messaging",
+    bool_variables: ["build_variant_eng"],
+    properties: ["optimize"],
+}
+
+messaging_java_defaults {
+    name: "messaging_defaults",
+    soong_config_variables: {
+        build_variant_eng: {
+            optimize: {
+                proguard_flags_files: [
+                    "proguard.flags",
+                    "proguard-test.flags",
+                ],
+            },
+            conditions_default: {
+                optimize: {
+                    proguard_flags_files: [
+                        "proguard.flags",
+                        "proguard-release.flags",
+                    ],
+                }
+            },
+        },
+    },
+}
+
+
+android_app {
+    name: "messaging",
+
+    srcs: ["src/**/*.java"],
+
+    defaults: ["messaging_defaults"],
+
+    static_libs: [
+        "androidx.appcompat_appcompat",
+        "androidx.collection_collection",
+        "androidx.core_core",
+        "androidx.fragment_fragment",
+        "androidx.media_media",
+        "androidx.legacy_legacy-support-core-utils",
+        "androidx.legacy_legacy-support-core-ui",
+        "androidx.palette_palette",
+        "androidx.recyclerview_recyclerview",
+        "androidx.viewpager_viewpager",
+        "androidx.legacy_legacy-support-v13",
+        "colorpicker",
+        "libchips",
+        "libphotoviewer",
+        "androidx.annotation_annotation",
+        "android-common",
+        "android-common-framesequence",
+        "com.android.vcard",
+        "guava",
+        "libphonenumber",
+    ],
+
+    aaptflags: [
+        "--version-name",
+        "1.0.001",
+        "--version-code",
+        "10001040",
+    ],
+    required: [
+        "libframesequence",
+        "libgiftranscode",
+    ],
+    optimize: {
+        obfuscate: true,
+        optimize: true,
+        enabled: true,
+    },
+
+    certificate: "platform",
+
+    sdk_version: "current",
+
+    product_specific: true,
+}
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..fffcdab
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,533 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.messaging"
+    android:installLocation="internalOnly">
+
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24" />
+
+    <!-- Application holds CPU wakelock while working in background -->
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <!-- Application needs SMS/MMS permissions -->
+    <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.WRITE_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_MMS"/>
+    <uses-permission android:name="android.permission.SEND_SMS"/>
+    <!-- Application needs access to MMS network -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <!-- Application needs CONTACT permissions -->
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+    <!-- Application needs to read profiles for the user itself from CP2 -->
+    <uses-permission android:name="android.permission.READ_PROFILE"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+
+    <!--  Optional features -->
+    <uses-feature android:name="android.hardware.camera" android:required="false" />
+    <uses-feature android:name="android.hardware.camera.front" android:required="false" />
+    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
+    <uses-feature android:name="android.hardware.microphone" android:required="false" />
+    <uses-feature android:name="android.hardware.screen.portrait" android:required="false" />
+
+    <application
+        android:name="com.android.messaging.BugleApplication"
+        android:allowBackup="false"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/BugleTheme"
+        android:supportsRtl="true">
+
+        <!-- Displays a list of conversations -->
+        <activity
+            android:name=".ui.conversationlist.ConversationListActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/app_name"
+            android:exported="true"
+            android:theme="@style/BugleTheme.ConversationListActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.APP_MESSAGING" />
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name=".ui.PermissionCheckActivity"
+            android:screenOrientation="portrait"
+            android:configChanges="orientation|screenSize|keyboardHidden" />
+
+        <!-- Launches a conversation (ensures correct app name shown in recents) -->
+        <activity
+            android:name=".ui.conversation.LaunchConversationActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:theme="@style/Invisible"
+            android:noHistory="true"
+            android:exported="true"
+            android:documentLaunchMode="always">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <action android:name="android.intent.action.SENDTO" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </activity>
+
+        <!-- Displays a list of archived conversations -->
+        <activity
+            android:name=".ui.conversationlist.ArchivedConversationListActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/archived_activity_title"
+            android:theme="@style/BugleTheme.ArchivedConversationListActivity"
+            android:parentActivityName="com.android.messaging.ui.conversationlist.ConversationListActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversationlist.ConversationListActivity" />
+        </activity>
+
+        <!-- Displays the contents of a single conversation -->
+        <activity
+            android:name=".ui.conversation.ConversationActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:windowSoftInputMode="stateHidden|adjustResize"
+            android:theme="@style/BugleTheme.ConversationActivity"
+            android:parentActivityName="com.android.messaging.ui.conversationlist.ConversationListActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversationlist.ConversationListActivity" />
+        </activity>
+
+        <!-- Blocked Participants -->
+        <activity
+            android:name=".ui.BlockedParticipantsActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/blocked_contacts_title"
+            android:theme="@style/BugleTheme"
+            android:parentActivityName="com.android.messaging.ui.conversationlist.ConversationListActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversationlist.ConversationListActivity" />
+        </activity>
+
+        <!-- Full-screen photo viewer -->
+        <activity
+            android:name=".ui.photoviewer.BuglePhotoViewActivity"
+            android:label="@string/photo_view_activity_title"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:theme="@style/BuglePhotoViewTheme"
+        />
+
+        <!-- Settings -->
+        <activity
+            android:name=".ui.appsettings.SettingsActivity"
+            android:label="@string/settings_activity_title"
+            android:theme="@style/BugleTheme.SettingsActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:parentActivityName="com.android.messaging.ui.conversationlist.ConversationListActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversationlist.ConversationListActivity" />
+        </activity>
+
+        <activity
+            android:name=".ui.appsettings.PerSubscriptionSettingsActivity"
+            android:label="@string/advanced_settings_activity_title"
+            android:theme="@style/BugleTheme.SettingsActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:parentActivityName="com.android.messaging.ui.appsettings.SettingsActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.appsettings.SettingsActivity" />
+        </activity>
+
+        <activity
+            android:name=".ui.appsettings.ApplicationSettingsActivity"
+            android:label="@string/general_settings_activity_title"
+            android:theme="@style/BugleTheme.SettingsActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:parentActivityName="com.android.messaging.ui.appsettings.SettingsActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:exported="true"
+                android:value="com.android.messaging.ui.appsettings.SettingsActivity" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.NOTIFICATION_PREFERENCES" />
+            </intent-filter>
+        </activity>
+
+        <!-- Handles sharing intent -->
+        <activity
+            android:name=".ui.conversationlist.ShareIntentActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:theme="@style/BugleTheme.DialogActivity"
+            android:excludeFromRecents="true"
+            android:exported="true"
+            android:documentLaunchMode="always">
+            <intent-filter
+                android:label="@string/share_intent_label">
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="text/plain" />
+                <data android:mimeType="text/x-vCard" />
+                <data android:mimeType="text/x-vcard" />
+                <data android:mimeType="image/*" />
+                <data android:mimeType="audio/*" />
+                <data android:mimeType="video/*" />
+                <data android:mimeType="application/ogg" />
+            </intent-filter>
+        </activity>
+
+        <!-- People & Options -->
+        <activity
+            android:name=".ui.conversationsettings.PeopleAndOptionsActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/people_and_options_activity_title"
+            android:theme="@style/BugleTheme"
+            android:parentActivityName="com.android.messaging.ui.conversation.ConversationActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversation.ConversationActivity" />
+        </activity>
+
+         <!-- License -->
+        <activity android:name=".ui.LicenseActivity"
+            android:exported="true"
+            android:theme="@android:style/Theme.Holo.Light.Dialog"
+            android:label="@string/menu_license">
+        </activity>
+
+        <!-- Message Forwarding -->
+        <activity
+            android:name=".ui.conversationlist.ForwardMessageActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/forward_message_activity_title"
+            android:theme="@style/BugleTheme.DialogActivity">
+        </activity>
+
+        <!-- Entry point for handling remote input/actions. Currently, this is only used by Android
+             Wear to send voice replies. Since that uses PendingIntents, we don't need to export
+             this activity. If we want other apps to be able to use this activity at will,
+             we'll need to guard it with a signature-matching protected permission. We would also
+             need to add an intent filter and remove the android:exported attribute. -->
+        <activity
+            android:name=".ui.RemoteInputEntrypointActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:exported="false"
+            android:theme="@style/Invisible">
+        </activity>
+
+        <!-- VCard details -->
+        <activity
+            android:name=".ui.VCardDetailActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/vcard_detail_activity_title"
+            android:theme="@style/BugleTheme">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value=".ui.conversation.ConversationActivity" />
+        </activity>
+
+        <!-- Attachment chooser -->
+        <activity
+            android:name=".ui.attachmentchooser.AttachmentChooserActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:label="@string/attachment_chooser_activity_title"
+            android:theme="@style/BugleTheme"
+            android:parentActivityName="com.android.messaging.ui.conversation.ConversationActivity">
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="com.android.messaging.ui.conversation.ConversationActivity" />
+        </activity>
+
+        <!-- Test activity that we use to host fragments/views. Unfortunately, apparently necessary
+             because Android framework test cases want activity to be in the instrumented package.
+             See http://developer.android.com/reference/android/test/ActivityInstrumentationTestCase2.html
+        -->
+        <activity
+            android:name=".ui.TestActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden">
+        </activity>
+
+        <activity
+            android:name=".ui.debug.DebugMmsConfigActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:screenOrientation="user"
+            android:theme="@style/BugleTheme.DialogActivity"
+            android:exported="false">
+        </activity>
+
+        <provider android:name=".datamodel.MessagingContentProvider" android:label="@string/app_name"
+                  android:authorities="com.android.messaging.datamodel.MessagingContentProvider"
+                  android:exported="false" >
+        </provider>
+
+        <provider android:name=".datamodel.MmsFileProvider"
+                  android:authorities="com.android.messaging.datamodel.MmsFileProvider"
+                  android:grantUriPermissions="true"
+                  android:exported="false" />
+
+        <provider android:name=".datamodel.MediaScratchFileProvider"
+                  android:authorities="com.android.messaging.datamodel.MediaScratchFileProvider"
+                  android:grantUriPermissions="true"
+                  android:exported="false" />
+
+
+        <!-- Action Services -->
+        <service android:name=".datamodel.action.ActionServiceImpl"
+                 android:permission="android.permission.BIND_JOB_SERVICE"
+                 android:exported="true"/>
+        <service android:name=".datamodel.action.BackgroundWorkerService"
+                 android:permission="android.permission.BIND_JOB_SERVICE"
+                 android:exported="true"/>
+
+        <!-- Sms and Mms related items -->
+
+        <!-- Intents for Notification and Pre-KLP Delivery -->
+        <!-- Registered with the highest possible priority (max_int) -->
+        <receiver android:name=".receiver.MmsWapPushReceiver"
+                  android:enabled="false"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter android:priority="2147483647">
+                <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+        <receiver android:name=".receiver.SmsReceiver"
+                  android:enabled="false"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter android:priority="2147483647">
+                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
+            </intent-filter>
+            <intent-filter android:priority="2147483647">
+                <action android:name="android.provider.Telephony.MMS_DOWNLOADED" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intents for aborting SMS/MMS broadcasts pre-KLP -->
+        <!-- Registered for a priority just ahead of inbox Messaging apps (2) -->
+        <receiver android:name=".receiver.AbortMmsWapPushReceiver"
+                  android:enabled="false"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter android:priority="3">
+                <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+        <receiver android:name=".receiver.AbortSmsReceiver"
+                  android:enabled="false"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter android:priority="3">
+                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intents for KLP+ Delivery -->
+        <receiver android:name=".receiver.MmsWapPushDeliverReceiver"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+        <receiver android:name=".receiver.SmsDeliverReceiver"
+                  android:exported="true"
+                  android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_DELIVER" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name=".receiver.SendStatusReceiver"
+                android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.messaging.receiver.SendStatusReceiver.MESSAGE_SENT" />
+                <data android:scheme="content" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.messaging.receiver.SendStatusReceiver.MESSAGE_DELIVERED" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.messaging.receiver.SendStatusReceiver.MMS_SENT" />
+                <data android:scheme="content" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.messaging.receiver.SendStatusReceiver.MMS_DOWNLOADED" />
+                <data android:scheme="content" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name=".datamodel.NoConfirmationSmsSendService"
+                 android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+                 android:exported="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </service>
+
+        <activity android:name=".ui.ClassZeroActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:screenOrientation="user"
+                  android:label="@string/class_0_message_activity"
+                  android:theme="@style/BugleTheme.DialogActivity"
+                  android:launchMode="singleTask"
+                  android:excludeFromRecents="true">
+        </activity>
+
+        <activity android:name=".ui.SmsStorageLowWarningActivity"
+                  android:theme="@style/Translucent"
+                  android:configChanges="orientation|screenSize|keyboardHidden" />
+
+        <activity android:name=".ui.appsettings.ApnSettingsActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:screenOrientation="user"
+                  android:theme="@style/BugleTheme"
+                  android:parentActivityName="com.android.messaging.ui.appsettings.SettingsActivity" />
+
+        <activity android:name=".ui.appsettings.ApnEditorActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:screenOrientation="user"
+                  android:theme="@style/BugleTheme"
+                  android:parentActivityName="com.android.messaging.ui.appsettings.ApnSettingsActivity"/>
+
+        <receiver android:name=".receiver.StorageStatusReceiver"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.DEVICE_STORAGE_OK" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name=".receiver.BootAndPackageReplacedReceiver"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+                <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
+            </intent-filter>
+        </receiver>
+
+        <!-- Broadcast receiver that will be notified to reset notifications -->
+        <receiver
+            android:name=".receiver.NotificationReceiver"
+            android:exported="false">
+        </receiver>
+
+        <!-- Broadcast receiver that will be notified for ActionService alarms. -->
+        <receiver
+            android:name=".datamodel.action.ActionServiceImpl$PendingActionReceiver"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.messaging.datamodel.PENDING_ACTION" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name=".receiver.DefaultSmsSubscriptionChangeReceiver"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED"/>
+            </intent-filter>
+        </receiver>
+
+        <!-- Widget that displays the conversation list -->
+        <receiver android:name=".widget.BugleWidgetProvider"
+                android:exported="true"
+                android:label="@string/widget_conversation_name">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.appwidget.provider"
+                       android:resource="@xml/widget_conversation_list" />
+        </receiver>
+
+        <!-- Widget that displays the messages of a single conversation -->
+        <receiver android:name=".widget.WidgetConversationProvider"
+                android:exported="true"
+                android:label="@string/widget_conversation_name">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.appwidget.provider"
+                       android:resource="@xml/widget_conversation" />
+        </receiver>
+
+        <service android:name=".widget.WidgetConversationListService"
+                 android:permission="android.permission.BIND_REMOTEVIEWS"
+                 android:exported="false" />
+
+        <service android:name=".widget.WidgetConversationService"
+                 android:permission="android.permission.BIND_REMOTEVIEWS"
+                 android:exported="false" />
+
+        <activity android:name=".ui.WidgetPickConversationActivity"
+            android:theme="@style/BugleTheme"
+                android:exported="true"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+
+        <service android:name="androidx.appcompat.mms.MmsService"/>
+    </application>
+
+</manifest>
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..79e4ced
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2017 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/messaging)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/libgiftranscode.so)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/libgiftranscode.so)
diff --git a/ForceProguard.mk b/ForceProguard.mk
new file mode 100755
index 0000000..e6f4fea
--- /dev/null
+++ b/ForceProguard.mk
@@ -0,0 +1,40 @@
+#  Copyright (C) 2015 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.
+
+# Check to see if we need to force proguard to re-run, typically after using tapas to
+# switch to/from eng builds. This is determined by comparing the flag files used in the previous
+# build. If the flag files have changed, proguard is rerun.
+
+# If the LOCAL_MODULE being setup isn't a build target, then don't run ForceProguard.
+ifneq (,$(findstring $(LOCAL_MODULE), $(TARGET_BUILD_APPS)))
+
+PREVIOUS_FLAG_FILES_USED_DIR := $(call local-intermediates-dir,1)
+
+# If the local intermediates dir doesn't exist, ForceProguard won't work.
+ifneq ($(wildcard $(PREVIOUS_FLAG_FILES_USED_DIR)),)
+PREVIOUS_FLAG_FILES_USED_FILE := $(PREVIOUS_FLAG_FILES_USED_DIR)/previous_proguard_flag_files
+PREVIOUS_FLAG_FILES_USED := $(if $(wildcard $(PREVIOUS_FLAG_FILES_USED_FILE)), \
+                                $(shell cat $(PREVIOUS_FLAG_FILES_USED_FILE)))
+
+ifneq ($(strip $(PREVIOUS_FLAG_FILES_USED)), $(strip $(LOCAL_PROGUARD_FLAG_FILES)))
+$(info *** Flag files used for proguard have changed; forcing proguard to rerun.)
+$(shell touch $(LOCAL_PATH)/proguard.flags)
+$(shell echo $(LOCAL_PROGUARD_FLAG_FILES) > $(PREVIOUS_FLAG_FILES_USED_FILE))
+endif
+
+endif
+# End local intermediates directory existence check
+
+endif
+# End LOCAL_MODULE is a build target check
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..f4ccae0
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,4 @@
+# Default code reviewers picked from top 3 or more developers.
+# Please update this list if you find better candidates.
+tomtaylor@google.com
+rtenneti@google.com
diff --git a/README b/README
new file mode 100644
index 0000000..15142ba
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+This app is not actively supported and the source is only available as a reference. This project will be removed from the source manifest sometime in the future.
+
diff --git a/assets/licenses.html b/assets/licenses.html
new file mode 100644
index 0000000..aa9c3b7
--- /dev/null
+++ b/assets/licenses.html
@@ -0,0 +1,666 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>
+</title>
+<style>
+body { font-family: sans-serif; }
+pre { background-color: #eeeeee; padding: 1em; white-space: pre-wrap; }
+</style>
+</head>
+<body>
+<h3>Notice for AOSP:</h3>
+<pre>
+    Copyright (c) 2005-2008, The Android Open Source Project
+
+       Licensed under the Apache License, Version 2.0 (the "License");
+       you may not use this file except in compliance with the License.
+
+       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.
+
+       Apache License
+       Version 2.0, January 2004
+       http://www.apache.org/licenses/
+
+       TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+       1. Definitions.
+
+          "License" shall mean the terms and conditions for use, reproduction,
+          and distribution as defined by Sections 1 through 9 of this document.
+
+          "Licensor" shall mean the copyright owner or entity authorized by
+          the copyright owner that is granting the License.
+
+          "Legal Entity" shall mean the union of the acting entity and all
+          other entities that control, are controlled by, or are under common
+          control with that entity. For the purposes of this definition,
+          "control" means (i) the power, direct or indirect, to cause the
+          direction or management of such entity, whether by contract or
+          otherwise, or (ii) ownership of fifty percent (50%) or more of the
+          outstanding shares, or (iii) beneficial ownership of such entity.
+
+          "You" (or "Your") shall mean an individual or Legal Entity
+          exercising permissions granted by this License.
+
+          "Source" form shall mean the preferred form for making modifications,
+          including but not limited to software source code, documentation
+          source, and configuration files.
+
+          "Object" form shall mean any form resulting from mechanical
+          transformation or translation of a Source form, including but
+          not limited to compiled object code, generated documentation,
+          and conversions to other media types.
+
+          "Work" shall mean the work of authorship, whether in Source or
+          Object form, made available under the License, as indicated by a
+          copyright notice that is included in or attached to the work
+          (an example is provided in the Appendix below).
+
+          "Derivative Works" shall mean any work, whether in Source or Object
+          form, that is based on (or derived from) the Work and for which the
+          editorial revisions, annotations, elaborations, or other modifications
+          represent, as a whole, an original work of authorship. For the purposes
+          of this License, Derivative Works shall not include works that remain
+          separable from, or merely link (or bind by name) to the interfaces of,
+          the Work and Derivative Works thereof.
+
+          "Contribution" shall mean any work of authorship, including
+          the original version of the Work and any modifications or additions
+          to that Work or Derivative Works thereof, that is intentionally
+          submitted to Licensor for inclusion in the Work by the copyright owner
+          or by an individual or Legal Entity authorized to submit on behalf of
+          the copyright owner. For the purposes of this definition, "submitted"
+          means any form of electronic, verbal, or written communication sent
+          to the Licensor or its representatives, including but not limited to
+          communication on electronic mailing lists, source code control systems,
+          and issue tracking systems that are managed by, or on behalf of, the
+          Licensor for the purpose of discussing and improving the Work, but
+          excluding communication that is conspicuously marked or otherwise
+          designated in writing by the copyright owner as "Not a Contribution."
+
+          "Contributor" shall mean Licensor and any individual or Legal Entity
+          on behalf of whom a Contribution has been received by Licensor and
+          subsequently incorporated within the Work.
+
+       2. Grant of Copyright License. Subject to the terms and conditions of
+          this License, each Contributor hereby grants to You a perpetual,
+          worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+          copyright license to reproduce, prepare Derivative Works of,
+          publicly display, publicly perform, sublicense, and distribute the
+          Work and such Derivative Works in Source or Object form.
+
+       3. Grant of Patent License. Subject to the terms and conditions of
+          this License, each Contributor hereby grants to You a perpetual,
+          worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+          (except as stated in this section) patent license to make, have made,
+          use, offer to sell, sell, import, and otherwise transfer the Work,
+          where such license applies only to those patent claims licensable
+          by such Contributor that are necessarily infringed by their
+          Contribution(s) alone or by combination of their Contribution(s)
+          with the Work to which such Contribution(s) was submitted. If You
+          institute patent litigation against any entity (including a
+          cross-claim or counterclaim in a lawsuit) alleging that the Work
+          or a Contribution incorporated within the Work constitutes direct
+          or contributory patent infringement, then any patent licenses
+          granted to You under this License for that Work shall terminate
+          as of the date such litigation is filed.
+
+       4. Redistribution. You may reproduce and distribute copies of the
+          Work or Derivative Works thereof in any medium, with or without
+          modifications, and in Source or Object form, provided that You
+          meet the following conditions:
+
+          (a) You must give any other recipients of the Work or
+              Derivative Works a copy of this License; and
+
+          (b) You must cause any modified files to carry prominent notices
+              stating that You changed the files; and
+
+          (c) You must retain, in the Source form of any Derivative Works
+              that You distribute, all copyright, patent, trademark, and
+              attribution notices from the Source form of the Work,
+              excluding those notices that do not pertain to any part of
+              the Derivative Works; and
+
+          (d) If the Work includes a "NOTICE" text file as part of its
+              distribution, then any Derivative Works that You distribute must
+              include a readable copy of the attribution notices contained
+              within such NOTICE file, excluding those notices that do not
+              pertain to any part of the Derivative Works, in at least one
+              of the following places: within a NOTICE text file distributed
+              as part of the Derivative Works; within the Source form or
+              documentation, if provided along with the Derivative Works; or,
+              within a display generated by the Derivative Works, if and
+              wherever such third-party notices normally appear. The contents
+              of the NOTICE file are for informational purposes only and
+              do not modify the License. You may add Your own attribution
+              notices within Derivative Works that You distribute, alongside
+              or as an addendum to the NOTICE text from the Work, provided
+              that such additional attribution notices cannot be construed
+              as modifying the License.
+
+          You may add Your own copyright statement to Your modifications and
+          may provide additional or different license terms and conditions
+          for use, reproduction, or distribution of Your modifications, or
+          for any such Derivative Works as a whole, provided Your use,
+          reproduction, and distribution of the Work otherwise complies with
+          the conditions stated in this License.
+
+       5. Submission of Contributions. Unless You explicitly state otherwise,
+          any Contribution intentionally submitted for inclusion in the Work
+          by You to the Licensor shall be under the terms and conditions of
+          this License, without any additional terms or conditions.
+          Notwithstanding the above, nothing herein shall supersede or modify
+          the terms of any separate license agreement you may have executed
+          with Licensor regarding such Contributions.
+
+       6. Trademarks. This License does not grant permission to use the trade
+          names, trademarks, service marks, or product names of the Licensor,
+          except as required for reasonable and customary use in describing the
+          origin of the Work and reproducing the content of the NOTICE file.
+
+       7. Disclaimer of Warranty. Unless required by applicable law or
+          agreed to in writing, Licensor provides the Work (and each
+          Contributor provides its Contributions) on an "AS IS" BASIS,
+          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+          implied, including, without limitation, any warranties or conditions
+          of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+          PARTICULAR PURPOSE. You are solely responsible for determining the
+          appropriateness of using or redistributing the Work and assume any
+          risks associated with Your exercise of permissions under this License.
+
+       8. Limitation of Liability. In no event and under no legal theory,
+          whether in tort (including negligence), contract, or otherwise,
+          unless required by applicable law (such as deliberate and grossly
+          negligent acts) or agreed to in writing, shall any Contributor be
+          liable to You for damages, including any direct, indirect, special,
+          incidental, or consequential damages of any character arising as a
+          result of this License or out of the use or inability to use the
+          Work (including but not limited to damages for loss of goodwill,
+          work stoppage, computer failure or malfunction, or any and all
+          other commercial damages or losses), even if such Contributor
+          has been advised of the possibility of such damages.
+
+       9. Accepting Warranty or Additional Liability. While redistributing
+          the Work or Derivative Works thereof, You may choose to offer,
+          and charge a fee for, acceptance of support, warranty, indemnity,
+          or other liability obligations and/or rights consistent with this
+          License. However, in accepting such obligations, You may act only
+          on Your own behalf and on Your sole responsibility, not on behalf
+          of any other Contributor, and only if You agree to indemnify,
+          defend, and hold each Contributor harmless for any liability
+          incurred by, or claims asserted against, such Contributor by reason
+          of your accepting any such warranty or additional liability.
+</pre>
+
+<h3>Notices for Guava: Google Core Libraries for Java</h3>
+<pre>
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+</pre>
+
+<h3>Notices for JSR 305</h3>
+<pre>
+Copyright (c) 2007-2009, JSR305 expert group
+All rights reserved.
+
+http://www.opensource.org/licenses/bsd-license.php
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of the JSR305 expert group nor the names of its
+      contributors may be used to endorse or promote products derived from
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+</pre>
+
+<h3>Notices for libphonenumber</h3>
+<pre>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+</pre>
+
+<h3>Notices for GIFLIB</h3>
+<pre>
+The GIFLIB distribution is Copyright (c) 1997  Eric S. Raymond
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</pre>
+</body></html>
diff --git a/jni/Android.bp b/jni/Android.bp
new file mode 100644
index 0000000..22840ea
--- /dev/null
+++ b/jni/Android.bp
@@ -0,0 +1,40 @@
+//  Copyright (C) 2015 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_shared {
+    name: "libgiftranscode",
+    static_libs: ["libgif"],
+    // Link to Android logging (liblog.so) and dynamic linker (libdl.so) libraries
+    shared_libs: [
+        "liblog",
+        "libdl",
+    ],
+    // for including the jni.h file
+    header_libs: ["jni_headers"],
+    include_dirs: ["external/giflib"],
+    srcs: ["GifTranscoder.cpp"],
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wno-switch",
+    ],
+    sdk_version: "19",
+    // LLVM libc++
+    stl: "c++_static",
+    product_specific: true,
+}
diff --git a/jni/GifTranscoder.cpp b/jni/GifTranscoder.cpp
new file mode 100644
index 0000000..324d315
--- /dev/null
+++ b/jni/GifTranscoder.cpp
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <jni.h>
+#include <time.h>
+#include <stdio.h>
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+
+#include "GifTranscoder.h"
+
+#define SQUARE(a) ((a)*(a))
+
+// GIF does not support partial transparency, so our alpha channels are always 0x0 or 0xff.
+static const ColorARGB TRANSPARENT = 0x0;
+
+#define ALPHA(color) (((color) >> 24) & 0xff)
+#define RED(color)   (((color) >> 16) & 0xff)
+#define GREEN(color) (((color) >>  8) & 0xff)
+#define BLUE(color)  (((color) >>  0) & 0xff)
+
+#define MAKE_COLOR_ARGB(a, r, g, b) \
+    ((a) << 24 | (r) << 16 | (g) << 8 | (b))
+
+#define MAX_COLOR_DISTANCE (255 * 255 * 255)
+
+#define TAG "GifTranscoder.cpp"
+#define LOGD_ENABLED 0
+#if LOGD_ENABLED
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__))
+#else
+#define LOGD(...) ((void)0)
+#endif
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__))
+
+// This macro expects the assertion to pass, but logs a FATAL if not.
+#define ASSERT(cond, ...) \
+    ( (__builtin_expect((cond) == 0, 0)) \
+    ? ((void)__android_log_assert(#cond, TAG, ## __VA_ARGS__)) \
+    : (void) 0 )
+#define ASSERT_ENABLED 1
+
+namespace {
+
+// Current time in milliseconds since Unix epoch.
+double now(void) {
+    struct timespec res;
+    clock_gettime(CLOCK_REALTIME, &res);
+    return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
+}
+
+// Gets the pixel at position (x,y) from a buffer that uses row-major order to store an image with
+// the specified width.
+template <typename T>
+T* getPixel(T* buffer, int width, int x, int y) {
+    return buffer + (y * width + x);
+}
+
+} // namespace
+
+int GifTranscoder::transcode(const char* pathIn, const char* pathOut) {
+    int error;
+    double t0;
+    GifFileType* gifIn;
+    GifFileType* gifOut;
+
+    // Automatically closes the GIF files when this method returns
+    GifFilesCloser closer;
+
+    gifIn = DGifOpenFileName(pathIn, &error);
+    if (gifIn) {
+        closer.setGifIn(gifIn);
+        LOGD("Opened input GIF: %s", pathIn);
+    } else {
+        LOGE("Could not open input GIF: %s, error = %d", pathIn, error);
+        return GIF_ERROR;
+    }
+
+    gifOut = EGifOpenFileName(pathOut, false, &error);
+    if (gifOut) {
+        closer.setGifOut(gifOut);
+        LOGD("Opened output GIF: %s", pathOut);
+    } else {
+        LOGE("Could not open output GIF: %s, error = %d", pathOut, error);
+        return GIF_ERROR;
+    }
+
+    t0 = now();
+    if (resizeBoxFilter(gifIn, gifOut)) {
+        LOGD("Resized GIF in %.2f ms", now() - t0);
+    } else {
+        LOGE("Could not resize GIF");
+        return GIF_ERROR;
+    }
+
+    return GIF_OK;
+}
+
+bool GifTranscoder::resizeBoxFilter(GifFileType* gifIn, GifFileType* gifOut) {
+    ASSERT(gifIn != NULL, "gifIn cannot be NULL");
+    ASSERT(gifOut != NULL, "gifOut cannot be NULL");
+
+    if (gifIn->SWidth < 0 || gifIn->SHeight < 0) {
+        LOGE("Input GIF has invalid size: %d x %d", gifIn->SWidth, gifIn->SHeight);
+        return false;
+    }
+
+    // Output GIF will be 50% the size of the original.
+    if (EGifPutScreenDesc(gifOut,
+                          gifIn->SWidth / 2,
+                          gifIn->SHeight / 2,
+                          gifIn->SColorResolution,
+                          gifIn->SBackGroundColor,
+                          gifIn->SColorMap) == GIF_ERROR) {
+        LOGE("Could not write screen descriptor");
+        return false;
+    }
+    LOGD("Wrote screen descriptor");
+
+    // Index of the current image.
+    int imageIndex = 0;
+
+    // Transparent color of the current image.
+    int transparentColor = NO_TRANSPARENT_COLOR;
+
+    // Buffer for reading raw images from the input GIF.
+    std::vector<GifByteType> srcBuffer(gifIn->SWidth * gifIn->SHeight);
+
+    // Buffer for rendering images from the input GIF.
+    std::unique_ptr<ColorARGB[]> renderBuffer(new ColorARGB[gifIn->SWidth * gifIn->SHeight]);
+
+    // Buffer for writing new images to output GIF (one row at a time).
+    std::unique_ptr<GifByteType[]> dstRowBuffer(new GifByteType[gifOut->SWidth]);
+
+    // Many GIFs use DISPOSE_DO_NOT to make images draw on top of previous images. They can also
+    // use DISPOSE_BACKGROUND to clear the last image region before drawing the next one. We need
+    // to keep track of the disposal mode as we go along to properly render the GIF.
+    int disposalMode = DISPOSAL_UNSPECIFIED;
+    int prevImageDisposalMode = DISPOSAL_UNSPECIFIED;
+    GifImageDesc prevImageDimens;
+
+    // Background color (applies to entire GIF).
+    ColorARGB bgColor = TRANSPARENT;
+
+    GifRecordType recordType;
+    do {
+        if (DGifGetRecordType(gifIn, &recordType) == GIF_ERROR) {
+            LOGE("Could not get record type");
+            return false;
+        }
+        LOGD("Read record type: %d", recordType);
+        switch (recordType) {
+            case IMAGE_DESC_RECORD_TYPE: {
+                if (DGifGetImageDesc(gifIn) == GIF_ERROR) {
+                    LOGE("Could not read image descriptor (%d)", imageIndex);
+                    return false;
+                }
+
+                // Check the current image position.
+                if (gifIn->Image.Left < 0 ||
+                        gifIn->Image.Top < 0 ||
+                        gifIn->Image.Left + gifIn->Image.Width > gifIn->SWidth ||
+                        gifIn->Image.Top + gifIn->Image.Height > gifIn->SHeight) {
+                    LOGE("GIF image extends beyond logical screen");
+                    return false;
+                }
+
+                // Write the new image descriptor.
+                if (EGifPutImageDesc(gifOut,
+                                     0, // Left
+                                     0, // Top
+                                     gifOut->SWidth,
+                                     gifOut->SHeight,
+                                     false, // Interlace
+                                     gifIn->Image.ColorMap) == GIF_ERROR) {
+                    LOGE("Could not write image descriptor (%d)", imageIndex);
+                    return false;
+                }
+
+                // Read the image from the input GIF. The buffer is already initialized to the
+                // size of the GIF, which is usually equal to the size of all the images inside it.
+                // If not, the call to resize below ensures that the buffer is the right size.
+                srcBuffer.resize(gifIn->Image.Width * gifIn->Image.Height);
+                if (readImage(gifIn, srcBuffer.data()) == false) {
+                    LOGE("Could not read image data (%d)", imageIndex);
+                    return false;
+                }
+                LOGD("Read image data (%d)", imageIndex);
+                // Render the image from the input GIF.
+                if (renderImage(gifIn,
+                                srcBuffer.data(),
+                                imageIndex,
+                                transparentColor,
+                                renderBuffer.get(),
+                                bgColor,
+                                prevImageDimens,
+                                prevImageDisposalMode) == false) {
+                    LOGE("Could not render %d", imageIndex);
+                    return false;
+                }
+                LOGD("Rendered image (%d)", imageIndex);
+
+                // Generate the image in the output GIF.
+                for (int y = 0; y < gifOut->SHeight; y++) {
+                    for (int x = 0; x < gifOut->SWidth; x++) {
+                      const GifByteType dstColorIndex = computeNewColorIndex(
+                          gifIn, transparentColor, renderBuffer.get(), x, y);
+                      *(dstRowBuffer.get() + x) = dstColorIndex;
+                    }
+                    if (EGifPutLine(gifOut, dstRowBuffer.get(), gifOut->SWidth) == GIF_ERROR) {
+                        LOGE("Could not write raster data (%d)", imageIndex);
+                        return false;
+                    }
+                }
+                LOGD("Wrote raster data (%d)", imageIndex);
+
+                // Save the disposal mode for rendering the next image.
+                // We only support DISPOSE_DO_NOT and DISPOSE_BACKGROUND.
+                prevImageDisposalMode = disposalMode;
+                if (prevImageDisposalMode == DISPOSAL_UNSPECIFIED) {
+                    prevImageDisposalMode = DISPOSE_DO_NOT;
+                } else if (prevImageDisposalMode == DISPOSE_PREVIOUS) {
+                    prevImageDisposalMode = DISPOSE_BACKGROUND;
+                }
+                if (prevImageDisposalMode == DISPOSE_BACKGROUND) {
+                    prevImageDimens.Left = gifIn->Image.Left;
+                    prevImageDimens.Top = gifIn->Image.Top;
+                    prevImageDimens.Width = gifIn->Image.Width;
+                    prevImageDimens.Height = gifIn->Image.Height;
+                }
+
+                if (gifOut->Image.ColorMap) {
+                    GifFreeMapObject(gifOut->Image.ColorMap);
+                    gifOut->Image.ColorMap = NULL;
+                }
+
+                imageIndex++;
+            } break;
+            case EXTENSION_RECORD_TYPE: {
+                int extCode;
+                GifByteType* ext;
+                if (DGifGetExtension(gifIn, &extCode, &ext) == GIF_ERROR) {
+                    LOGE("Could not read extension block");
+                    return false;
+                }
+                LOGD("Read extension block, code: %d", extCode);
+                if (extCode == GRAPHICS_EXT_FUNC_CODE) {
+                    GraphicsControlBlock gcb;
+                    if (DGifExtensionToGCB(ext[0], ext + 1, &gcb) == GIF_ERROR) {
+                        LOGE("Could not interpret GCB extension");
+                        return false;
+                    }
+                    transparentColor = gcb.TransparentColor;
+
+                    // This logic for setting the background color based on the first GCB
+                    // doesn't quite match the GIF spec, but empirically it seems to work and it
+                    // matches what libframesequence (Rastermill) does.
+                    if (imageIndex == 0 && gifIn->SColorMap) {
+                        if (gcb.TransparentColor == NO_TRANSPARENT_COLOR) {
+                            if (gifIn->SBackGroundColor < 0 ||
+                                gifIn->SBackGroundColor >= gifIn->SColorMap->ColorCount) {
+                                LOGE("SBackGroundColor overflow");
+                                return false;
+                            }
+                            GifColorType bgColorIndex =
+                                    gifIn->SColorMap->Colors[gifIn->SBackGroundColor];
+                            bgColor = gifColorToColorARGB(bgColorIndex);
+                            LOGD("Set background color based on first GCB");
+                        }
+                    }
+
+                    // Record the original disposal mode and then update it.
+                    disposalMode = gcb.DisposalMode;
+                    gcb.DisposalMode = DISPOSE_BACKGROUND;
+                    EGifGCBToExtension(&gcb, ext + 1);
+                }
+                if (EGifPutExtensionLeader(gifOut, extCode) == GIF_ERROR) {
+                    LOGE("Could not write extension leader");
+                    return false;
+                }
+                if (EGifPutExtensionBlock(gifOut, ext[0], ext + 1) == GIF_ERROR) {
+                    LOGE("Could not write extension block");
+                    return false;
+                }
+                LOGD("Wrote extension block");
+                while (ext != NULL) {
+                    if (DGifGetExtensionNext(gifIn, &ext) == GIF_ERROR) {
+                        LOGE("Could not read extension continuation");
+                        return false;
+                    }
+                    if (ext != NULL) {
+                        LOGD("Read extension continuation");
+                        if (EGifPutExtensionBlock(gifOut, ext[0], ext + 1) == GIF_ERROR) {
+                            LOGE("Could not write extension continuation");
+                            return false;
+                        }
+                        LOGD("Wrote extension continuation");
+                    }
+                }
+                if (EGifPutExtensionTrailer(gifOut) == GIF_ERROR) {
+                    LOGE("Could not write extension trailer");
+                    return false;
+                }
+            } break;
+        }
+
+    } while (recordType != TERMINATE_RECORD_TYPE);
+    LOGD("No more records");
+
+    return true;
+}
+
+bool GifTranscoder::readImage(GifFileType* gifIn, GifByteType* rasterBits) {
+    if (gifIn->Image.Interlace) {
+        int interlacedOffset[] = { 0, 4, 2, 1 };
+        int interlacedJumps[] = { 8, 8, 4, 2 };
+
+        // Need to perform 4 passes on the image
+        for (int i = 0; i < 4; i++) {
+            for (int j = interlacedOffset[i]; j < gifIn->Image.Height; j += interlacedJumps[i]) {
+                if (DGifGetLine(gifIn,
+                                rasterBits + j * gifIn->Image.Width,
+                                gifIn->Image.Width) == GIF_ERROR) {
+                    LOGE("Could not read interlaced raster data");
+                    return false;
+                }
+            }
+        }
+    } else {
+        if (DGifGetLine(gifIn, rasterBits, gifIn->Image.Width * gifIn->Image.Height) == GIF_ERROR) {
+            LOGE("Could not read raster data");
+            return false;
+        }
+    }
+    return true;
+}
+
+bool GifTranscoder::renderImage(GifFileType* gifIn,
+                                GifByteType* rasterBits,
+                                int imageIndex,
+                                int transparentColorIndex,
+                                ColorARGB* renderBuffer,
+                                ColorARGB bgColor,
+                                GifImageDesc prevImageDimens,
+                                int prevImageDisposalMode) {
+    ASSERT(imageIndex < gifIn->ImageCount,
+           "Image index %d is out of bounds (count=%d)", imageIndex, gifIn->ImageCount);
+
+    ColorMapObject* colorMap = getColorMap(gifIn);
+    if (colorMap == NULL) {
+        LOGE("No GIF color map found");
+        return false;
+    }
+
+    // Clear all or part of the background, before drawing the first image and maybe before drawing
+    // subsequent images (depending on the DisposalMode).
+    if (imageIndex == 0) {
+        fillRect(renderBuffer, gifIn->SWidth, gifIn->SHeight,
+                 0, 0, gifIn->SWidth, gifIn->SHeight, bgColor);
+    } else if (prevImageDisposalMode == DISPOSE_BACKGROUND) {
+        fillRect(renderBuffer, gifIn->SWidth, gifIn->SHeight,
+                 prevImageDimens.Left, prevImageDimens.Top,
+                 prevImageDimens.Width, prevImageDimens.Height, TRANSPARENT);
+    }
+
+    // Paint this image onto the canvas
+    for (int y = 0; y < gifIn->Image.Height; y++) {
+        for (int x = 0; x < gifIn->Image.Width; x++) {
+            GifByteType colorIndex = *getPixel(rasterBits, gifIn->Image.Width, x, y);
+            if (colorIndex >= colorMap->ColorCount) {
+                LOGE("Color Index %d is out of bounds (count=%d)", colorIndex,
+                    colorMap->ColorCount);
+                return false;
+            }
+
+            // This image may be smaller than the GIF's "logical screen"
+            int renderX = x + gifIn->Image.Left;
+            int renderY = y + gifIn->Image.Top;
+
+            // Skip drawing transparent pixels if this image renders on top of the last one
+            if (imageIndex > 0 && prevImageDisposalMode == DISPOSE_DO_NOT &&
+                colorIndex == transparentColorIndex) {
+                continue;
+            }
+
+            ColorARGB* renderPixel = getPixel(renderBuffer, gifIn->SWidth, renderX, renderY);
+            *renderPixel = getColorARGB(colorMap, transparentColorIndex, colorIndex);
+        }
+    }
+    return true;
+}
+
+void GifTranscoder::fillRect(ColorARGB* renderBuffer,
+                             int imageWidth,
+                             int imageHeight,
+                             int left,
+                             int top,
+                             int width,
+                             int height,
+                             ColorARGB color) {
+    ASSERT(left + width <= imageWidth, "Rectangle is outside image bounds");
+    ASSERT(top + height <= imageHeight, "Rectangle is outside image bounds");
+
+    for (int y = 0; y < height; y++) {
+        for (int x = 0; x < width; x++) {
+            ColorARGB* renderPixel = getPixel(renderBuffer, imageWidth, x + left, y + top);
+            *renderPixel = color;
+        }
+    }
+}
+
+GifByteType GifTranscoder::computeNewColorIndex(GifFileType* gifIn,
+                                                int transparentColorIndex,
+                                                ColorARGB* renderBuffer,
+                                                int x,
+                                                int y) {
+    ColorMapObject* colorMap = getColorMap(gifIn);
+
+    // Compute the average color of 4 adjacent pixels from the input image.
+    ColorARGB c1 = *getPixel(renderBuffer, gifIn->SWidth, x * 2, y * 2);
+    ColorARGB c2 = *getPixel(renderBuffer, gifIn->SWidth, x * 2 + 1, y * 2);
+    ColorARGB c3 = *getPixel(renderBuffer, gifIn->SWidth, x * 2, y * 2 + 1);
+    ColorARGB c4 = *getPixel(renderBuffer, gifIn->SWidth, x * 2 + 1, y * 2 + 1);
+    ColorARGB avgColor = computeAverage(c1, c2, c3, c4);
+
+    // Search the color map for the best match.
+    return findBestColor(colorMap, transparentColorIndex, avgColor);
+}
+
+ColorARGB GifTranscoder::computeAverage(ColorARGB c1, ColorARGB c2, ColorARGB c3, ColorARGB c4) {
+    char avgAlpha = (char)(((int) ALPHA(c1) + (int) ALPHA(c2) +
+                            (int) ALPHA(c3) + (int) ALPHA(c4)) / 4);
+    char avgRed =   (char)(((int) RED(c1) + (int) RED(c2) +
+                            (int) RED(c3) + (int) RED(c4)) / 4);
+    char avgGreen = (char)(((int) GREEN(c1) + (int) GREEN(c2) +
+                            (int) GREEN(c3) + (int) GREEN(c4)) / 4);
+    char avgBlue =  (char)(((int) BLUE(c1) + (int) BLUE(c2) +
+                            (int) BLUE(c3) + (int) BLUE(c4)) / 4);
+    return MAKE_COLOR_ARGB(avgAlpha, avgRed, avgGreen, avgBlue);
+}
+
+GifByteType GifTranscoder::findBestColor(ColorMapObject* colorMap, int transparentColorIndex,
+                                         ColorARGB targetColor) {
+    // Return the transparent color if the average alpha is zero.
+    char alpha = ALPHA(targetColor);
+    if (alpha == 0 && transparentColorIndex != NO_TRANSPARENT_COLOR) {
+        return transparentColorIndex;
+    }
+
+    GifByteType closestColorIndex = 0;
+    int closestColorDistance = MAX_COLOR_DISTANCE;
+    for (int i = 0; i < colorMap->ColorCount; i++) {
+        // Skip the transparent color (we've already eliminated that option).
+        if (i == transparentColorIndex) {
+            continue;
+        }
+        ColorARGB indexedColor = gifColorToColorARGB(colorMap->Colors[i]);
+        int distance = computeDistance(targetColor, indexedColor);
+        if (distance < closestColorDistance) {
+            closestColorIndex = i;
+            closestColorDistance = distance;
+        }
+    }
+    return closestColorIndex;
+}
+
+int GifTranscoder::computeDistance(ColorARGB c1, ColorARGB c2) {
+    return SQUARE(RED(c1) - RED(c2)) +
+           SQUARE(GREEN(c1) - GREEN(c2)) +
+           SQUARE(BLUE(c1) - BLUE(c2));
+}
+
+ColorMapObject* GifTranscoder::getColorMap(GifFileType* gifIn) {
+    if (gifIn->Image.ColorMap) {
+        return gifIn->Image.ColorMap;
+    }
+    return gifIn->SColorMap;
+}
+
+ColorARGB GifTranscoder::getColorARGB(ColorMapObject* colorMap, int transparentColorIndex,
+                                      GifByteType colorIndex) {
+    if (colorIndex == transparentColorIndex) {
+        return TRANSPARENT;
+    }
+    return gifColorToColorARGB(colorMap->Colors[colorIndex]);
+}
+
+ColorARGB GifTranscoder::gifColorToColorARGB(const GifColorType& color) {
+    return MAKE_COLOR_ARGB(0xff, color.Red, color.Green, color.Blue);
+}
+
+GifFilesCloser::~GifFilesCloser() {
+    if (mGifIn) {
+        DGifCloseFile(mGifIn, NULL);
+        mGifIn = NULL;
+    }
+    if (mGifOut) {
+        EGifCloseFile(mGifOut, NULL);
+        mGifOut = NULL;
+    }
+}
+
+void GifFilesCloser::setGifIn(GifFileType* gifIn) {
+    ASSERT(mGifIn == NULL, "mGifIn is already set");
+    mGifIn = gifIn;
+}
+
+void GifFilesCloser::releaseGifIn() {
+    ASSERT(mGifIn != NULL, "mGifIn is already NULL");
+    mGifIn = NULL;
+}
+
+void GifFilesCloser::setGifOut(GifFileType* gifOut) {
+    ASSERT(mGifOut == NULL, "mGifOut is already set");
+    mGifOut = gifOut;
+}
+
+void GifFilesCloser::releaseGifOut() {
+    ASSERT(mGifOut != NULL, "mGifOut is already NULL");
+    mGifOut = NULL;
+}
+
+// JNI stuff
+
+jboolean transcode(JNIEnv* env, jobject clazz, jstring filePath, jstring outFilePath) {
+    const char* pathIn = env->GetStringUTFChars(filePath, JNI_FALSE);
+    const char* pathOut = env->GetStringUTFChars(outFilePath, JNI_FALSE);
+
+    GifTranscoder transcoder;
+    int gifCode = transcoder.transcode(pathIn, pathOut);
+
+    env->ReleaseStringUTFChars(filePath, pathIn);
+    env->ReleaseStringUTFChars(outFilePath, pathOut);
+
+    return (gifCode == GIF_OK);
+}
+
+const char *kClassPathName = "com/android/messaging/util/GifTranscoder";
+
+JNINativeMethod kMethods[] = {
+        { "transcodeInternal", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)transcode },
+};
+
+int registerNativeMethods(JNIEnv* env, const char* className,
+                          JNINativeMethod* gMethods, int numMethods) {
+    jclass clazz = env->FindClass(className);
+    if (clazz == NULL) {
+        return JNI_FALSE;
+    }
+    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return -1;
+    }
+    if (!registerNativeMethods(env, kClassPathName,
+                               kMethods, sizeof(kMethods) / sizeof(kMethods[0]))) {
+      return -1;
+    }
+    return JNI_VERSION_1_6;
+}
diff --git a/jni/GifTranscoder.h b/jni/GifTranscoder.h
new file mode 100644
index 0000000..39ecc24
--- /dev/null
+++ b/jni/GifTranscoder.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GIF_TRANSCODER_H
+#define GIF_TRANSCODER_H
+
+#include <sys/types.h>
+
+#include "gif_lib.h"
+
+// 24-bit color with alpha, stored in order: A, R, G, B.
+// The internal GIF render buffer stores pixels using this format.
+typedef uint32_t ColorARGB;
+
+// Compresses a GIF (probably animated) so it can be sent via MMS, which generally has a 1 MB limit
+// on attachments. GIF image data is already compressed (LZW), so to achieve further reduction in
+// file size, we reduce the image dimensions.
+//
+// Helpful GIF references:
+// GIF89A spec: http://www.w3.org/Graphics/GIF/spec-gif89a.txt
+// What's in a GIF: http://giflib.sourceforge.net/whatsinagif/index.html
+//
+class GifTranscoder {
+public:
+    GifTranscoder() {}
+    ~GifTranscoder() {}
+
+    // Resizes a GIF's width and height to 50% of their original dimensions. The new file is
+    // written to pathOut.
+    //
+    // The image is resized using a box filter, which averages the colors in each 2x2 box of pixels
+    // in the source to generate the color of the pixel in the destination.
+    //
+    // Returns GIF_OK (1) on success, or GIF_ERROR (0) on failure.
+    int transcode(const char* pathIn, const char* pathOut);
+
+private:
+    // Implementation of the box filter algorithm.
+    static bool resizeBoxFilter(GifFileType* gifIn, GifFileType* gifOut);
+
+    // Reads the raster data for the current image of the GIF.
+    static bool readImage(GifFileType* gifIn, GifByteType* rasterBits);
+
+    // Renders the current image of the GIF into the supplied render buffer.
+    static bool renderImage(GifFileType* gifIn,
+                            GifByteType* rasterBits,
+                            int imageIndex,
+                            int transparentColorIndex,
+                            ColorARGB* renderBuffer,
+                            ColorARGB bgColor,
+                            GifImageDesc prevImageDimens,
+                            int prevImageDisposalMode);
+
+    // Fills a rectangle in the buffer with a solid color.
+    static void fillRect(ColorARGB* renderBuffer,
+                         int imageWidth,
+                         int imageHeight,
+                         int left,
+                         int top,
+                         int width,
+                         int height,
+                         ColorARGB color);
+
+    // Computes the color for the pixel (x,y) in the current image in the output GIF.
+    static GifByteType computeNewColorIndex(GifFileType* gifIn,
+                                            int transparentColorIndex,
+                                            ColorARGB* renderBuffer,
+                                            int x,
+                                            int y);
+
+    // Computes the average color (by averaging the per-channel (ARGB) values).
+    static ColorARGB computeAverage(ColorARGB c1, ColorARGB c2, ColorARGB c3, ColorARGB c4);
+
+    // Searches a color map for the color closest (Euclidean distance) to the target color.
+    static GifByteType findBestColor(ColorMapObject* colorMap, int transparentColorIndex,
+                                     ColorARGB targetColor);
+
+    // Computes distance (squared) between 2 colors, considering each channel a separate dimension.
+    static int computeDistance(ColorARGB c1, ColorARGB c2);
+
+    // Returns the local color map of the current image (if any), or else the global color map.
+    static ColorMapObject* getColorMap(GifFileType* gifIn);
+
+    // Returns an indexed color from the color map.
+    static ColorARGB getColorARGB(ColorMapObject* colorMap, int transparentColorIndex,
+                                  GifByteType colorIndex);
+
+    // Converts a 24-bit GIF color (RGB) to a 32-bit ARGB color.
+    static ColorARGB gifColorToColorARGB(const GifColorType& color);
+};
+
+// Wrapper class that automatically closes the GIF files when the wrapper goes out of scope.
+class GifFilesCloser {
+public:
+    GifFilesCloser() {}
+    ~GifFilesCloser();
+
+    void setGifIn(GifFileType* gifIn);
+    void releaseGifIn();
+
+    void setGifOut(GifFileType* gifOut);
+    void releaseGifOut();
+
+private:
+    GifFileType* mGifIn = NULL;
+    GifFileType* mGifOut = NULL;
+};
+
+#endif // GIF_TRANSCODER_H
diff --git a/proguard-release.flags b/proguard-release.flags
new file mode 100644
index 0000000..67ae150
--- /dev/null
+++ b/proguard-release.flags
@@ -0,0 +1,26 @@
+#  Copyright (C) 2015 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.
+
+-keep class com.android.messaging.ui.contact.* { *; }
+
+-assumenosideeffects public class com.android.messaging.util.Trace {
+    public void beginSection(...);
+    public void endSection(...);
+}
+-assumenosideeffects public class com.android.messaging.util.Assert {
+    private void setIfEngBuild();
+}
+-assumenosideeffects public class com.android.messaging.util.DebugUtils {
+    public void logCurrentMethod(...);
+}
diff --git a/proguard-test.flags b/proguard-test.flags
new file mode 100755
index 0000000..50f69a2
--- /dev/null
+++ b/proguard-test.flags
@@ -0,0 +1,41 @@
+#  Copyright (C) 2015 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.
+#
+# These flags are in addition to the one in proguard.flags, which is included by the build
+# directives in Android.mk.
+
+-dontobfuscate
+-dontoptimize
+
+# FLAG(dnotario): Until we rationalize how to handle tests (extensive unit tests will want similar
+# settings to these, but maybe we want to require VisibleForTesting attribute), just expose all
+# non-private methods. This means we cannot run tests on user builds for the moment.
+-keep class com.android.messaging.* {
+  !private *;
+}
+
+-keep class com.android.messaging.*.* {
+  !private *;
+}
+
+-keep class com.android.messaging.*.*.* {
+  !private *;
+}
+
+-keep class com.android.messaging.ui.*.* { *; }
+
+# Keep the classes needed by emma
+-keep class com.vladium.** { *; }
+
+# End of Test Rules
diff --git a/proguard.flags b/proguard.flags
new file mode 100644
index 0000000..c5bbb42
--- /dev/null
+++ b/proguard.flags
@@ -0,0 +1,64 @@
+#  Copyright (C) 2015 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.
+#
+# Keep enough data for stack traces
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable,*Annotation*
+
+# Keep classes and methods that have the guava @VisibleForTesting annotation
+-keep @com.google.common.annotations.VisibleForTesting class *
+-keepclassmembers class * {
+  @com.google.common.annotations.VisibleForTesting *;
+}
+-keep class com.android.messaging.* { *; }
+-keep class com.android.messaging.*.* { *; }
+-keep class com.android.messaging.*.*.* { *; }
+
+# Keep methods that have the @VisibleForAnimation annotation
+-keep @interface com.android.messaging.annotation.VisibleForAnimation
+-keepclassmembers class * {
+  @com.android.messaging.annotation.VisibleForAnimation *;
+}
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class * extends androidx.fragment.app.Fragment
+-keep public class com.android.vcard.* { *; }
+
+-keep class androidx.collection.* { *; }
+-keep class androidx.core.* { *; }
+-keep class androidx.core.*.* { *; }
+-keep class androidx.appcompat.* { *; }
+-keep class androidx.appcompat.*.* { *; }
+-keep class androidx.recyclerview.widget.* { *; }
+-keep class androidx.viewpager.widget.* { *; }
+
+# Keep rastermill classes that need to be accessed from native code (JNI)
+-keep class android.support.rastermill.** { *; }
+
+# Preserve the name of the getCaller method so it can find itself in the stack trace it generates
+-keepclassmembers public class com.android.messaging.util.DebugUtils {
+  public static java.lang.StackTraceElement getCaller(...);
+}
+
+# Keep the static fields of referenced inner classes of auto-generated R classes, in case we
+# access those fields by reflection (e.g. EmojiMarkup)
+-keepclassmembers class **.R$* {
+    public static <fields>;
+}
diff --git a/res/animator/fab_anim.xml b/res/animator/fab_anim.xml
new file mode 100644
index 0000000..e06416e
--- /dev/null
+++ b/res/animator/fab_anim.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:state_enabled="true"
+        android:state_pressed="true">
+        <objectAnimator
+            android:duration="@android:integer/config_shortAnimTime"
+            android:propertyName="translationZ"
+            android:valueTo="@dimen/fab_elevation_pressed"
+            android:valueType="floatType" />
+    </item>
+
+    <item>
+        <objectAnimator
+            android:duration="@android:integer/config_shortAnimTime"
+            android:propertyName="translationZ"
+            android:valueTo="@dimen/fab_elevation"
+            android:valueType="floatType" />
+    </item>
+
+</selector>
diff --git a/res/color/tab_text_color.xml b/res/color/tab_text_color.xml
new file mode 100644
index 0000000..dec20dd
--- /dev/null
+++ b/res/color/tab_text_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:color="@android:color/white"
+        android:state_selected="true"/>
+    <item
+        android:color="@color/translucent_white" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable-hdpi/contact_popup_background.9.png b/res/drawable-hdpi/contact_popup_background.9.png
new file mode 100644
index 0000000..060ffad
--- /dev/null
+++ b/res/drawable-hdpi/contact_popup_background.9.png
Binary files differ
diff --git a/res/drawable-hdpi/fab_new_message_static_shadow.png b/res/drawable-hdpi/fab_new_message_static_shadow.png
new file mode 100644
index 0000000..22e1764
--- /dev/null
+++ b/res/drawable-hdpi/fab_new_message_static_shadow.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_add_white.png b/res/drawable-hdpi/ic_add_white.png
new file mode 100644
index 0000000..b52309f
--- /dev/null
+++ b/res/drawable-hdpi/ic_add_white.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_archive_small_dark.png b/res/drawable-hdpi/ic_archive_small_dark.png
new file mode 100644
index 0000000..b679ebb
--- /dev/null
+++ b/res/drawable-hdpi/ic_archive_small_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_archive_undo_small_dark.png b/res/drawable-hdpi/ic_archive_undo_small_dark.png
new file mode 100644
index 0000000..505988d
--- /dev/null
+++ b/res/drawable-hdpi/ic_archive_undo_small_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_arrow_back_light.png b/res/drawable-hdpi/ic_arrow_back_light.png
new file mode 100644
index 0000000..fa1f67b
--- /dev/null
+++ b/res/drawable-hdpi/ic_arrow_back_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_attachment_dark.png b/res/drawable-hdpi/ic_attachment_dark.png
new file mode 100644
index 0000000..10a1028
--- /dev/null
+++ b/res/drawable-hdpi/ic_attachment_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_audio_light.png b/res/drawable-hdpi/ic_audio_light.png
new file mode 100644
index 0000000..9605a5c
--- /dev/null
+++ b/res/drawable-hdpi/ic_audio_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_audio_pause.png b/res/drawable-hdpi/ic_audio_pause.png
new file mode 100644
index 0000000..8797ad0
--- /dev/null
+++ b/res/drawable-hdpi/ic_audio_pause.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_audio_play.png b/res/drawable-hdpi/ic_audio_play.png
new file mode 100644
index 0000000..552dc9c
--- /dev/null
+++ b/res/drawable-hdpi/ic_audio_play.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_camera_front_light.png b/res/drawable-hdpi/ic_camera_front_light.png
new file mode 100644
index 0000000..c0ddaf6
--- /dev/null
+++ b/res/drawable-hdpi/ic_camera_front_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_camera_light.png b/res/drawable-hdpi/ic_camera_light.png
new file mode 100644
index 0000000..d0406e4
--- /dev/null
+++ b/res/drawable-hdpi/ic_camera_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_camera_rear_light.png b/res/drawable-hdpi/ic_camera_rear_light.png
new file mode 100644
index 0000000..6624c55
--- /dev/null
+++ b/res/drawable-hdpi/ic_camera_rear_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_cancel_small_dark.png b/res/drawable-hdpi/ic_cancel_small_dark.png
new file mode 100644
index 0000000..5de5cfb
--- /dev/null
+++ b/res/drawable-hdpi/ic_cancel_small_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_cancel_small_light.png b/res/drawable-hdpi/ic_cancel_small_light.png
new file mode 100644
index 0000000..05c6b19
--- /dev/null
+++ b/res/drawable-hdpi/ic_cancel_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkbox_blank_light.png b/res/drawable-hdpi/ic_checkbox_blank_light.png
new file mode 100644
index 0000000..879a770
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkbox_blank_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkbox_light.png b/res/drawable-hdpi/ic_checkbox_light.png
new file mode 100644
index 0000000..e41ba42
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkbox_outline_light.png b/res/drawable-hdpi/ic_checkbox_outline_light.png
new file mode 100644
index 0000000..44ed34e
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkbox_outline_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_circle_blue.png b/res/drawable-hdpi/ic_checkmark_circle_blue.png
new file mode 100644
index 0000000..7932c30
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_large.png b/res/drawable-hdpi/ic_checkmark_large.png
new file mode 100644
index 0000000..b8ecc06
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkmark_large.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_large_light.png b/res/drawable-hdpi/ic_checkmark_large_light.png
new file mode 100644
index 0000000..48bf283
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkmark_large_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_small_light.png b/res/drawable-hdpi/ic_checkmark_small_light.png
new file mode 100644
index 0000000..ae0bf6d
--- /dev/null
+++ b/res/drawable-hdpi/ic_checkmark_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_content_copy_dark.png b/res/drawable-hdpi/ic_content_copy_dark.png
new file mode 100644
index 0000000..22d2516
--- /dev/null
+++ b/res/drawable-hdpi/ic_content_copy_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_delete_small_dark.png b/res/drawable-hdpi/ic_delete_small_dark.png
new file mode 100644
index 0000000..901f992
--- /dev/null
+++ b/res/drawable-hdpi/ic_delete_small_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dnd_on_dark.png b/res/drawable-hdpi/ic_dnd_on_dark.png
new file mode 100644
index 0000000..181df02
--- /dev/null
+++ b/res/drawable-hdpi/ic_dnd_on_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_failed_light.png b/res/drawable-hdpi/ic_failed_light.png
new file mode 100644
index 0000000..3614fbe
--- /dev/null
+++ b/res/drawable-hdpi/ic_failed_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_failed_status_red.png b/res/drawable-hdpi/ic_failed_status_red.png
new file mode 100644
index 0000000..aa2d138
--- /dev/null
+++ b/res/drawable-hdpi/ic_failed_status_red.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_file_download_dark.png b/res/drawable-hdpi/ic_file_download_dark.png
new file mode 100644
index 0000000..028c85e
--- /dev/null
+++ b/res/drawable-hdpi/ic_file_download_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_file_download_light.png b/res/drawable-hdpi/ic_file_download_light.png
new file mode 100644
index 0000000..ffa5b82
--- /dev/null
+++ b/res/drawable-hdpi/ic_file_download_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_forward_dark.png b/res/drawable-hdpi/ic_forward_dark.png
new file mode 100644
index 0000000..e8b718a
--- /dev/null
+++ b/res/drawable-hdpi/ic_forward_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_image_light.png b/res/drawable-hdpi/ic_image_light.png
new file mode 100644
index 0000000..744f920
--- /dev/null
+++ b/res/drawable-hdpi/ic_image_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ime_light.png b/res/drawable-hdpi/ic_ime_light.png
new file mode 100644
index 0000000..da65039
--- /dev/null
+++ b/res/drawable-hdpi/ic_ime_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_info_dark.png b/res/drawable-hdpi/ic_info_dark.png
new file mode 100644
index 0000000..1453228
--- /dev/null
+++ b/res/drawable-hdpi/ic_info_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..5e4e62f
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_audio_mic.png b/res/drawable-hdpi/ic_mp_audio_mic.png
new file mode 100644
index 0000000..9c005d6
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_audio_mic.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_camera_small_light.png b/res/drawable-hdpi/ic_mp_camera_small_light.png
new file mode 100644
index 0000000..6e3b09b
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_camera_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_capture_stop_large_light.png b/res/drawable-hdpi/ic_mp_capture_stop_large_light.png
new file mode 100644
index 0000000..5e29fdd
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_capture_stop_large_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_full_screen_light.png b/res/drawable-hdpi/ic_mp_full_screen_light.png
new file mode 100644
index 0000000..9c69eb8
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_full_screen_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_video_large_light.png b/res/drawable-hdpi/ic_mp_video_large_light.png
new file mode 100644
index 0000000..d6db42c
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_video_large_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_mp_video_small_light.png b/res/drawable-hdpi/ic_mp_video_small_light.png
new file mode 100644
index 0000000..9816af7
--- /dev/null
+++ b/res/drawable-hdpi/ic_mp_video_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_music.png b/res/drawable-hdpi/ic_music.png
new file mode 100644
index 0000000..033b402
--- /dev/null
+++ b/res/drawable-hdpi/ic_music.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_notifications_off_dark.png b/res/drawable-hdpi/ic_notifications_off_dark.png
new file mode 100644
index 0000000..9bcdc62
--- /dev/null
+++ b/res/drawable-hdpi/ic_notifications_off_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_notifications_off_light.png b/res/drawable-hdpi/ic_notifications_off_light.png
new file mode 100644
index 0000000..433b6a9
--- /dev/null
+++ b/res/drawable-hdpi/ic_notifications_off_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_notifications_off_small_light.png b/res/drawable-hdpi/ic_notifications_off_small_light.png
new file mode 100644
index 0000000..fbd0ad5
--- /dev/null
+++ b/res/drawable-hdpi/ic_notifications_off_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_notifications_on_dark.png b/res/drawable-hdpi/ic_notifications_on_dark.png
new file mode 100644
index 0000000..21e48a5
--- /dev/null
+++ b/res/drawable-hdpi/ic_notifications_on_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_notifications_on_light.png b/res/drawable-hdpi/ic_notifications_on_light.png
new file mode 100644
index 0000000..6b39fec
--- /dev/null
+++ b/res/drawable-hdpi/ic_notifications_on_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_numeric_dialpad.png b/res/drawable-hdpi/ic_numeric_dialpad.png
new file mode 100644
index 0000000..5460fd7
--- /dev/null
+++ b/res/drawable-hdpi/ic_numeric_dialpad.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_oobe_conv_list.png b/res/drawable-hdpi/ic_oobe_conv_list.png
new file mode 100644
index 0000000..3b904ba
--- /dev/null
+++ b/res/drawable-hdpi/ic_oobe_conv_list.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_oobe_freq_list.png b/res/drawable-hdpi/ic_oobe_freq_list.png
new file mode 100644
index 0000000..148a9ea
--- /dev/null
+++ b/res/drawable-hdpi/ic_oobe_freq_list.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_people_add_light.png b/res/drawable-hdpi/ic_people_add_light.png
new file mode 100644
index 0000000..c506e9a
--- /dev/null
+++ b/res/drawable-hdpi/ic_people_add_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_person_add_dark.png b/res/drawable-hdpi/ic_person_add_dark.png
new file mode 100644
index 0000000..71ca2a0
--- /dev/null
+++ b/res/drawable-hdpi/ic_person_add_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_person_add_light.png b/res/drawable-hdpi/ic_person_add_light.png
new file mode 100644
index 0000000..bb8ad3e
--- /dev/null
+++ b/res/drawable-hdpi/ic_person_add_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_person_light.png b/res/drawable-hdpi/ic_person_light.png
new file mode 100644
index 0000000..b439c93
--- /dev/null
+++ b/res/drawable-hdpi/ic_person_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_person_light_large.png b/res/drawable-hdpi/ic_person_light_large.png
new file mode 100644
index 0000000..5ddf265
--- /dev/null
+++ b/res/drawable-hdpi/ic_person_light_large.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_phone_small_light.png b/res/drawable-hdpi/ic_phone_small_light.png
new file mode 100644
index 0000000..35cf121
--- /dev/null
+++ b/res/drawable-hdpi/ic_phone_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_photo_library_light.png b/res/drawable-hdpi/ic_photo_library_light.png
new file mode 100644
index 0000000..55b956a
--- /dev/null
+++ b/res/drawable-hdpi/ic_photo_library_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_preview_pause.png b/res/drawable-hdpi/ic_preview_pause.png
new file mode 100644
index 0000000..06b1db4
--- /dev/null
+++ b/res/drawable-hdpi/ic_preview_pause.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_preview_play.png b/res/drawable-hdpi/ic_preview_play.png
new file mode 100644
index 0000000..6fc389a
--- /dev/null
+++ b/res/drawable-hdpi/ic_preview_play.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_remove_light.png b/res/drawable-hdpi/ic_remove_light.png
new file mode 100644
index 0000000..2222274
--- /dev/null
+++ b/res/drawable-hdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_remove_small_light.png b/res/drawable-hdpi/ic_remove_small_light.png
new file mode 100644
index 0000000..07e668c
--- /dev/null
+++ b/res/drawable-hdpi/ic_remove_small_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_save_dark.png b/res/drawable-hdpi/ic_save_dark.png
new file mode 100644
index 0000000..7cf01da
--- /dev/null
+++ b/res/drawable-hdpi/ic_save_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_save_light.png b/res/drawable-hdpi/ic_save_light.png
new file mode 100644
index 0000000..b76adb2
--- /dev/null
+++ b/res/drawable-hdpi/ic_save_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_send_dark.png b/res/drawable-hdpi/ic_send_dark.png
new file mode 100644
index 0000000..62108ef
--- /dev/null
+++ b/res/drawable-hdpi/ic_send_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_send_light.png b/res/drawable-hdpi/ic_send_light.png
new file mode 100644
index 0000000..724783d
--- /dev/null
+++ b/res/drawable-hdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_share_dark.png b/res/drawable-hdpi/ic_share_dark.png
new file mode 100644
index 0000000..bd27042
--- /dev/null
+++ b/res/drawable-hdpi/ic_share_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_share_light.png b/res/drawable-hdpi/ic_share_light.png
new file mode 100644
index 0000000..dadb3e8
--- /dev/null
+++ b/res/drawable-hdpi/ic_share_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_sim_card_send.png b/res/drawable-hdpi/ic_sim_card_send.png
new file mode 100644
index 0000000..426b153
--- /dev/null
+++ b/res/drawable-hdpi/ic_sim_card_send.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_sms_delivery_ok.png b/res/drawable-hdpi/ic_sms_delivery_ok.png
new file mode 100644
index 0000000..e038563
--- /dev/null
+++ b/res/drawable-hdpi/ic_sms_delivery_ok.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_sms_light.png b/res/drawable-hdpi/ic_sms_light.png
new file mode 100644
index 0000000..aaeec4e
--- /dev/null
+++ b/res/drawable-hdpi/ic_sms_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_sms_multi_light.png b/res/drawable-hdpi/ic_sms_multi_light.png
new file mode 100644
index 0000000..81ac2e7
--- /dev/null
+++ b/res/drawable-hdpi/ic_sms_multi_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_video_play_light.png b/res/drawable-hdpi/ic_video_play_light.png
new file mode 100644
index 0000000..4a74f37
--- /dev/null
+++ b/res/drawable-hdpi/ic_video_play_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_wear_reply.png b/res/drawable-hdpi/ic_wear_reply.png
new file mode 100644
index 0000000..19ce472
--- /dev/null
+++ b/res/drawable-hdpi/ic_wear_reply.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_avatar_shadow.png b/res/drawable-hdpi/ic_widget_avatar_shadow.png
new file mode 100644
index 0000000..9e0d519
--- /dev/null
+++ b/res/drawable-hdpi/ic_widget_avatar_shadow.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_list.png b/res/drawable-hdpi/ic_widget_list.png
new file mode 100644
index 0000000..06f9732
--- /dev/null
+++ b/res/drawable-hdpi/ic_widget_list.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_work_profile.png b/res/drawable-hdpi/ic_work_profile.png
new file mode 100644
index 0000000..5c2e457
--- /dev/null
+++ b/res/drawable-hdpi/ic_work_profile.png
Binary files differ
diff --git a/res/drawable-hdpi/msg_bubble_error.9.png b/res/drawable-hdpi/msg_bubble_error.9.png
new file mode 100644
index 0000000..6a26c30
--- /dev/null
+++ b/res/drawable-hdpi/msg_bubble_error.9.png
Binary files differ
diff --git a/res/drawable-hdpi/msg_bubble_incoming.9.png b/res/drawable-hdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..7fed0a8
--- /dev/null
+++ b/res/drawable-hdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-hdpi/msg_bubble_input.9.png b/res/drawable-hdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..01076da
--- /dev/null
+++ b/res/drawable-hdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-hdpi/msg_bubble_outgoing.9.png b/res/drawable-hdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..8e7ccc0
--- /dev/null
+++ b/res/drawable-hdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-hdpi/permissions.png b/res/drawable-hdpi/permissions.png
new file mode 100644
index 0000000..20697cf
--- /dev/null
+++ b/res/drawable-hdpi/permissions.png
Binary files differ
diff --git a/res/drawable-hdpi/swipe_shadow.9.png b/res/drawable-hdpi/swipe_shadow.9.png
new file mode 100644
index 0000000..8405721
--- /dev/null
+++ b/res/drawable-hdpi/swipe_shadow.9.png
Binary files differ
diff --git a/res/drawable-hdpi/swipe_shadow_drag.9.png b/res/drawable-hdpi/swipe_shadow_drag.9.png
new file mode 100644
index 0000000..950ec71
--- /dev/null
+++ b/res/drawable-hdpi/swipe_shadow_drag.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_btn_bg_normal.9.png b/res/drawable-hdpi/tab_btn_bg_normal.9.png
new file mode 100644
index 0000000..791bb40
--- /dev/null
+++ b/res/drawable-hdpi/tab_btn_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_btn_bg_pressed.9.png b/res/drawable-hdpi/tab_btn_bg_pressed.9.png
new file mode 100644
index 0000000..b2b488c
--- /dev/null
+++ b/res/drawable-hdpi/tab_btn_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected.9.png b/res/drawable-hdpi/tab_selected.9.png
new file mode 100644
index 0000000..84e63df
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_focused_holo.9.png b/res/drawable-hdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..5cdc5b4
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..ca3eb7b
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..08e5edb
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected.9.png b/res/drawable-hdpi/tab_unselected.9.png
new file mode 100644
index 0000000..bbcfb2c
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..a0c8bc3
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..6cf948e
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..a5dce50
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_hr.9.png b/res/drawable-hdpi/widget_hr.9.png
new file mode 100644
index 0000000..7590256
--- /dev/null
+++ b/res/drawable-hdpi/widget_hr.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_msg_bubble_incoming.9.png b/res/drawable-hdpi/widget_msg_bubble_incoming.9.png
new file mode 100644
index 0000000..c6e77a7
--- /dev/null
+++ b/res/drawable-hdpi/widget_msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_msg_bubble_outgoing.9.png b/res/drawable-hdpi/widget_msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..476efae
--- /dev/null
+++ b/res/drawable-hdpi/widget_msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/ic_send_light.png b/res/drawable-ldrtl-hdpi/ic_send_light.png
new file mode 100644
index 0000000..4ee98a3
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png b/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..8e7ccc0
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/msg_bubble_input.9.png b/res/drawable-ldrtl-hdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..c3f68b0
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/msg_bubble_outgoing.9.png b/res/drawable-ldrtl-hdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..7fed0a8
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/ic_send_light.png b/res/drawable-ldrtl-mdpi/ic_send_light.png
new file mode 100644
index 0000000..1267d66
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png b/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..5ca9b14
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/msg_bubble_input.9.png b/res/drawable-ldrtl-mdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..6f0b4bc
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/msg_bubble_outgoing.9.png b/res/drawable-ldrtl-mdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..4e7e464
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/ic_send_light.png b/res/drawable-ldrtl-xhdpi/ic_send_light.png
new file mode 100644
index 0000000..178c3cf
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png b/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..52cb936
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/msg_bubble_input.9.png b/res/drawable-ldrtl-xhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..4c5f45d
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/msg_bubble_outgoing.9.png b/res/drawable-ldrtl-xhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..0661fdb
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxhdpi/ic_send_light.png b/res/drawable-ldrtl-xxhdpi/ic_send_light.png
new file mode 100644
index 0000000..74ffc46
--- /dev/null
+++ b/res/drawable-ldrtl-xxhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png b/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..5d8fc74
--- /dev/null
+++ b/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxhdpi/msg_bubble_input.9.png b/res/drawable-ldrtl-xxhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..6d59b8f
--- /dev/null
+++ b/res/drawable-ldrtl-xxhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxhdpi/msg_bubble_outgoing.9.png b/res/drawable-ldrtl-xxhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..009c721
--- /dev/null
+++ b/res/drawable-ldrtl-xxhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxxhdpi/ic_send_light.png b/res/drawable-ldrtl-xxxhdpi/ic_send_light.png
new file mode 100644
index 0000000..cd8e266
--- /dev/null
+++ b/res/drawable-ldrtl-xxxhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png b/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..8378db5
--- /dev/null
+++ b/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxxhdpi/msg_bubble_input.9.png b/res/drawable-ldrtl-xxxhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..a707db0
--- /dev/null
+++ b/res/drawable-ldrtl-xxxhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxxhdpi/msg_bubble_outgoing.9.png b/res/drawable-ldrtl-xxxhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..f0d0d9e
--- /dev/null
+++ b/res/drawable-ldrtl-xxxhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-mdpi/contact_popup_background.9.png b/res/drawable-mdpi/contact_popup_background.9.png
new file mode 100644
index 0000000..2989590
--- /dev/null
+++ b/res/drawable-mdpi/contact_popup_background.9.png
Binary files differ
diff --git a/res/drawable-mdpi/fab_new_message_static_shadow.png b/res/drawable-mdpi/fab_new_message_static_shadow.png
new file mode 100644
index 0000000..2e24f0a
--- /dev/null
+++ b/res/drawable-mdpi/fab_new_message_static_shadow.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_add_white.png b/res/drawable-mdpi/ic_add_white.png
new file mode 100644
index 0000000..4a14229
--- /dev/null
+++ b/res/drawable-mdpi/ic_add_white.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_archive_small_dark.png b/res/drawable-mdpi/ic_archive_small_dark.png
new file mode 100644
index 0000000..a733f56
--- /dev/null
+++ b/res/drawable-mdpi/ic_archive_small_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_archive_undo_small_dark.png b/res/drawable-mdpi/ic_archive_undo_small_dark.png
new file mode 100644
index 0000000..bc9dead
--- /dev/null
+++ b/res/drawable-mdpi/ic_archive_undo_small_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_arrow_back_light.png b/res/drawable-mdpi/ic_arrow_back_light.png
new file mode 100644
index 0000000..c59a517
--- /dev/null
+++ b/res/drawable-mdpi/ic_arrow_back_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_attachment_dark.png b/res/drawable-mdpi/ic_attachment_dark.png
new file mode 100644
index 0000000..2315e23
--- /dev/null
+++ b/res/drawable-mdpi/ic_attachment_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_audio_light.png b/res/drawable-mdpi/ic_audio_light.png
new file mode 100644
index 0000000..78bc072
--- /dev/null
+++ b/res/drawable-mdpi/ic_audio_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_audio_pause.png b/res/drawable-mdpi/ic_audio_pause.png
new file mode 100644
index 0000000..e74d158
--- /dev/null
+++ b/res/drawable-mdpi/ic_audio_pause.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_audio_play.png b/res/drawable-mdpi/ic_audio_play.png
new file mode 100644
index 0000000..0d986a4
--- /dev/null
+++ b/res/drawable-mdpi/ic_audio_play.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_camera_front_light.png b/res/drawable-mdpi/ic_camera_front_light.png
new file mode 100644
index 0000000..a537897
--- /dev/null
+++ b/res/drawable-mdpi/ic_camera_front_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_camera_light.png b/res/drawable-mdpi/ic_camera_light.png
new file mode 100644
index 0000000..429bef4
--- /dev/null
+++ b/res/drawable-mdpi/ic_camera_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_camera_rear_light.png b/res/drawable-mdpi/ic_camera_rear_light.png
new file mode 100644
index 0000000..4da3328
--- /dev/null
+++ b/res/drawable-mdpi/ic_camera_rear_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_cancel_small_dark.png b/res/drawable-mdpi/ic_cancel_small_dark.png
new file mode 100644
index 0000000..f63f351
--- /dev/null
+++ b/res/drawable-mdpi/ic_cancel_small_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_cancel_small_light.png b/res/drawable-mdpi/ic_cancel_small_light.png
new file mode 100644
index 0000000..33fdf10
--- /dev/null
+++ b/res/drawable-mdpi/ic_cancel_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkbox_blank_light.png b/res/drawable-mdpi/ic_checkbox_blank_light.png
new file mode 100644
index 0000000..baec804
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkbox_blank_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkbox_light.png b/res/drawable-mdpi/ic_checkbox_light.png
new file mode 100644
index 0000000..b1b1269
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkbox_outline_light.png b/res/drawable-mdpi/ic_checkbox_outline_light.png
new file mode 100644
index 0000000..4c3c722
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkbox_outline_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_circle_blue.png b/res/drawable-mdpi/ic_checkmark_circle_blue.png
new file mode 100644
index 0000000..6cf348e
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_large.png b/res/drawable-mdpi/ic_checkmark_large.png
new file mode 100644
index 0000000..95206d1
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkmark_large.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_large_light.png b/res/drawable-mdpi/ic_checkmark_large_light.png
new file mode 100644
index 0000000..4c33ce6
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkmark_large_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_small_light.png b/res/drawable-mdpi/ic_checkmark_small_light.png
new file mode 100644
index 0000000..414fe8f
--- /dev/null
+++ b/res/drawable-mdpi/ic_checkmark_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_content_copy_dark.png b/res/drawable-mdpi/ic_content_copy_dark.png
new file mode 100644
index 0000000..4b99a83
--- /dev/null
+++ b/res/drawable-mdpi/ic_content_copy_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_delete_small_dark.png b/res/drawable-mdpi/ic_delete_small_dark.png
new file mode 100644
index 0000000..86c0002
--- /dev/null
+++ b/res/drawable-mdpi/ic_delete_small_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dnd_on_dark.png b/res/drawable-mdpi/ic_dnd_on_dark.png
new file mode 100644
index 0000000..4e911a9
--- /dev/null
+++ b/res/drawable-mdpi/ic_dnd_on_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_failed_light.png b/res/drawable-mdpi/ic_failed_light.png
new file mode 100644
index 0000000..02a4d0b
--- /dev/null
+++ b/res/drawable-mdpi/ic_failed_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_failed_status_red.png b/res/drawable-mdpi/ic_failed_status_red.png
new file mode 100644
index 0000000..f6feafe
--- /dev/null
+++ b/res/drawable-mdpi/ic_failed_status_red.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_file_download_dark.png b/res/drawable-mdpi/ic_file_download_dark.png
new file mode 100644
index 0000000..8104657
--- /dev/null
+++ b/res/drawable-mdpi/ic_file_download_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_file_download_light.png b/res/drawable-mdpi/ic_file_download_light.png
new file mode 100644
index 0000000..d066170
--- /dev/null
+++ b/res/drawable-mdpi/ic_file_download_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_forward_dark.png b/res/drawable-mdpi/ic_forward_dark.png
new file mode 100644
index 0000000..7930393
--- /dev/null
+++ b/res/drawable-mdpi/ic_forward_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_image_light.png b/res/drawable-mdpi/ic_image_light.png
new file mode 100644
index 0000000..3bd919e
--- /dev/null
+++ b/res/drawable-mdpi/ic_image_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ime_light.png b/res/drawable-mdpi/ic_ime_light.png
new file mode 100644
index 0000000..fd58cb5
--- /dev/null
+++ b/res/drawable-mdpi/ic_ime_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_info_dark.png b/res/drawable-mdpi/ic_info_dark.png
new file mode 100644
index 0000000..67457a3
--- /dev/null
+++ b/res/drawable-mdpi/ic_info_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ef6a3c5
--- /dev/null
+++ b/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_audio_mic.png b/res/drawable-mdpi/ic_mp_audio_mic.png
new file mode 100644
index 0000000..918d799
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_audio_mic.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_camera_small_light.png b/res/drawable-mdpi/ic_mp_camera_small_light.png
new file mode 100644
index 0000000..fe1dc7e
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_camera_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_capture_stop_large_light.png b/res/drawable-mdpi/ic_mp_capture_stop_large_light.png
new file mode 100644
index 0000000..a9705c1
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_capture_stop_large_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_full_screen_light.png b/res/drawable-mdpi/ic_mp_full_screen_light.png
new file mode 100644
index 0000000..5462c59
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_full_screen_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_video_large_light.png b/res/drawable-mdpi/ic_mp_video_large_light.png
new file mode 100644
index 0000000..fa8e3e2
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_video_large_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_mp_video_small_light.png b/res/drawable-mdpi/ic_mp_video_small_light.png
new file mode 100644
index 0000000..9204827
--- /dev/null
+++ b/res/drawable-mdpi/ic_mp_video_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_music.png b/res/drawable-mdpi/ic_music.png
new file mode 100644
index 0000000..106f912
--- /dev/null
+++ b/res/drawable-mdpi/ic_music.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_notifications_off_dark.png b/res/drawable-mdpi/ic_notifications_off_dark.png
new file mode 100644
index 0000000..4a5a7e9
--- /dev/null
+++ b/res/drawable-mdpi/ic_notifications_off_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_notifications_off_light.png b/res/drawable-mdpi/ic_notifications_off_light.png
new file mode 100644
index 0000000..33e0b4a
--- /dev/null
+++ b/res/drawable-mdpi/ic_notifications_off_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_notifications_off_small_light.png b/res/drawable-mdpi/ic_notifications_off_small_light.png
new file mode 100644
index 0000000..4bd9563
--- /dev/null
+++ b/res/drawable-mdpi/ic_notifications_off_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_notifications_on_dark.png b/res/drawable-mdpi/ic_notifications_on_dark.png
new file mode 100644
index 0000000..77a2a7d
--- /dev/null
+++ b/res/drawable-mdpi/ic_notifications_on_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_notifications_on_light.png b/res/drawable-mdpi/ic_notifications_on_light.png
new file mode 100644
index 0000000..eae03a5
--- /dev/null
+++ b/res/drawable-mdpi/ic_notifications_on_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_numeric_dialpad.png b/res/drawable-mdpi/ic_numeric_dialpad.png
new file mode 100644
index 0000000..5802167
--- /dev/null
+++ b/res/drawable-mdpi/ic_numeric_dialpad.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_oobe_conv_list.png b/res/drawable-mdpi/ic_oobe_conv_list.png
new file mode 100644
index 0000000..1648f2e
--- /dev/null
+++ b/res/drawable-mdpi/ic_oobe_conv_list.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_oobe_freq_list.png b/res/drawable-mdpi/ic_oobe_freq_list.png
new file mode 100644
index 0000000..8d7d47f
--- /dev/null
+++ b/res/drawable-mdpi/ic_oobe_freq_list.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_people_add_light.png b/res/drawable-mdpi/ic_people_add_light.png
new file mode 100644
index 0000000..4bc974f
--- /dev/null
+++ b/res/drawable-mdpi/ic_people_add_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_person_add_dark.png b/res/drawable-mdpi/ic_person_add_dark.png
new file mode 100644
index 0000000..6f1fd49
--- /dev/null
+++ b/res/drawable-mdpi/ic_person_add_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_person_add_light.png b/res/drawable-mdpi/ic_person_add_light.png
new file mode 100644
index 0000000..ba83709
--- /dev/null
+++ b/res/drawable-mdpi/ic_person_add_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_person_light.png b/res/drawable-mdpi/ic_person_light.png
new file mode 100644
index 0000000..5698835
--- /dev/null
+++ b/res/drawable-mdpi/ic_person_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_person_light_large.png b/res/drawable-mdpi/ic_person_light_large.png
new file mode 100644
index 0000000..7aa150b
--- /dev/null
+++ b/res/drawable-mdpi/ic_person_light_large.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_phone_small_light.png b/res/drawable-mdpi/ic_phone_small_light.png
new file mode 100644
index 0000000..dfcbba0
--- /dev/null
+++ b/res/drawable-mdpi/ic_phone_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_photo_library_light.png b/res/drawable-mdpi/ic_photo_library_light.png
new file mode 100644
index 0000000..26c58f3
--- /dev/null
+++ b/res/drawable-mdpi/ic_photo_library_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_preview_pause.png b/res/drawable-mdpi/ic_preview_pause.png
new file mode 100644
index 0000000..fbc3ff8
--- /dev/null
+++ b/res/drawable-mdpi/ic_preview_pause.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_preview_play.png b/res/drawable-mdpi/ic_preview_play.png
new file mode 100644
index 0000000..f839d44
--- /dev/null
+++ b/res/drawable-mdpi/ic_preview_play.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_remove_light.png b/res/drawable-mdpi/ic_remove_light.png
new file mode 100644
index 0000000..5b1712a
--- /dev/null
+++ b/res/drawable-mdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_remove_small_light.png b/res/drawable-mdpi/ic_remove_small_light.png
new file mode 100644
index 0000000..2131b6e
--- /dev/null
+++ b/res/drawable-mdpi/ic_remove_small_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_save_dark.png b/res/drawable-mdpi/ic_save_dark.png
new file mode 100644
index 0000000..f9b0de5
--- /dev/null
+++ b/res/drawable-mdpi/ic_save_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_save_light.png b/res/drawable-mdpi/ic_save_light.png
new file mode 100644
index 0000000..4faf5d5
--- /dev/null
+++ b/res/drawable-mdpi/ic_save_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_send_dark.png b/res/drawable-mdpi/ic_send_dark.png
new file mode 100644
index 0000000..965a9f0
--- /dev/null
+++ b/res/drawable-mdpi/ic_send_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_send_light.png b/res/drawable-mdpi/ic_send_light.png
new file mode 100644
index 0000000..46d2dcd
--- /dev/null
+++ b/res/drawable-mdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_share_dark.png b/res/drawable-mdpi/ic_share_dark.png
new file mode 100644
index 0000000..c6ba4c9
--- /dev/null
+++ b/res/drawable-mdpi/ic_share_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_share_light.png b/res/drawable-mdpi/ic_share_light.png
new file mode 100644
index 0000000..362c862
--- /dev/null
+++ b/res/drawable-mdpi/ic_share_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_sim_card_send.png b/res/drawable-mdpi/ic_sim_card_send.png
new file mode 100644
index 0000000..1f26017
--- /dev/null
+++ b/res/drawable-mdpi/ic_sim_card_send.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_sms_delivery_ok.png b/res/drawable-mdpi/ic_sms_delivery_ok.png
new file mode 100644
index 0000000..ffccf64
--- /dev/null
+++ b/res/drawable-mdpi/ic_sms_delivery_ok.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_sms_light.png b/res/drawable-mdpi/ic_sms_light.png
new file mode 100644
index 0000000..518c989
--- /dev/null
+++ b/res/drawable-mdpi/ic_sms_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_sms_multi_light.png b/res/drawable-mdpi/ic_sms_multi_light.png
new file mode 100644
index 0000000..bd6f4c6
--- /dev/null
+++ b/res/drawable-mdpi/ic_sms_multi_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_video_play_light.png b/res/drawable-mdpi/ic_video_play_light.png
new file mode 100644
index 0000000..e0ac1e4
--- /dev/null
+++ b/res/drawable-mdpi/ic_video_play_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_wear_reply.png b/res/drawable-mdpi/ic_wear_reply.png
new file mode 100644
index 0000000..47bb396
--- /dev/null
+++ b/res/drawable-mdpi/ic_wear_reply.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_avatar_shadow.png b/res/drawable-mdpi/ic_widget_avatar_shadow.png
new file mode 100644
index 0000000..1a8dc8e
--- /dev/null
+++ b/res/drawable-mdpi/ic_widget_avatar_shadow.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_list.png b/res/drawable-mdpi/ic_widget_list.png
new file mode 100644
index 0000000..9bf4b11
--- /dev/null
+++ b/res/drawable-mdpi/ic_widget_list.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_work_profile.png b/res/drawable-mdpi/ic_work_profile.png
new file mode 100644
index 0000000..b7ffd2b
--- /dev/null
+++ b/res/drawable-mdpi/ic_work_profile.png
Binary files differ
diff --git a/res/drawable-mdpi/msg_bubble_error.9.png b/res/drawable-mdpi/msg_bubble_error.9.png
new file mode 100644
index 0000000..694d117
--- /dev/null
+++ b/res/drawable-mdpi/msg_bubble_error.9.png
Binary files differ
diff --git a/res/drawable-mdpi/msg_bubble_incoming.9.png b/res/drawable-mdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..4e7e464
--- /dev/null
+++ b/res/drawable-mdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-mdpi/msg_bubble_input.9.png b/res/drawable-mdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..1810ffb
--- /dev/null
+++ b/res/drawable-mdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-mdpi/msg_bubble_outgoing.9.png b/res/drawable-mdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..5ca9b14
--- /dev/null
+++ b/res/drawable-mdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-mdpi/permissions.png b/res/drawable-mdpi/permissions.png
new file mode 100644
index 0000000..2d754ec
--- /dev/null
+++ b/res/drawable-mdpi/permissions.png
Binary files differ
diff --git a/res/drawable-mdpi/swipe_shadow.9.png b/res/drawable-mdpi/swipe_shadow.9.png
new file mode 100644
index 0000000..e2ed6d4
--- /dev/null
+++ b/res/drawable-mdpi/swipe_shadow.9.png
Binary files differ
diff --git a/res/drawable-mdpi/swipe_shadow_drag.9.png b/res/drawable-mdpi/swipe_shadow_drag.9.png
new file mode 100644
index 0000000..94be3f9
--- /dev/null
+++ b/res/drawable-mdpi/swipe_shadow_drag.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_btn_bg_normal.9.png b/res/drawable-mdpi/tab_btn_bg_normal.9.png
new file mode 100644
index 0000000..d56cd94
--- /dev/null
+++ b/res/drawable-mdpi/tab_btn_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_btn_bg_pressed.9.png b/res/drawable-mdpi/tab_btn_bg_pressed.9.png
new file mode 100644
index 0000000..4d4c932
--- /dev/null
+++ b/res/drawable-mdpi/tab_btn_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected.9.png b/res/drawable-mdpi/tab_selected.9.png
new file mode 100644
index 0000000..4b00f35
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_focused_holo.9.png b/res/drawable-mdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..c77808d
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..1e28bb6
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..098bf7d
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected.9.png b/res/drawable-mdpi/tab_unselected.9.png
new file mode 100644
index 0000000..bb45ab9
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..e00e256
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..80e8f0c
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..eb9422e
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_hr.9.png b/res/drawable-mdpi/widget_hr.9.png
new file mode 100644
index 0000000..93f3417
--- /dev/null
+++ b/res/drawable-mdpi/widget_hr.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_msg_bubble_incoming.9.png b/res/drawable-mdpi/widget_msg_bubble_incoming.9.png
new file mode 100644
index 0000000..ddadf73
--- /dev/null
+++ b/res/drawable-mdpi/widget_msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_msg_bubble_outgoing.9.png b/res/drawable-mdpi/widget_msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..00432c3
--- /dev/null
+++ b/res/drawable-mdpi/widget_msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-nodpi/bg_sms.jpg b/res/drawable-nodpi/bg_sms.jpg
new file mode 100644
index 0000000..d8711e7
--- /dev/null
+++ b/res/drawable-nodpi/bg_sms.jpg
Binary files differ
diff --git a/res/drawable-nodpi/ic_person_wear.png b/res/drawable-nodpi/ic_person_wear.png
new file mode 100644
index 0000000..97be017
--- /dev/null
+++ b/res/drawable-nodpi/ic_person_wear.png
Binary files differ
diff --git a/res/drawable-nodpi/messenger_widget_conversation_preview.png b/res/drawable-nodpi/messenger_widget_conversation_preview.png
new file mode 100644
index 0000000..e26ae97
--- /dev/null
+++ b/res/drawable-nodpi/messenger_widget_conversation_preview.png
Binary files differ
diff --git a/res/drawable-nodpi/messenger_widget_preview.png b/res/drawable-nodpi/messenger_widget_preview.png
new file mode 100644
index 0000000..a5d40b2
--- /dev/null
+++ b/res/drawable-nodpi/messenger_widget_preview.png
Binary files differ
diff --git a/res/drawable-v21/contact_picker_tab_background_selector.xml b/res/drawable-v21/contact_picker_tab_background_selector.xml
new file mode 100644
index 0000000..59bdf95
--- /dev/null
+++ b/res/drawable-v21/contact_picker_tab_background_selector.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/contact_picker_tab_pressed" />
\ No newline at end of file
diff --git a/res/drawable-v21/fab_new_message_bg.xml b/res/drawable-v21/fab_new_message_bg.xml
new file mode 100644
index 0000000..8043f0f
--- /dev/null
+++ b/res/drawable-v21/fab_new_message_bg.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/fab_ripple" >
+
+    <item>
+        <shape android:shape="oval">
+            <solid android:color="@color/fab_color" />
+        </shape>
+    </item>
+
+</ripple>
\ No newline at end of file
diff --git a/res/drawable-v21/gallery_image_background_selector.xml b/res/drawable-v21/gallery_image_background_selector.xml
new file mode 100644
index 0000000..7486fad
--- /dev/null
+++ b/res/drawable-v21/gallery_image_background_selector.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/gallery_image_pressed">
+    <item android:id="@android:id/mask"
+          android:drawable="@android:color/white" />
+</ripple>
diff --git a/res/drawable-v21/mediapicker_tab_button_background.xml b/res/drawable-v21/mediapicker_tab_button_background.xml
new file mode 100644
index 0000000..10c4474
--- /dev/null
+++ b/res/drawable-v21/mediapicker_tab_button_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/background_item_pressed" />
diff --git a/res/drawable-v21/transparent_button_background.xml b/res/drawable-v21/transparent_button_background.xml
new file mode 100644
index 0000000..10c4474
--- /dev/null
+++ b/res/drawable-v21/transparent_button_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/background_item_pressed" />
diff --git a/res/drawable-v21/widget_item_background.xml b/res/drawable-v21/widget_item_background.xml
new file mode 100644
index 0000000..eb20c06
--- /dev/null
+++ b/res/drawable-v21/widget_item_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/ripple_material_light" >
+    <item android:id="@android:id/mask">
+        <color android:color="@android:color/white" />
+    </item>
+</ripple>
diff --git a/res/drawable-xhdpi/contact_popup_background.9.png b/res/drawable-xhdpi/contact_popup_background.9.png
new file mode 100644
index 0000000..f8b809a
--- /dev/null
+++ b/res/drawable-xhdpi/contact_popup_background.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/fab_new_message_static_shadow.png b/res/drawable-xhdpi/fab_new_message_static_shadow.png
new file mode 100644
index 0000000..7075cb9
--- /dev/null
+++ b/res/drawable-xhdpi/fab_new_message_static_shadow.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_add_white.png b/res/drawable-xhdpi/ic_add_white.png
new file mode 100644
index 0000000..7ef4fc1
--- /dev/null
+++ b/res/drawable-xhdpi/ic_add_white.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_archive_small_dark.png b/res/drawable-xhdpi/ic_archive_small_dark.png
new file mode 100644
index 0000000..ea31204
--- /dev/null
+++ b/res/drawable-xhdpi/ic_archive_small_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_archive_undo_small_dark.png b/res/drawable-xhdpi/ic_archive_undo_small_dark.png
new file mode 100644
index 0000000..7508484
--- /dev/null
+++ b/res/drawable-xhdpi/ic_archive_undo_small_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_arrow_back_light.png b/res/drawable-xhdpi/ic_arrow_back_light.png
new file mode 100644
index 0000000..fa3d493
--- /dev/null
+++ b/res/drawable-xhdpi/ic_arrow_back_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_attachment_dark.png b/res/drawable-xhdpi/ic_attachment_dark.png
new file mode 100644
index 0000000..61e565c
--- /dev/null
+++ b/res/drawable-xhdpi/ic_attachment_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_audio_light.png b/res/drawable-xhdpi/ic_audio_light.png
new file mode 100644
index 0000000..fab5ba4
--- /dev/null
+++ b/res/drawable-xhdpi/ic_audio_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_audio_pause.png b/res/drawable-xhdpi/ic_audio_pause.png
new file mode 100644
index 0000000..e33b655
--- /dev/null
+++ b/res/drawable-xhdpi/ic_audio_pause.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_audio_play.png b/res/drawable-xhdpi/ic_audio_play.png
new file mode 100644
index 0000000..ff93063
--- /dev/null
+++ b/res/drawable-xhdpi/ic_audio_play.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_camera_front_light.png b/res/drawable-xhdpi/ic_camera_front_light.png
new file mode 100644
index 0000000..9cd577d
--- /dev/null
+++ b/res/drawable-xhdpi/ic_camera_front_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_camera_light.png b/res/drawable-xhdpi/ic_camera_light.png
new file mode 100644
index 0000000..3b74ad6
--- /dev/null
+++ b/res/drawable-xhdpi/ic_camera_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_camera_rear_light.png b/res/drawable-xhdpi/ic_camera_rear_light.png
new file mode 100644
index 0000000..92727af
--- /dev/null
+++ b/res/drawable-xhdpi/ic_camera_rear_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_cancel_small_dark.png b/res/drawable-xhdpi/ic_cancel_small_dark.png
new file mode 100644
index 0000000..8b34b9b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_cancel_small_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_cancel_small_light.png b/res/drawable-xhdpi/ic_cancel_small_light.png
new file mode 100644
index 0000000..dea984f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_cancel_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkbox_blank_light.png b/res/drawable-xhdpi/ic_checkbox_blank_light.png
new file mode 100644
index 0000000..7f6e917
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkbox_blank_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkbox_light.png b/res/drawable-xhdpi/ic_checkbox_light.png
new file mode 100644
index 0000000..a388a2b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkbox_outline_light.png b/res/drawable-xhdpi/ic_checkbox_outline_light.png
new file mode 100644
index 0000000..64f0a2b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkbox_outline_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_circle_blue.png b/res/drawable-xhdpi/ic_checkmark_circle_blue.png
new file mode 100644
index 0000000..ae0ac2d
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_large.png b/res/drawable-xhdpi/ic_checkmark_large.png
new file mode 100644
index 0000000..fd4420b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkmark_large.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_large_light.png b/res/drawable-xhdpi/ic_checkmark_large_light.png
new file mode 100644
index 0000000..d841688
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkmark_large_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_small_light.png b/res/drawable-xhdpi/ic_checkmark_small_light.png
new file mode 100644
index 0000000..cd084fb
--- /dev/null
+++ b/res/drawable-xhdpi/ic_checkmark_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_content_copy_dark.png b/res/drawable-xhdpi/ic_content_copy_dark.png
new file mode 100644
index 0000000..0114555
--- /dev/null
+++ b/res/drawable-xhdpi/ic_content_copy_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_delete_small_dark.png b/res/drawable-xhdpi/ic_delete_small_dark.png
new file mode 100644
index 0000000..b9b0cbd
--- /dev/null
+++ b/res/drawable-xhdpi/ic_delete_small_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dnd_on_dark.png b/res/drawable-xhdpi/ic_dnd_on_dark.png
new file mode 100644
index 0000000..c40fe99
--- /dev/null
+++ b/res/drawable-xhdpi/ic_dnd_on_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_failed_light.png b/res/drawable-xhdpi/ic_failed_light.png
new file mode 100644
index 0000000..33d3436
--- /dev/null
+++ b/res/drawable-xhdpi/ic_failed_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_failed_status_red.png b/res/drawable-xhdpi/ic_failed_status_red.png
new file mode 100644
index 0000000..3c6616a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_failed_status_red.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_file_download_dark.png b/res/drawable-xhdpi/ic_file_download_dark.png
new file mode 100644
index 0000000..c31257a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_file_download_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_file_download_light.png b/res/drawable-xhdpi/ic_file_download_light.png
new file mode 100644
index 0000000..b894fa6
--- /dev/null
+++ b/res/drawable-xhdpi/ic_file_download_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_forward_dark.png b/res/drawable-xhdpi/ic_forward_dark.png
new file mode 100644
index 0000000..b62f0de
--- /dev/null
+++ b/res/drawable-xhdpi/ic_forward_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_image_light.png b/res/drawable-xhdpi/ic_image_light.png
new file mode 100644
index 0000000..b2aecfb
--- /dev/null
+++ b/res/drawable-xhdpi/ic_image_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ime_light.png b/res/drawable-xhdpi/ic_ime_light.png
new file mode 100644
index 0000000..14b57f8
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ime_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_info_dark.png b/res/drawable-xhdpi/ic_info_dark.png
new file mode 100644
index 0000000..31d1e05
--- /dev/null
+++ b/res/drawable-xhdpi/ic_info_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..ad1acb4
--- /dev/null
+++ b/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_audio_mic.png b/res/drawable-xhdpi/ic_mp_audio_mic.png
new file mode 100644
index 0000000..b35d0f1
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_audio_mic.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_camera_small_light.png b/res/drawable-xhdpi/ic_mp_camera_small_light.png
new file mode 100644
index 0000000..75094e1
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_camera_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_capture_stop_large_light.png b/res/drawable-xhdpi/ic_mp_capture_stop_large_light.png
new file mode 100644
index 0000000..62125b3
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_capture_stop_large_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_full_screen_light.png b/res/drawable-xhdpi/ic_mp_full_screen_light.png
new file mode 100644
index 0000000..02cbd48
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_full_screen_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_video_large_light.png b/res/drawable-xhdpi/ic_mp_video_large_light.png
new file mode 100644
index 0000000..723b052
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_video_large_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_mp_video_small_light.png b/res/drawable-xhdpi/ic_mp_video_small_light.png
new file mode 100644
index 0000000..00fde5f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_mp_video_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_music.png b/res/drawable-xhdpi/ic_music.png
new file mode 100644
index 0000000..1de4c3b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_music.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_notifications_off_dark.png b/res/drawable-xhdpi/ic_notifications_off_dark.png
new file mode 100644
index 0000000..4f3b924
--- /dev/null
+++ b/res/drawable-xhdpi/ic_notifications_off_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_notifications_off_light.png b/res/drawable-xhdpi/ic_notifications_off_light.png
new file mode 100644
index 0000000..16ae132
--- /dev/null
+++ b/res/drawable-xhdpi/ic_notifications_off_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_notifications_off_small_light.png b/res/drawable-xhdpi/ic_notifications_off_small_light.png
new file mode 100644
index 0000000..e54fc52
--- /dev/null
+++ b/res/drawable-xhdpi/ic_notifications_off_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_notifications_on_dark.png b/res/drawable-xhdpi/ic_notifications_on_dark.png
new file mode 100644
index 0000000..40f2909
--- /dev/null
+++ b/res/drawable-xhdpi/ic_notifications_on_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_notifications_on_light.png b/res/drawable-xhdpi/ic_notifications_on_light.png
new file mode 100644
index 0000000..3c44f93
--- /dev/null
+++ b/res/drawable-xhdpi/ic_notifications_on_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_numeric_dialpad.png b/res/drawable-xhdpi/ic_numeric_dialpad.png
new file mode 100644
index 0000000..b22360f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_numeric_dialpad.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_oobe_conv_list.png b/res/drawable-xhdpi/ic_oobe_conv_list.png
new file mode 100644
index 0000000..b41d322
--- /dev/null
+++ b/res/drawable-xhdpi/ic_oobe_conv_list.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_oobe_freq_list.png b/res/drawable-xhdpi/ic_oobe_freq_list.png
new file mode 100644
index 0000000..898daf5
--- /dev/null
+++ b/res/drawable-xhdpi/ic_oobe_freq_list.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_people_add_light.png b/res/drawable-xhdpi/ic_people_add_light.png
new file mode 100644
index 0000000..f57f056
--- /dev/null
+++ b/res/drawable-xhdpi/ic_people_add_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_person_add_dark.png b/res/drawable-xhdpi/ic_person_add_dark.png
new file mode 100644
index 0000000..6f325cf
--- /dev/null
+++ b/res/drawable-xhdpi/ic_person_add_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_person_add_light.png b/res/drawable-xhdpi/ic_person_add_light.png
new file mode 100644
index 0000000..840f063
--- /dev/null
+++ b/res/drawable-xhdpi/ic_person_add_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_person_light.png b/res/drawable-xhdpi/ic_person_light.png
new file mode 100644
index 0000000..5d23639
--- /dev/null
+++ b/res/drawable-xhdpi/ic_person_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_person_light_large.png b/res/drawable-xhdpi/ic_person_light_large.png
new file mode 100644
index 0000000..22a4ff1
--- /dev/null
+++ b/res/drawable-xhdpi/ic_person_light_large.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_phone_small_light.png b/res/drawable-xhdpi/ic_phone_small_light.png
new file mode 100644
index 0000000..b2cab28
--- /dev/null
+++ b/res/drawable-xhdpi/ic_phone_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_photo_library_light.png b/res/drawable-xhdpi/ic_photo_library_light.png
new file mode 100644
index 0000000..627ff48
--- /dev/null
+++ b/res/drawable-xhdpi/ic_photo_library_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_preview_pause.png b/res/drawable-xhdpi/ic_preview_pause.png
new file mode 100644
index 0000000..bbfce5f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_preview_pause.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_preview_play.png b/res/drawable-xhdpi/ic_preview_play.png
new file mode 100644
index 0000000..8b22c75
--- /dev/null
+++ b/res/drawable-xhdpi/ic_preview_play.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_remove_light.png b/res/drawable-xhdpi/ic_remove_light.png
new file mode 100644
index 0000000..9424e1e
--- /dev/null
+++ b/res/drawable-xhdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_remove_small_light.png b/res/drawable-xhdpi/ic_remove_small_light.png
new file mode 100644
index 0000000..222b86c
--- /dev/null
+++ b/res/drawable-xhdpi/ic_remove_small_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_save_dark.png b/res/drawable-xhdpi/ic_save_dark.png
new file mode 100644
index 0000000..7927ba6
--- /dev/null
+++ b/res/drawable-xhdpi/ic_save_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_save_light.png b/res/drawable-xhdpi/ic_save_light.png
new file mode 100644
index 0000000..298bb47
--- /dev/null
+++ b/res/drawable-xhdpi/ic_save_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_send_dark.png b/res/drawable-xhdpi/ic_send_dark.png
new file mode 100644
index 0000000..a6b3699
--- /dev/null
+++ b/res/drawable-xhdpi/ic_send_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_send_light.png b/res/drawable-xhdpi/ic_send_light.png
new file mode 100644
index 0000000..a19b335
--- /dev/null
+++ b/res/drawable-xhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_share_dark.png b/res/drawable-xhdpi/ic_share_dark.png
new file mode 100644
index 0000000..a4b822a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_share_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_share_light.png b/res/drawable-xhdpi/ic_share_light.png
new file mode 100644
index 0000000..711797c
--- /dev/null
+++ b/res/drawable-xhdpi/ic_share_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_sim_card_send.png b/res/drawable-xhdpi/ic_sim_card_send.png
new file mode 100644
index 0000000..9fc7e9a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_sim_card_send.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_sms_delivery_ok.png b/res/drawable-xhdpi/ic_sms_delivery_ok.png
new file mode 100644
index 0000000..c12ae0a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_sms_delivery_ok.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_sms_light.png b/res/drawable-xhdpi/ic_sms_light.png
new file mode 100644
index 0000000..4b24a4b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_sms_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_sms_multi_light.png b/res/drawable-xhdpi/ic_sms_multi_light.png
new file mode 100644
index 0000000..f3ba620
--- /dev/null
+++ b/res/drawable-xhdpi/ic_sms_multi_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_video_play_light.png b/res/drawable-xhdpi/ic_video_play_light.png
new file mode 100644
index 0000000..89397a8
--- /dev/null
+++ b/res/drawable-xhdpi/ic_video_play_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_wear_reply.png b/res/drawable-xhdpi/ic_wear_reply.png
new file mode 100644
index 0000000..c909c59
--- /dev/null
+++ b/res/drawable-xhdpi/ic_wear_reply.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_avatar_shadow.png b/res/drawable-xhdpi/ic_widget_avatar_shadow.png
new file mode 100644
index 0000000..37600aa
--- /dev/null
+++ b/res/drawable-xhdpi/ic_widget_avatar_shadow.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_list.png b/res/drawable-xhdpi/ic_widget_list.png
new file mode 100644
index 0000000..a12764f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_widget_list.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_work_profile.png b/res/drawable-xhdpi/ic_work_profile.png
new file mode 100644
index 0000000..b47b485
--- /dev/null
+++ b/res/drawable-xhdpi/ic_work_profile.png
Binary files differ
diff --git a/res/drawable-xhdpi/msg_bubble_error.9.png b/res/drawable-xhdpi/msg_bubble_error.9.png
new file mode 100644
index 0000000..96b139b
--- /dev/null
+++ b/res/drawable-xhdpi/msg_bubble_error.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/msg_bubble_incoming.9.png b/res/drawable-xhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..0661fdb
--- /dev/null
+++ b/res/drawable-xhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/msg_bubble_input.9.png b/res/drawable-xhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..67f92ff
--- /dev/null
+++ b/res/drawable-xhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/msg_bubble_outgoing.9.png b/res/drawable-xhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..52cb936
--- /dev/null
+++ b/res/drawable-xhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/permissions.png b/res/drawable-xhdpi/permissions.png
new file mode 100644
index 0000000..39a81bc
--- /dev/null
+++ b/res/drawable-xhdpi/permissions.png
Binary files differ
diff --git a/res/drawable-xhdpi/swipe_shadow.9.png b/res/drawable-xhdpi/swipe_shadow.9.png
new file mode 100644
index 0000000..45d965d
--- /dev/null
+++ b/res/drawable-xhdpi/swipe_shadow.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/swipe_shadow_drag.9.png b/res/drawable-xhdpi/swipe_shadow_drag.9.png
new file mode 100644
index 0000000..b443b5c
--- /dev/null
+++ b/res/drawable-xhdpi/swipe_shadow_drag.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_btn_bg_normal.9.png b/res/drawable-xhdpi/tab_btn_bg_normal.9.png
new file mode 100644
index 0000000..d9446c6
--- /dev/null
+++ b/res/drawable-xhdpi/tab_btn_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_btn_bg_pressed.9.png b/res/drawable-xhdpi/tab_btn_bg_pressed.9.png
new file mode 100644
index 0000000..de76c06
--- /dev/null
+++ b/res/drawable-xhdpi/tab_btn_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_hr.9.png b/res/drawable-xhdpi/widget_hr.9.png
new file mode 100644
index 0000000..31fcc7e
--- /dev/null
+++ b/res/drawable-xhdpi/widget_hr.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_msg_bubble_incoming.9.png b/res/drawable-xhdpi/widget_msg_bubble_incoming.9.png
new file mode 100644
index 0000000..2abb496
--- /dev/null
+++ b/res/drawable-xhdpi/widget_msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_msg_bubble_outgoing.9.png b/res/drawable-xhdpi/widget_msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..35b58cd
--- /dev/null
+++ b/res/drawable-xhdpi/widget_msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/contact_popup_background.9.png b/res/drawable-xxhdpi/contact_popup_background.9.png
new file mode 100644
index 0000000..bb4f281
--- /dev/null
+++ b/res/drawable-xxhdpi/contact_popup_background.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/fab_new_message_static_shadow.png b/res/drawable-xxhdpi/fab_new_message_static_shadow.png
new file mode 100644
index 0000000..adfd569
--- /dev/null
+++ b/res/drawable-xxhdpi/fab_new_message_static_shadow.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_add_white.png b/res/drawable-xxhdpi/ic_add_white.png
new file mode 100644
index 0000000..7b4d52c
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_add_white.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_archive_small_dark.png b/res/drawable-xxhdpi/ic_archive_small_dark.png
new file mode 100644
index 0000000..64aa9d5
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_archive_small_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_archive_undo_small_dark.png b/res/drawable-xxhdpi/ic_archive_undo_small_dark.png
new file mode 100644
index 0000000..a3f7503
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_archive_undo_small_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_arrow_back_light.png b/res/drawable-xxhdpi/ic_arrow_back_light.png
new file mode 100644
index 0000000..8b532d0
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_arrow_back_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_attachment_dark.png b/res/drawable-xxhdpi/ic_attachment_dark.png
new file mode 100644
index 0000000..64d9dad
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_attachment_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_audio_light.png b/res/drawable-xxhdpi/ic_audio_light.png
new file mode 100644
index 0000000..9b2f05c
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_audio_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_audio_pause.png b/res/drawable-xxhdpi/ic_audio_pause.png
new file mode 100644
index 0000000..d294f3c
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_audio_pause.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_audio_play.png b/res/drawable-xxhdpi/ic_audio_play.png
new file mode 100644
index 0000000..cb84ee6
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_audio_play.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_camera_front_light.png b/res/drawable-xxhdpi/ic_camera_front_light.png
new file mode 100644
index 0000000..53616e4
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_camera_front_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_camera_light.png b/res/drawable-xxhdpi/ic_camera_light.png
new file mode 100644
index 0000000..64e9873
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_camera_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_camera_rear_light.png b/res/drawable-xxhdpi/ic_camera_rear_light.png
new file mode 100644
index 0000000..8e478e3
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_camera_rear_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_cancel_small_dark.png b/res/drawable-xxhdpi/ic_cancel_small_dark.png
new file mode 100644
index 0000000..c8f583c
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_cancel_small_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_cancel_small_light.png b/res/drawable-xxhdpi/ic_cancel_small_light.png
new file mode 100644
index 0000000..b3eacda
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_cancel_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_blank_light.png b/res/drawable-xxhdpi/ic_checkbox_blank_light.png
new file mode 100644
index 0000000..0556578
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkbox_blank_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_light.png b/res/drawable-xxhdpi/ic_checkbox_light.png
new file mode 100644
index 0000000..b10c8e9
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_outline_light.png b/res/drawable-xxhdpi/ic_checkbox_outline_light.png
new file mode 100644
index 0000000..cc77c5e
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkbox_outline_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_circle_blue.png b/res/drawable-xxhdpi/ic_checkmark_circle_blue.png
new file mode 100644
index 0000000..d40bb93
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_large.png b/res/drawable-xxhdpi/ic_checkmark_large.png
new file mode 100644
index 0000000..1be0e02
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkmark_large.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_large_light.png b/res/drawable-xxhdpi/ic_checkmark_large_light.png
new file mode 100644
index 0000000..b5f4e24
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkmark_large_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_small_light.png b/res/drawable-xxhdpi/ic_checkmark_small_light.png
new file mode 100644
index 0000000..7aeac03
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_checkmark_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_content_copy_dark.png b/res/drawable-xxhdpi/ic_content_copy_dark.png
new file mode 100644
index 0000000..e3518ae
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_content_copy_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_delete_small_dark.png b/res/drawable-xxhdpi/ic_delete_small_dark.png
new file mode 100644
index 0000000..146ac39
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_delete_small_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_dnd_on_dark.png b/res/drawable-xxhdpi/ic_dnd_on_dark.png
new file mode 100644
index 0000000..a9ccb88
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_dnd_on_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_failed_light.png b/res/drawable-xxhdpi/ic_failed_light.png
new file mode 100644
index 0000000..7612138
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_failed_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_failed_status_red.png b/res/drawable-xxhdpi/ic_failed_status_red.png
new file mode 100644
index 0000000..26f76cc
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_failed_status_red.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_file_download_dark.png b/res/drawable-xxhdpi/ic_file_download_dark.png
new file mode 100644
index 0000000..d7fc0b3
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_file_download_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_file_download_light.png b/res/drawable-xxhdpi/ic_file_download_light.png
new file mode 100644
index 0000000..42eadbc
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_file_download_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_forward_dark.png b/res/drawable-xxhdpi/ic_forward_dark.png
new file mode 100644
index 0000000..cd071be
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_forward_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_image_light.png b/res/drawable-xxhdpi/ic_image_light.png
new file mode 100644
index 0000000..16b7e7b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_image_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_ime_light.png b/res/drawable-xxhdpi/ic_ime_light.png
new file mode 100644
index 0000000..159d085
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_ime_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_info_dark.png b/res/drawable-xxhdpi/ic_info_dark.png
new file mode 100644
index 0000000..2df42de
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_info_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher.png b/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..de56e98
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_audio_mic.png b/res/drawable-xxhdpi/ic_mp_audio_mic.png
new file mode 100644
index 0000000..a01388b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_audio_mic.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_camera_small_light.png b/res/drawable-xxhdpi/ic_mp_camera_small_light.png
new file mode 100644
index 0000000..8012fce
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_camera_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_capture_stop_large_light.png b/res/drawable-xxhdpi/ic_mp_capture_stop_large_light.png
new file mode 100644
index 0000000..d34667a
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_capture_stop_large_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_full_screen_light.png b/res/drawable-xxhdpi/ic_mp_full_screen_light.png
new file mode 100644
index 0000000..483a1a3
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_full_screen_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_video_large_light.png b/res/drawable-xxhdpi/ic_mp_video_large_light.png
new file mode 100644
index 0000000..0a34b5e
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_video_large_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_mp_video_small_light.png b/res/drawable-xxhdpi/ic_mp_video_small_light.png
new file mode 100644
index 0000000..1cb7798
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_mp_video_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_music.png b/res/drawable-xxhdpi/ic_music.png
new file mode 100644
index 0000000..f8016cc
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_music.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_notifications_off_dark.png b/res/drawable-xxhdpi/ic_notifications_off_dark.png
new file mode 100644
index 0000000..27d3754
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_notifications_off_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_notifications_off_light.png b/res/drawable-xxhdpi/ic_notifications_off_light.png
new file mode 100644
index 0000000..a2aedec
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_notifications_off_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_notifications_off_small_light.png b/res/drawable-xxhdpi/ic_notifications_off_small_light.png
new file mode 100644
index 0000000..2a90e07
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_notifications_off_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_notifications_on_dark.png b/res/drawable-xxhdpi/ic_notifications_on_dark.png
new file mode 100644
index 0000000..e64da6b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_notifications_on_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_notifications_on_light.png b/res/drawable-xxhdpi/ic_notifications_on_light.png
new file mode 100644
index 0000000..f8f7d15
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_notifications_on_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_numeric_dialpad.png b/res/drawable-xxhdpi/ic_numeric_dialpad.png
new file mode 100644
index 0000000..a0d9e5e
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_numeric_dialpad.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_oobe_conv_list.png b/res/drawable-xxhdpi/ic_oobe_conv_list.png
new file mode 100644
index 0000000..f6fcde1
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_oobe_conv_list.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_oobe_freq_list.png b/res/drawable-xxhdpi/ic_oobe_freq_list.png
new file mode 100644
index 0000000..4d7543d
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_oobe_freq_list.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_people_add_light.png b/res/drawable-xxhdpi/ic_people_add_light.png
new file mode 100644
index 0000000..915b91d
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_people_add_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_person_add_dark.png b/res/drawable-xxhdpi/ic_person_add_dark.png
new file mode 100644
index 0000000..1d9bb20
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_person_add_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_person_add_light.png b/res/drawable-xxhdpi/ic_person_add_light.png
new file mode 100644
index 0000000..5a17f08
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_person_add_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_person_light.png b/res/drawable-xxhdpi/ic_person_light.png
new file mode 100644
index 0000000..adab957
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_person_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_person_light_large.png b/res/drawable-xxhdpi/ic_person_light_large.png
new file mode 100644
index 0000000..3cf214f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_person_light_large.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_phone_small_light.png b/res/drawable-xxhdpi/ic_phone_small_light.png
new file mode 100644
index 0000000..8d7c25f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_phone_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_photo_library_light.png b/res/drawable-xxhdpi/ic_photo_library_light.png
new file mode 100644
index 0000000..cd72bdf
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_photo_library_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_preview_pause.png b/res/drawable-xxhdpi/ic_preview_pause.png
new file mode 100644
index 0000000..7ead0d7
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_preview_pause.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_preview_play.png b/res/drawable-xxhdpi/ic_preview_play.png
new file mode 100644
index 0000000..2db591b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_preview_play.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove_light.png b/res/drawable-xxhdpi/ic_remove_light.png
new file mode 100644
index 0000000..6f07cc5
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove_small_light.png b/res/drawable-xxhdpi/ic_remove_small_light.png
new file mode 100644
index 0000000..c69e993
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_remove_small_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_save_dark.png b/res/drawable-xxhdpi/ic_save_dark.png
new file mode 100644
index 0000000..8267484
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_save_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_save_light.png b/res/drawable-xxhdpi/ic_save_light.png
new file mode 100644
index 0000000..4b944cf
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_save_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_send_dark.png b/res/drawable-xxhdpi/ic_send_dark.png
new file mode 100644
index 0000000..44729b1
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_send_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_send_light.png b/res/drawable-xxhdpi/ic_send_light.png
new file mode 100644
index 0000000..a1a6cab
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_share_dark.png b/res/drawable-xxhdpi/ic_share_dark.png
new file mode 100644
index 0000000..790670a
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_share_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_share_light.png b/res/drawable-xxhdpi/ic_share_light.png
new file mode 100644
index 0000000..880c6a2
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_share_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_sim_card_send.png b/res/drawable-xxhdpi/ic_sim_card_send.png
new file mode 100644
index 0000000..8eae7c3
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_sim_card_send.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_sms_delivery_ok.png b/res/drawable-xxhdpi/ic_sms_delivery_ok.png
new file mode 100644
index 0000000..2c8c9b0
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_sms_delivery_ok.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_sms_light.png b/res/drawable-xxhdpi/ic_sms_light.png
new file mode 100644
index 0000000..7a8b491
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_sms_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_sms_multi_light.png b/res/drawable-xxhdpi/ic_sms_multi_light.png
new file mode 100644
index 0000000..6496cb8
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_sms_multi_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_video_play_light.png b/res/drawable-xxhdpi/ic_video_play_light.png
new file mode 100644
index 0000000..f49c653
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_video_play_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_wear_reply.png b/res/drawable-xxhdpi/ic_wear_reply.png
new file mode 100644
index 0000000..0790ee8
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_wear_reply.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_avatar_shadow.png b/res/drawable-xxhdpi/ic_widget_avatar_shadow.png
new file mode 100644
index 0000000..ea4e26d
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_widget_avatar_shadow.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_list.png b/res/drawable-xxhdpi/ic_widget_list.png
new file mode 100644
index 0000000..c370ee8
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_widget_list.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_work_profile.png b/res/drawable-xxhdpi/ic_work_profile.png
new file mode 100644
index 0000000..de257e7
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_work_profile.png
Binary files differ
diff --git a/res/drawable-xxhdpi/msg_bubble_error.9.png b/res/drawable-xxhdpi/msg_bubble_error.9.png
new file mode 100644
index 0000000..f8bdc96
--- /dev/null
+++ b/res/drawable-xxhdpi/msg_bubble_error.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/msg_bubble_incoming.9.png b/res/drawable-xxhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..ab693b3
--- /dev/null
+++ b/res/drawable-xxhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/msg_bubble_input.9.png b/res/drawable-xxhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..de41ef4
--- /dev/null
+++ b/res/drawable-xxhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/msg_bubble_outgoing.9.png b/res/drawable-xxhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..5b2a2ff
--- /dev/null
+++ b/res/drawable-xxhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/permissions.png b/res/drawable-xxhdpi/permissions.png
new file mode 100644
index 0000000..fd61476
--- /dev/null
+++ b/res/drawable-xxhdpi/permissions.png
Binary files differ
diff --git a/res/drawable-xxhdpi/swipe_shadow.9.png b/res/drawable-xxhdpi/swipe_shadow.9.png
new file mode 100644
index 0000000..0491faa
--- /dev/null
+++ b/res/drawable-xxhdpi/swipe_shadow.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/swipe_shadow_drag.9.png b/res/drawable-xxhdpi/swipe_shadow_drag.9.png
new file mode 100644
index 0000000..0153c5b
--- /dev/null
+++ b/res/drawable-xxhdpi/swipe_shadow_drag.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_btn_bg_normal.9.png b/res/drawable-xxhdpi/tab_btn_bg_normal.9.png
new file mode 100644
index 0000000..9f3a0f9
--- /dev/null
+++ b/res/drawable-xxhdpi/tab_btn_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_btn_bg_pressed.9.png b/res/drawable-xxhdpi/tab_btn_bg_pressed.9.png
new file mode 100644
index 0000000..53f226e
--- /dev/null
+++ b/res/drawable-xxhdpi/tab_btn_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_hr.9.png b/res/drawable-xxhdpi/widget_hr.9.png
new file mode 100644
index 0000000..375272b
--- /dev/null
+++ b/res/drawable-xxhdpi/widget_hr.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_msg_bubble_incoming.9.png b/res/drawable-xxhdpi/widget_msg_bubble_incoming.9.png
new file mode 100644
index 0000000..5093c23
--- /dev/null
+++ b/res/drawable-xxhdpi/widget_msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_msg_bubble_outgoing.9.png b/res/drawable-xxhdpi/widget_msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..6ae5608
--- /dev/null
+++ b/res/drawable-xxhdpi/widget_msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/contact_popup_background.9.png b/res/drawable-xxxhdpi/contact_popup_background.9.png
new file mode 100644
index 0000000..30919fa
--- /dev/null
+++ b/res/drawable-xxxhdpi/contact_popup_background.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/fab_new_message_static_shadow.png b/res/drawable-xxxhdpi/fab_new_message_static_shadow.png
new file mode 100644
index 0000000..e1d16a6
--- /dev/null
+++ b/res/drawable-xxxhdpi/fab_new_message_static_shadow.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_add_white.png b/res/drawable-xxxhdpi/ic_add_white.png
new file mode 100644
index 0000000..0ed23b1
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_add_white.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_archive_small_dark.png b/res/drawable-xxxhdpi/ic_archive_small_dark.png
new file mode 100644
index 0000000..c380363
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_archive_small_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_archive_undo_small_dark.png b/res/drawable-xxxhdpi/ic_archive_undo_small_dark.png
new file mode 100644
index 0000000..b2e4f8b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_archive_undo_small_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_arrow_back_light.png b/res/drawable-xxxhdpi/ic_arrow_back_light.png
new file mode 100644
index 0000000..54a5687
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_arrow_back_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_attachment_dark.png b/res/drawable-xxxhdpi/ic_attachment_dark.png
new file mode 100644
index 0000000..7cf871a
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_attachment_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_audio_light.png b/res/drawable-xxxhdpi/ic_audio_light.png
new file mode 100644
index 0000000..768ac89
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_audio_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_audio_pause.png b/res/drawable-xxxhdpi/ic_audio_pause.png
new file mode 100644
index 0000000..f7ae29f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_audio_pause.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_audio_play.png b/res/drawable-xxxhdpi/ic_audio_play.png
new file mode 100644
index 0000000..71f21e7
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_audio_play.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_camera_front_light.png b/res/drawable-xxxhdpi/ic_camera_front_light.png
new file mode 100644
index 0000000..3af175b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_camera_front_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_camera_light.png b/res/drawable-xxxhdpi/ic_camera_light.png
new file mode 100644
index 0000000..c3484b6
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_camera_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_camera_rear_light.png b/res/drawable-xxxhdpi/ic_camera_rear_light.png
new file mode 100644
index 0000000..c59b65b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_camera_rear_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_cancel_small_dark.png b/res/drawable-xxxhdpi/ic_cancel_small_dark.png
new file mode 100644
index 0000000..f454d2a
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_cancel_small_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_cancel_small_light.png b/res/drawable-xxxhdpi/ic_cancel_small_light.png
new file mode 100644
index 0000000..cce1904
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_cancel_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkbox_blank_light.png b/res/drawable-xxxhdpi/ic_checkbox_blank_light.png
new file mode 100644
index 0000000..ad983af
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkbox_blank_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkbox_light.png b/res/drawable-xxxhdpi/ic_checkbox_light.png
new file mode 100644
index 0000000..f4c0cfc
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkbox_outline_light.png b/res/drawable-xxxhdpi/ic_checkbox_outline_light.png
new file mode 100644
index 0000000..eb0a803
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkbox_outline_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png b/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png
new file mode 100644
index 0000000..0c2a7d5
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_large.png b/res/drawable-xxxhdpi/ic_checkmark_large.png
new file mode 100644
index 0000000..8119ff2
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkmark_large.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_large_light.png b/res/drawable-xxxhdpi/ic_checkmark_large_light.png
new file mode 100644
index 0000000..dddac27
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkmark_large_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_small_light.png b/res/drawable-xxxhdpi/ic_checkmark_small_light.png
new file mode 100644
index 0000000..380f4e8
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_checkmark_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_content_copy_dark.png b/res/drawable-xxxhdpi/ic_content_copy_dark.png
new file mode 100644
index 0000000..24dc390
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_content_copy_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_delete_small_dark.png b/res/drawable-xxxhdpi/ic_delete_small_dark.png
new file mode 100644
index 0000000..497e7a7
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_delete_small_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_dnd_on_dark.png b/res/drawable-xxxhdpi/ic_dnd_on_dark.png
new file mode 100644
index 0000000..de2f17b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_dnd_on_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_failed_light.png b/res/drawable-xxxhdpi/ic_failed_light.png
new file mode 100644
index 0000000..53d374c
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_failed_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_failed_status_red.png b/res/drawable-xxxhdpi/ic_failed_status_red.png
new file mode 100644
index 0000000..ee1ed24
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_failed_status_red.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_file_download_dark.png b/res/drawable-xxxhdpi/ic_file_download_dark.png
new file mode 100644
index 0000000..0012e5e
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_file_download_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_file_download_light.png b/res/drawable-xxxhdpi/ic_file_download_light.png
new file mode 100644
index 0000000..6d7ca08
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_file_download_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_forward_dark.png b/res/drawable-xxxhdpi/ic_forward_dark.png
new file mode 100644
index 0000000..6408fb9
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_forward_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_image_light.png b/res/drawable-xxxhdpi/ic_image_light.png
new file mode 100644
index 0000000..0d229e2
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_image_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_ime_light.png b/res/drawable-xxxhdpi/ic_ime_light.png
new file mode 100644
index 0000000..031d086
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_ime_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_info_dark.png b/res/drawable-xxxhdpi/ic_info_dark.png
new file mode 100644
index 0000000..107385b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_info_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_launcher.png b/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..9ac88b4
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_audio_mic.png b/res/drawable-xxxhdpi/ic_mp_audio_mic.png
new file mode 100644
index 0000000..9f51c4b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_audio_mic.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_camera_small_light.png b/res/drawable-xxxhdpi/ic_mp_camera_small_light.png
new file mode 100644
index 0000000..d6d8c9d
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_camera_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_capture_stop_large_light.png b/res/drawable-xxxhdpi/ic_mp_capture_stop_large_light.png
new file mode 100644
index 0000000..30e725f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_capture_stop_large_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_full_screen_light.png b/res/drawable-xxxhdpi/ic_mp_full_screen_light.png
new file mode 100644
index 0000000..4860109
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_full_screen_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_video_large_light.png b/res/drawable-xxxhdpi/ic_mp_video_large_light.png
new file mode 100644
index 0000000..32c4317
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_video_large_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_mp_video_small_light.png b/res/drawable-xxxhdpi/ic_mp_video_small_light.png
new file mode 100644
index 0000000..6d2a14b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_mp_video_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_music.png b/res/drawable-xxxhdpi/ic_music.png
new file mode 100644
index 0000000..11d67ae
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_music.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_notifications_off_dark.png b/res/drawable-xxxhdpi/ic_notifications_off_dark.png
new file mode 100644
index 0000000..10ac318
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_notifications_off_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_notifications_off_light.png b/res/drawable-xxxhdpi/ic_notifications_off_light.png
new file mode 100644
index 0000000..8eb5782
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_notifications_off_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_notifications_off_small_light.png b/res/drawable-xxxhdpi/ic_notifications_off_small_light.png
new file mode 100644
index 0000000..3756943
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_notifications_off_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_notifications_on_dark.png b/res/drawable-xxxhdpi/ic_notifications_on_dark.png
new file mode 100644
index 0000000..3896212
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_notifications_on_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_notifications_on_light.png b/res/drawable-xxxhdpi/ic_notifications_on_light.png
new file mode 100644
index 0000000..47794fd
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_notifications_on_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_numeric_dialpad.png b/res/drawable-xxxhdpi/ic_numeric_dialpad.png
new file mode 100644
index 0000000..5e0986c
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_numeric_dialpad.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_oobe_conv_list.png b/res/drawable-xxxhdpi/ic_oobe_conv_list.png
new file mode 100644
index 0000000..0decb23
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_oobe_conv_list.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_oobe_freq_list.png b/res/drawable-xxxhdpi/ic_oobe_freq_list.png
new file mode 100644
index 0000000..4522cb6
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_oobe_freq_list.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_people_add_light.png b/res/drawable-xxxhdpi/ic_people_add_light.png
new file mode 100644
index 0000000..5db76a9
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_people_add_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_person_add_dark.png b/res/drawable-xxxhdpi/ic_person_add_dark.png
new file mode 100644
index 0000000..37e252f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_person_add_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_person_add_light.png b/res/drawable-xxxhdpi/ic_person_add_light.png
new file mode 100644
index 0000000..b279246
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_person_add_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_person_light.png b/res/drawable-xxxhdpi/ic_person_light.png
new file mode 100644
index 0000000..59853fc
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_person_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_person_light_large.png b/res/drawable-xxxhdpi/ic_person_light_large.png
new file mode 100644
index 0000000..44d4809
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_person_light_large.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_phone_small_light.png b/res/drawable-xxxhdpi/ic_phone_small_light.png
new file mode 100644
index 0000000..433e4a7
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_phone_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_photo_library_light.png b/res/drawable-xxxhdpi/ic_photo_library_light.png
new file mode 100644
index 0000000..9fe62f4
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_photo_library_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_preview_pause.png b/res/drawable-xxxhdpi/ic_preview_pause.png
new file mode 100644
index 0000000..72ee671
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_preview_pause.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_preview_play.png b/res/drawable-xxxhdpi/ic_preview_play.png
new file mode 100644
index 0000000..b54968f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_preview_play.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_remove_light.png b/res/drawable-xxxhdpi/ic_remove_light.png
new file mode 100644
index 0000000..e32a4dc
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_remove_small_light.png b/res/drawable-xxxhdpi/ic_remove_small_light.png
new file mode 100644
index 0000000..0e0cb05
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_remove_small_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_save_dark.png b/res/drawable-xxxhdpi/ic_save_dark.png
new file mode 100644
index 0000000..2819de2
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_save_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_save_light.png b/res/drawable-xxxhdpi/ic_save_light.png
new file mode 100644
index 0000000..ba7564b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_save_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_send_dark.png b/res/drawable-xxxhdpi/ic_send_dark.png
new file mode 100644
index 0000000..5f52b29
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_send_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_send_light.png b/res/drawable-xxxhdpi/ic_send_light.png
new file mode 100644
index 0000000..b4e8563
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_send_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_share_dark.png b/res/drawable-xxxhdpi/ic_share_dark.png
new file mode 100644
index 0000000..a6ddd2d
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_share_dark.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_share_light.png b/res/drawable-xxxhdpi/ic_share_light.png
new file mode 100644
index 0000000..ac63637
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_share_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_sim_card_send.png b/res/drawable-xxxhdpi/ic_sim_card_send.png
new file mode 100644
index 0000000..0db661b
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_sim_card_send.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_sms_delivery_ok.png b/res/drawable-xxxhdpi/ic_sms_delivery_ok.png
new file mode 100644
index 0000000..487525d
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_sms_delivery_ok.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_sms_light.png b/res/drawable-xxxhdpi/ic_sms_light.png
new file mode 100644
index 0000000..98d1bc8
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_sms_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_sms_multi_light.png b/res/drawable-xxxhdpi/ic_sms_multi_light.png
new file mode 100644
index 0000000..e2f4bfc
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_sms_multi_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_video_play_light.png b/res/drawable-xxxhdpi/ic_video_play_light.png
new file mode 100644
index 0000000..9192f84
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_video_play_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_wear_reply.png b/res/drawable-xxxhdpi/ic_wear_reply.png
new file mode 100644
index 0000000..34065f6
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_wear_reply.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_widget_avatar_shadow.png b/res/drawable-xxxhdpi/ic_widget_avatar_shadow.png
new file mode 100644
index 0000000..83d02ce
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_widget_avatar_shadow.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_widget_list.png b/res/drawable-xxxhdpi/ic_widget_list.png
new file mode 100644
index 0000000..f316487
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_widget_list.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_work_profile.png b/res/drawable-xxxhdpi/ic_work_profile.png
new file mode 100644
index 0000000..72292bd
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_work_profile.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/msg_bubble_error.9.png b/res/drawable-xxxhdpi/msg_bubble_error.9.png
new file mode 100644
index 0000000..fb8161c
--- /dev/null
+++ b/res/drawable-xxxhdpi/msg_bubble_error.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/msg_bubble_incoming.9.png b/res/drawable-xxxhdpi/msg_bubble_incoming.9.png
new file mode 100644
index 0000000..34130fc
--- /dev/null
+++ b/res/drawable-xxxhdpi/msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/msg_bubble_input.9.png b/res/drawable-xxxhdpi/msg_bubble_input.9.png
new file mode 100644
index 0000000..d330459
--- /dev/null
+++ b/res/drawable-xxxhdpi/msg_bubble_input.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/msg_bubble_outgoing.9.png b/res/drawable-xxxhdpi/msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..cfd5734
--- /dev/null
+++ b/res/drawable-xxxhdpi/msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/permissions.png b/res/drawable-xxxhdpi/permissions.png
new file mode 100644
index 0000000..2a7a0d7
--- /dev/null
+++ b/res/drawable-xxxhdpi/permissions.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/swipe_shadow.9.png b/res/drawable-xxxhdpi/swipe_shadow.9.png
new file mode 100644
index 0000000..4726ef4
--- /dev/null
+++ b/res/drawable-xxxhdpi/swipe_shadow.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/swipe_shadow_drag.9.png b/res/drawable-xxxhdpi/swipe_shadow_drag.9.png
new file mode 100644
index 0000000..d48e311
--- /dev/null
+++ b/res/drawable-xxxhdpi/swipe_shadow_drag.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/tab_btn_bg_normal.9.png b/res/drawable-xxxhdpi/tab_btn_bg_normal.9.png
new file mode 100644
index 0000000..1290a0d
--- /dev/null
+++ b/res/drawable-xxxhdpi/tab_btn_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/tab_btn_bg_pressed.9.png b/res/drawable-xxxhdpi/tab_btn_bg_pressed.9.png
new file mode 100644
index 0000000..9fce798
--- /dev/null
+++ b/res/drawable-xxxhdpi/tab_btn_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/widget_hr.9.png b/res/drawable-xxxhdpi/widget_hr.9.png
new file mode 100644
index 0000000..80fdaf6
--- /dev/null
+++ b/res/drawable-xxxhdpi/widget_hr.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/widget_msg_bubble_incoming.9.png b/res/drawable-xxxhdpi/widget_msg_bubble_incoming.9.png
new file mode 100644
index 0000000..383133e
--- /dev/null
+++ b/res/drawable-xxxhdpi/widget_msg_bubble_incoming.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/widget_msg_bubble_outgoing.9.png b/res/drawable-xxxhdpi/widget_msg_bubble_outgoing.9.png
new file mode 100644
index 0000000..daf33b5
--- /dev/null
+++ b/res/drawable-xxxhdpi/widget_msg_bubble_outgoing.9.png
Binary files differ
diff --git a/res/drawable/attachment_audio_preview_background.xml b/res/drawable/attachment_audio_preview_background.xml
new file mode 100644
index 0000000..8b62415
--- /dev/null
+++ b/res/drawable/attachment_audio_preview_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/attachment_image_placeholder_background.xml b/res/drawable/attachment_image_placeholder_background.xml
new file mode 100644
index 0000000..b3315e8
--- /dev/null
+++ b/res/drawable/attachment_image_placeholder_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="@dimen/attachment_rounded_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/attachment_more_items_background.xml b/res/drawable/attachment_more_items_background.xml
new file mode 100644
index 0000000..0ef8e61
--- /dev/null
+++ b/res/drawable/attachment_more_items_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/attachment_preview_more_items_text_background" />
+    <corners android:radius="@dimen/attachment_rounded_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/attachment_vcard_preview_background.xml b/res/drawable/attachment_vcard_preview_background.xml
new file mode 100644
index 0000000..8b62415
--- /dev/null
+++ b/res/drawable/attachment_vcard_preview_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/audio_progress_bar_background_incoming.xml b/res/drawable/audio_progress_bar_background_incoming.xml
new file mode 100644
index 0000000..990e1de
--- /dev/null
+++ b/res/drawable/audio_progress_bar_background_incoming.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <stroke
+        android:color="@color/conversation_background"
+        android:width="1dp" />
+    <corners android:radius="3dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/audio_progress_bar_background_outgoing.xml b/res/drawable/audio_progress_bar_background_outgoing.xml
new file mode 100644
index 0000000..351cf18
--- /dev/null
+++ b/res/drawable/audio_progress_bar_background_outgoing.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/conversation_background" />
+    <corners android:radius="3dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/audio_progress_bar_progress.xml b/res/drawable/audio_progress_bar_progress.xml
new file mode 100644
index 0000000..a70ff32
--- /dev/null
+++ b/res/drawable/audio_progress_bar_progress.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/audio_progress_bar_color" />
+    <corners android:radius="3dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/audio_record_control_button_background.xml b/res/drawable/audio_record_control_button_background.xml
new file mode 100644
index 0000000..02f329e
--- /dev/null
+++ b/res/drawable/audio_record_control_button_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <stroke
+        android:width="1dp"
+        android:color="@color/audio_record_control_button_stroke"/>
+    <solid
+        android:color="@android:color/white"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/chips_dropdown_background.xml b/res/drawable/chips_dropdown_background.xml
new file mode 100644
index 0000000..48a727d
--- /dev/null
+++ b/res/drawable/chips_dropdown_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/chips_dropdown_background_activated"
+          android:state_activated="true"/>
+    <item android:drawable="@color/chips_dropdown_background_pressed" android:state_pressed="true"/>
+    <item android:drawable="@android:color/white"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/chips_dropdown_text_color.xml b/res/drawable/chips_dropdown_text_color.xml
new file mode 100644
index 0000000..5f06751
--- /dev/null
+++ b/res/drawable/chips_dropdown_text_color.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_activated="true" android:color="@android:color/white" />
+    <item android:state_checked="true" android:color="@android:color/white" />
+    <item android:state_selected="true" android:color="@android:color/white" />
+    <item android:color="#333333"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/compose_chips_divider_gradient.xml b/res/drawable/compose_chips_divider_gradient.xml
new file mode 100644
index 0000000..65c6601
--- /dev/null
+++ b/res/drawable/compose_chips_divider_gradient.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:startColor="@color/compose_contact_divider"
+        android:endColor="@android:color/transparent"
+        android:angle="-90"
+        android:dither="true"
+     />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/contact_picker_tab_background_selector.xml b/res/drawable/contact_picker_tab_background_selector.xml
new file mode 100644
index 0000000..78c443b
--- /dev/null
+++ b/res/drawable/contact_picker_tab_background_selector.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:drawable="@color/contact_picker_tab_pressed" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/contacts_fastscroll_label_left.xml b/res/drawable/contacts_fastscroll_label_left.xml
new file mode 100644
index 0000000..5ed079a
--- /dev/null
+++ b/res/drawable/contacts_fastscroll_label_left.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:insetLeft="@dimen/fastscroll_preview_margin_left_right">
+    <shape
+            android:shape="rectangle">
+        <corners
+                android:topLeftRadius="@dimen/fastscroll_preview_corner_radius"
+                android:topRightRadius="@dimen/fastscroll_preview_corner_radius"
+                android:bottomRightRadius="@dimen/fastscroll_preview_corner_radius" />
+        <solid android:color="@color/action_bar_background_color" />
+    </shape>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/contacts_fastscroll_label_right.xml b/res/drawable/contacts_fastscroll_label_right.xml
new file mode 100644
index 0000000..67c4622
--- /dev/null
+++ b/res/drawable/contacts_fastscroll_label_right.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:insetRight="@dimen/fastscroll_preview_margin_left_right">
+    <shape
+            android:shape="rectangle">
+        <corners
+                android:topLeftRadius="@dimen/fastscroll_preview_corner_radius"
+                android:topRightRadius="@dimen/fastscroll_preview_corner_radius"
+                android:bottomLeftRadius="@dimen/fastscroll_preview_corner_radius" />
+        <solid android:color="@color/action_bar_background_color" />
+    </shape>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/conversation_compose_divider_gradient.xml b/res/drawable/conversation_compose_divider_gradient.xml
new file mode 100644
index 0000000..2c8a180
--- /dev/null
+++ b/res/drawable/conversation_compose_divider_gradient.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:startColor="@color/conversation_compose_divider_start"
+        android:endColor="@android:color/transparent"
+        android:angle="90"
+        android:dither="true"
+     />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/default_image.xml b/res/drawable/default_image.xml
new file mode 100644
index 0000000..749e73b
--- /dev/null
+++ b/res/drawable/default_image.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!--
+     This overrides frameworks/opt/photoviewer/res/drawable/default_image.xml
+     as a workaround for http://b/17510888. It should be removed after that
+     but is fixed.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+
+  <!-- these are the dimensions of the original default_image.png -->
+  <size
+      android:width="215dp"
+      android:height="210dp" />
+
+  <solid
+      android:color="#00000000" />
+
+</shape>
diff --git a/res/drawable/fab_new_message_bg.xml b/res/drawable/fab_new_message_bg.xml
new file mode 100644
index 0000000..741b4b5
--- /dev/null
+++ b/res/drawable/fab_new_message_bg.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<layer-list
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <bitmap
+            android:src="@drawable/fab_new_message_static_shadow" />
+    </item>
+    <item
+        android:left="2dp"
+        android:right="2dp"
+        android:bottom="@dimen/fab_padding_bottom">
+        <selector>
+            <item
+                android:state_pressed="true">
+                <shape
+                    android:shape="oval" >
+                    <solid
+                        android:color="@color/fab_pressed_color" />
+                </shape>
+            </item>
+            <item>
+                <shape
+                    android:shape="oval" >
+                    <solid
+                        android:color="@color/fab_color" />
+                </shape>
+            </item>
+        </selector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/fastscroll_preview_left.xml b/res/drawable/fastscroll_preview_left.xml
new file mode 100644
index 0000000..165a222
--- /dev/null
+++ b/res/drawable/fastscroll_preview_left.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:topLeftRadius="@dimen/fastscroll_preview_corner_radius"
+        android:topRightRadius="@dimen/fastscroll_preview_corner_radius"
+        android:bottomRightRadius="@dimen/fastscroll_preview_corner_radius" />
+    <solid android:color="@color/color_filter_base_color" />
+</shape>
diff --git a/res/drawable/fastscroll_preview_right.xml b/res/drawable/fastscroll_preview_right.xml
new file mode 100644
index 0000000..7c0dc09
--- /dev/null
+++ b/res/drawable/fastscroll_preview_right.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:topLeftRadius="@dimen/fastscroll_preview_corner_radius"
+        android:topRightRadius="@dimen/fastscroll_preview_corner_radius"
+        android:bottomLeftRadius="@dimen/fastscroll_preview_corner_radius" />
+    <solid android:color="@color/color_filter_base_color" />
+</shape>
diff --git a/res/drawable/fastscroll_thumb.xml b/res/drawable/fastscroll_thumb.xml
new file mode 100644
index 0000000..be7c96f
--- /dev/null
+++ b/res/drawable/fastscroll_thumb.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/fastscroll_thumb_color" />
+    <size android:width="@dimen/fastscroll_track_width"
+        android:height="@dimen/fastscroll_thumb_height" />
+</shape>
diff --git a/res/drawable/fastscroll_thumb_pressed.xml b/res/drawable/fastscroll_thumb_pressed.xml
new file mode 100644
index 0000000..39de5a6
--- /dev/null
+++ b/res/drawable/fastscroll_thumb_pressed.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/color_filter_base_color" />
+    <size android:width="@dimen/fastscroll_track_width"
+        android:height="@dimen/fastscroll_thumb_height" />
+</shape>
diff --git a/res/drawable/fastscroll_track.xml b/res/drawable/fastscroll_track.xml
new file mode 100644
index 0000000..f3bf96d
--- /dev/null
+++ b/res/drawable/fastscroll_track.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+    <solid android:color="@color/fastscroll_track_color" />
+    <size android:width="@dimen/fastscroll_track_width" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/gallery_checkbox_selector.xml b/res/drawable/gallery_checkbox_selector.xml
new file mode 100644
index 0000000..cdd9734
--- /dev/null
+++ b/res/drawable/gallery_checkbox_selector.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_checked="true"
+        android:drawable="@drawable/ic_checkbox_light" />
+    <item
+        android:state_selected="true"
+        android:drawable="@drawable/ic_checkbox_light" />
+    <item
+        android:drawable="@drawable/ic_checkbox_blank_light" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/gallery_image_background_selector.xml b/res/drawable/gallery_image_background_selector.xml
new file mode 100644
index 0000000..0b902fd
--- /dev/null
+++ b/res/drawable/gallery_image_background_selector.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:drawable="@color/gallery_image_pressed" />
+    <item
+        android:drawable="@android:color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/generic_video_icon.xml b/res/drawable/generic_video_icon.xml
new file mode 100644
index 0000000..e98cb94
--- /dev/null
+++ b/res/drawable/generic_video_icon.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 Google Inc.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="@color/generic_video_icon"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/mediapicker_tab_button_background.xml b/res/drawable/mediapicker_tab_button_background.xml
new file mode 100644
index 0000000..08dbf5c
--- /dev/null
+++ b/res/drawable/mediapicker_tab_button_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:drawable="@color/background_item_pressed" />
+    <item
+        android:state_activated="true"
+        android:drawable="@color/background_item_activated" />
+    <item
+        android:drawable="@color/background_item_transparent" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/message_bubble_incoming_no_arrow.xml b/res/drawable/message_bubble_incoming_no_arrow.xml
new file mode 100644
index 0000000..d234508
--- /dev/null
+++ b/res/drawable/message_bubble_incoming_no_arrow.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_filter_base_color" />
+    <corners android:radius="3dp" />
+</shape>
diff --git a/res/drawable/message_bubble_outgoing_no_arrow.xml b/res/drawable/message_bubble_outgoing_no_arrow.xml
new file mode 100644
index 0000000..d234508
--- /dev/null
+++ b/res/drawable/message_bubble_outgoing_no_arrow.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/color_filter_base_color" />
+    <corners android:radius="3dp" />
+</shape>
diff --git a/res/drawable/send_arrow_background.xml b/res/drawable/send_arrow_background.xml
new file mode 100644
index 0000000..4434997
--- /dev/null
+++ b/res/drawable/send_arrow_background.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true">
+        <shape
+            android:shape="oval" >
+            <solid android:color="@color/compose_message_send_color_pressed" />
+        </shape>
+     </item>
+    <item>
+        <shape
+            android:shape="oval" >
+            <solid android:color="@color/compose_message_send_color" />
+        </shape>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/sim_selector_background_gradient.xml b/res/drawable/sim_selector_background_gradient.xml
new file mode 100644
index 0000000..ea7e440
--- /dev/null
+++ b/res/drawable/sim_selector_background_gradient.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:startColor="@color/sim_selector_background_start"
+        android:endColor="@color/sim_selector_background_end"
+        android:angle="90"
+        android:dither="true"
+     />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/subject_editor_bubble.xml b/res/drawable/subject_editor_bubble.xml
new file mode 100644
index 0000000..21f0248
--- /dev/null
+++ b/res/drawable/subject_editor_bubble.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+         <shape>
+             <solid android:color="@color/subject_editor_bubble" />
+             <corners android:radius="3dp" />
+         </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/tab_btn_bg.xml b/res/drawable/tab_btn_bg.xml
new file mode 100644
index 0000000..f7f03dd
--- /dev/null
+++ b/res/drawable/tab_btn_bg.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/tab_btn_bg_pressed" />
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/tab_btn_bg_pressed" />
+    <item
+        android:drawable="@drawable/tab_btn_bg_normal" />
+</selector>
diff --git a/res/drawable/transparent_button_background.xml b/res/drawable/transparent_button_background.xml
new file mode 100644
index 0000000..08dbf5c
--- /dev/null
+++ b/res/drawable/transparent_button_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:drawable="@color/background_item_pressed" />
+    <item
+        android:state_activated="true"
+        android:drawable="@color/background_item_activated" />
+    <item
+        android:drawable="@color/background_item_transparent" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/widget_bottom_background.xml b/res/drawable/widget_bottom_background.xml
new file mode 100644
index 0000000..198b2d6
--- /dev/null
+++ b/res/drawable/widget_bottom_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/widget_background_color" />
+    <corners android:radius="2dp"
+             android:bottomRightRadius="2dp"
+             android:topRightRadius="0dp"
+             android:bottomLeftRadius="2dp"
+             android:topLeftRadius="0dp"
+             />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/widget_top_background.xml b/res/drawable/widget_top_background.xml
new file mode 100644
index 0000000..1476c95
--- /dev/null
+++ b/res/drawable/widget_top_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/action_bar_background_color" />
+    <corners android:radius="2dp"
+             android:bottomRightRadius="0dp"
+             android:topRightRadius="2dp"
+             android:bottomLeftRadius="0dp"
+             android:topLeftRadius="2dp"
+             />
+</shape>
\ No newline at end of file
diff --git a/res/layout/action_bar_conversation_name.xml b/res/layout/action_bar_conversation_name.xml
new file mode 100644
index 0000000..586cf83
--- /dev/null
+++ b/res/layout/action_bar_conversation_name.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/conversation_title_container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="fill_horizontal" >
+
+      <TextView
+            android:id="@+id/conversation_title"
+            style="@style/ConversationActionBarTitleTextStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/add_contacts_confirmation_dialog_body.xml b/res/layout/add_contacts_confirmation_dialog_body.xml
new file mode 100644
index 0000000..07f3d0f
--- /dev/null
+++ b/res/layout/add_contacts_confirmation_dialog_body.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center_vertical"
+    android:padding="20dp" >
+
+    <com.android.messaging.ui.ContactIconView
+        android:id="@+id/contact_icon"
+        android:layout_width="@dimen/conversation_list_contact_icon_size"
+        android:layout_height="@dimen/conversation_list_contact_icon_size"
+        android:importantForAccessibility="no"
+        app:iconSize="large"
+        android:layout_gravity="center_vertical"
+        android:clickable="true" />
+
+    <TextView
+        android:id="@+id/participant_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:maxLines="1"
+        android:ellipsize="end"
+        style="@style/AddContactConfirmationTextStyle"
+        android:layout_gravity="center_vertical" />
+
+</LinearLayout>
diff --git a/res/layout/all_contacts_list_view.xml b/res/layout/all_contacts_list_view.xml
new file mode 100644
index 0000000..fe05c4d
--- /dev/null
+++ b/res/layout/all_contacts_list_view.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ListView
+        android:id="@+id/all_contacts_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        android:clipToPadding="false"
+        android:divider="@null"
+        android:dividerHeight="0px"
+        android:fastScrollEnabled="true" />
+
+    <include
+        layout="@layout/list_empty_view"
+        android:id="@+id/empty_view"
+        android:visibility="gone" />
+
+</FrameLayout>
diff --git a/res/layout/apn_preference_layout.xml b/res/layout/apn_preference_layout.xml
new file mode 100644
index 0000000..12693d4
--- /dev/null
+++ b/res/layout/apn_preference_layout.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<!--
+    This is the layout file for an ApnPreference in the ApnSettingsActivity. The preference
+    is a list item.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    style="@style/ApnPreferenceLayoutStyle">
+
+    <RelativeLayout
+        android:id="@+id/text_layout"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:layout_weight="1"
+        android:focusable="true"
+        android:background="?android:attr/selectableItemBackground">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:focusable="true"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem" />
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="2" />
+
+    </RelativeLayout>
+
+    <RadioButton
+        android:id="@+id/apn_radiobutton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip"
+        android:layout_gravity="center_vertical"
+        android:clickable="true" />
+
+</LinearLayout>
diff --git a/res/layout/attachment_chooser_activity.xml b/res/layout/attachment_chooser_activity.xml
new file mode 100644
index 0000000..850716e
--- /dev/null
+++ b/res/layout/attachment_chooser_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment"
+    android:id="@+id/attachment_chooser_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/attachment_chooser_audio.xml b/res/layout/attachment_chooser_audio.xml
new file mode 100644
index 0000000..ea2f431
--- /dev/null
+++ b/res/layout/attachment_chooser_audio.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/audio_attachment_background"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/attachment_chooser_audio_background">
+
+    <com.android.messaging.ui.AudioAttachmentView
+        android:id="@+id/audio_attachment_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        app:layoutMode="compact" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_chooser_fragment.xml b/res/layout/attachment_chooser_fragment.xml
new file mode 100644
index 0000000..15e249a
--- /dev/null
+++ b/res/layout/attachment_chooser_fragment.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.attachmentchooser.AttachmentGridView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/grid"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="6dp"
+    android:columnWidth="@dimen/attachment_grid_image_cell_size"
+    android:numColumns="auto_fit"
+    android:verticalSpacing="6dp"
+    android:horizontalSpacing="6dp"
+    android:stretchMode="columnWidth"
+    android:gravity="center"
+    android:clipToPadding="false" />
diff --git a/res/layout/attachment_chooser_image.xml b/res/layout/attachment_chooser_image.xml
new file mode 100644
index 0000000..b635161
--- /dev/null
+++ b/res/layout/attachment_chooser_image.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.AsyncImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/attachment_image_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:minWidth="@dimen/single_attachment_min_dimen"
+    android:minHeight="@dimen/single_attachment_min_dimen"
+    android:scaleType="centerCrop"
+    android:adjustViewBounds="true" />
diff --git a/res/layout/attachment_chooser_vcard.xml b/res/layout/attachment_chooser_vcard.xml
new file mode 100644
index 0000000..e6f1072
--- /dev/null
+++ b/res/layout/attachment_chooser_vcard.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/attachment_chooser_vcard_background">
+
+    <com.android.messaging.ui.PersonItemView
+        android:id="@+id/vcard_attachment_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_chooser_video.xml b/res/layout/attachment_chooser_video.xml
new file mode 100644
index 0000000..4ae4b0a
--- /dev/null
+++ b/res/layout/attachment_chooser_video.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.VideoThumbnailView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/attachment_video_thumbnail"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    app:mode="imageThumbnail"
+    app:allowCrop="true" />
diff --git a/res/layout/attachment_grid_item_view.xml b/res/layout/attachment_grid_item_view.xml
new file mode 100644
index 0000000..639ea64
--- /dev/null
+++ b/res/layout/attachment_grid_item_view.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.attachmentchooser.AttachmentGridItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/attachment_grid_image_cell_size"
+    android:clickable="true">
+
+    <FrameLayout
+        android:id="@+id/attachment_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="?android:attr/selectableItemBackground" />
+
+    <CheckBox
+        android:id="@+id/checkbox"
+        style="@style/AttachmentGridItemViewCheckBoxStyle"
+        android:button="@drawable/gallery_checkbox_selector"
+        android:background="@null"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|end"
+        android:paddingTop="4dp"
+        android:contentDescription="@string/gallery_checkbox_content_description" />
+</com.android.messaging.ui.attachmentchooser.AttachmentGridItemView>
diff --git a/res/layout/attachment_more_text_view.xml b/res/layout/attachment_more_text_view.xml
new file mode 100644
index 0000000..1a99a63
--- /dev/null
+++ b/res/layout/attachment_more_text_view.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/AttachmentPreviewMoreItemsText"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:background="@drawable/attachment_more_items_background" />
\ No newline at end of file
diff --git a/res/layout/attachment_multiple_audio.xml b/res/layout/attachment_multiple_audio.xml
new file mode 100644
index 0000000..48440f0
--- /dev/null
+++ b/res/layout/attachment_multiple_audio.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/audio_attachment_background"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/attachment_audio_preview_background">
+
+    <com.android.messaging.ui.AudioAttachmentView
+        android:id="@+id/audio_attachment_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        app:layoutMode="compact" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_multiple_image.xml b/res/layout/attachment_multiple_image.xml
new file mode 100644
index 0000000..7d911ac
--- /dev/null
+++ b/res/layout/attachment_multiple_image.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<com.android.messaging.ui.AsyncImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/attachment_image_view"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:maxWidth="@dimen/multiple_attachment_preview_width"
+    android:maxHeight="@dimen/multiple_attachment_preview_height"
+    android:scaleType="centerCrop"
+    android:adjustViewBounds="true"
+    app:fadeIn="false"
+    app:cornerRadius="@dimen/attachment_rounded_corner_radius"
+    app:placeholderDrawable="@drawable/attachment_image_placeholder_background" />
diff --git a/res/layout/attachment_multiple_vcard.xml b/res/layout/attachment_multiple_vcard.xml
new file mode 100644
index 0000000..e03d47b
--- /dev/null
+++ b/res/layout/attachment_multiple_vcard.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@drawable/attachment_vcard_preview_background">
+
+    <com.android.messaging.ui.PersonItemView
+        android:id="@+id/vcard_attachment_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_multiple_video.xml b/res/layout/attachment_multiple_video.xml
new file mode 100644
index 0000000..fdbc423
--- /dev/null
+++ b/res/layout/attachment_multiple_video.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<com.android.messaging.ui.VideoThumbnailView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/attachment_video_thumbnail"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    app:mode="imageThumbnail"
+    app:allowCrop="true" />
diff --git a/res/layout/attachment_pending_item.xml b/res/layout/attachment_pending_item.xml
new file mode 100644
index 0000000..3e9bec7
--- /dev/null
+++ b/res/layout/attachment_pending_item.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+    <ImageView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/pending_item_view"
+        android:layout_width="@dimen/pending_attachment_size"
+        android:layout_height="@dimen/pending_attachment_size"
+        android:scaleType="center"
+        android:background="@android:color/white"
+        android:src="@drawable/ic_attachment_dark"
+        android:importantForAccessibility="no"
+        android:contentDescription="@null"/>
+
+    <TextView
+            android:id="@+id/caption"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:maxLines="3"
+            android:ellipsize="end"
+            android:padding="8dp"
+            android:background="@color/message_bubble_color_outgoing"
+            style="@style/ConversationMessage" />
+
+</LinearLayout>
diff --git a/res/layout/attachment_preview.xml b/res/layout/attachment_preview.xml
new file mode 100644
index 0000000..36ea038
--- /dev/null
+++ b/res/layout/attachment_preview.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.AttachmentPreview
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:scrollbars="none">
+
+    <FrameLayout
+        android:id="@+id/attachment_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="right">
+        <FrameLayout
+            android:id="@+id/attachment_view"
+            style="@style/AttachmentPreviewAttachmentStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp" />
+
+        <ImageButton
+            android:id="@+id/close_button"
+            style="@style/AttachmentPreviewCloseButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@null"
+            android:src="@drawable/ic_remove_light"
+            android:contentDescription="@null" />
+    </FrameLayout>
+</com.android.messaging.ui.AttachmentPreview>
\ No newline at end of file
diff --git a/res/layout/attachment_single_audio.xml b/res/layout/attachment_single_audio.xml
new file mode 100644
index 0000000..3ad02a8
--- /dev/null
+++ b/res/layout/attachment_single_audio.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/audio_attachment_background"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/attachment_audio_preview_background"
+    style="@style/AudioAttachmentViewStyle">
+
+    <com.android.messaging.ui.AudioAttachmentView
+        android:id="@+id/audio_attachment_view"
+        android:layout_width="match_parent"
+        android:layout_height="70dp" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_single_image.xml b/res/layout/attachment_single_image.xml
new file mode 100644
index 0000000..7338368
--- /dev/null
+++ b/res/layout/attachment_single_image.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <com.android.messaging.ui.AsyncImageView
+        android:id="@+id/attachment_image_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:minWidth="@dimen/single_attachment_min_dimen"
+        android:minHeight="@dimen/single_attachment_min_dimen"
+        android:maxHeight="@dimen/single_attachment_max_height"
+        android:scaleType="fitCenter"
+        android:adjustViewBounds="true"
+        app:fadeIn="false"
+        app:cornerRadius="@dimen/attachment_rounded_corner_radius" />
+
+    <TextView
+        android:id="@+id/caption"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:maxLines="3"
+        android:ellipsize="end"
+        android:padding="8dp"
+        android:background="@color/message_bubble_color_outgoing"
+        style="@style/ConversationMessage" />
+
+</LinearLayout>
diff --git a/res/layout/attachment_single_vcard.xml b/res/layout/attachment_single_vcard.xml
new file mode 100644
index 0000000..6016593
--- /dev/null
+++ b/res/layout/attachment_single_vcard.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@drawable/attachment_vcard_preview_background">
+
+    <com.android.messaging.ui.PersonItemView
+        android:id="@+id/vcard_attachment_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/message_text_top_padding"
+        android:paddingBottom="@dimen/message_text_bottom_padding"
+        style="@style/VcardAttachmentSingleStyle" />
+
+</FrameLayout>
diff --git a/res/layout/attachment_single_video.xml b/res/layout/attachment_single_video.xml
new file mode 100644
index 0000000..fba594f
--- /dev/null
+++ b/res/layout/attachment_single_video.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<com.android.messaging.ui.VideoThumbnailView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/attachment_video_thumbnail"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:minWidth="120dp"
+    android:minHeight="120dp"
+    android:maxHeight="@dimen/single_attachment_max_height"
+    app:allowCrop="true"
+    app:mode="imageThumbnail" />
diff --git a/res/layout/audio_attachment_view.xml b/res/layout/audio_attachment_view.xml
new file mode 100644
index 0000000..6fcf89c
--- /dev/null
+++ b/res/layout/audio_attachment_view.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- A reusable view that hosts an inline audio player. The view is used by both the media picker
+     and the conversation to show an audio attachment -->
+<merge
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <com.android.messaging.ui.AudioAttachmentPlayPauseButton
+        android:id="@+id/play_pause_button"
+        style="@style/AudioAttachmentViewPlayPauseButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center">
+        <ImageView
+            android:id="@+id/play_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_audio_play"
+            android:contentDescription="@string/audio_play_content_description"/>
+
+        <ImageView
+            android:id="@+id/pause_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_audio_pause"
+            android:contentDescription="@string/audio_pause_content_description"/>
+    </com.android.messaging.ui.AudioAttachmentPlayPauseButton>
+
+    <com.android.messaging.ui.mediapicker.PausableChronometer
+        android:id="@+id/timer"
+        style="@style/AudioAttachmentTimerText"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center" />
+
+    <com.android.messaging.ui.AudioPlaybackProgressBar
+        android:id="@+id/progress"
+        style="@android:style/Widget.ProgressBar.Horizontal"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="@dimen/audio_progress_bar_height"
+        android:layout_gravity="center" />
+
+</merge>
diff --git a/res/layout/blocked_participant_list_item_view.xml b/res/layout/blocked_participant_list_item_view.xml
new file mode 100644
index 0000000..7ac0ec9
--- /dev/null
+++ b/res/layout/blocked_participant_list_item_view.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.BlockedParticipantListItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:padding="@dimen/blocked_participant_list_item_view_padding">
+    <com.android.messaging.ui.ContactIconView
+        android:id="@+id/contact_icon"
+        android:layout_width="@dimen/contact_list_icon_size"
+        android:layout_height="@dimen/contact_list_icon_size"
+        android:importantForAccessibility="no"
+        app:iconSize="normal"
+        android:layout_gravity="center_vertical"/>
+    <TextView
+        android:id="@+id/name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:maxLines="1"
+        android:ellipsize="end"
+        style="@style/ParticipantListItem"
+        android:layout_gravity="center_vertical"
+        android:padding="@dimen/blocked_participant_list_item_view_padding"/>
+    <TextView
+        android:id="@+id/tap_to_unblock"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:textColor="@color/unblock_item_text_color"
+        android:text="@string/tap_to_unblock_message"
+        android:layout_gravity="center_vertical"
+        android:gravity="right"
+        android:padding="@dimen/blocked_participant_list_item_view_padding"/>
+</com.android.messaging.ui.BlockedParticipantListItemView>
diff --git a/res/layout/blocked_participants_activity.xml b/res/layout/blocked_participants_activity.xml
new file mode 100644
index 0000000..e00f20f
--- /dev/null
+++ b/res/layout/blocked_participants_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.BlockedParticipantsFragment"
+    android:id="@+id/blocked_participants_fragment"
+    android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+    android:layout_width="fill_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/blocked_participants_fragment.xml b/res/layout/blocked_participants_fragment.xml
new file mode 100644
index 0000000..7bb3c6a
--- /dev/null
+++ b/res/layout/blocked_participants_fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="fill_parent"
+    android:layout_height="match_parent"
+    android:divider="@null"
+    android:dividerHeight="0px" />
\ No newline at end of file
diff --git a/res/layout/chips_alternates_dropdown_item.xml b/res/layout/chips_alternates_dropdown_item.xml
new file mode 100644
index 0000000..dad052c
--- /dev/null
+++ b/res/layout/chips_alternates_dropdown_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="72dp"
+    android:background="@drawable/chips_dropdown_background"
+    android:padding="12dp">
+
+    <com.android.messaging.ui.ContactIconView
+        android:id="@android:id/icon"
+        style="@style/ChipIconStyle"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_gravity="center_vertical"
+        android:importantForAccessibility="no" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ellipsize="middle"
+            android:singleLine="true"
+            android:textAlignment="viewStart"
+            android:textColor="@drawable/chips_dropdown_text_color"
+            android:textSize="16sp" />
+
+        <TextView
+            android:id="@android:id/text1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ellipsize="middle"
+            android:singleLine="true"
+            android:textAlignment="viewStart"
+            android:textColor="@drawable/chips_dropdown_text_color"
+            android:textSize="14sp"/>
+
+    </LinearLayout>
+
+    <ImageView
+        android:id="@android:id/icon1"
+        style="@style/ChipDeleteIconStyle"
+        android:layout_width="36dp"
+        android:layout_height="48dp"
+        android:layout_gravity="center_vertical"
+        android:paddingTop="10dp"
+        android:paddingBottom="10dp"
+        android:contentDescription="@string/chips_delete_content_description" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/compose_message_view.xml b/res/layout/compose_message_view.xml
new file mode 100644
index 0000000..8bb8249
--- /dev/null
+++ b/res/layout/compose_message_view.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversation.ComposeMessageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/message_compose_view_container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+    <!-- Note it may seem off to have the layout_weight="1" on the compose bar and attachment view
+     when it's the media picker that expands, but this is correct because weight also works when
+     there's not enough space.  Any views with positive weights will be shrunk to make space.
+     When the media picker goes full screen, it fills the parent, leaving no room for the compose
+     bar -->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:orientation="vertical">
+
+        <View
+            android:id="@+id/top_margin"
+            android:layout_width="match_parent"
+            android:layout_height="16dp" />
+
+        <include layout="@layout/attachment_preview"
+            android:id="@+id/attachment_draft_view"
+            style="@style/ComposeMessageViewDraftViewStyle"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginBottom="4dp"
+            android:layout_weight="1"
+            android:visibility="gone" />
+
+        <RelativeLayout
+            android:id="@+id/subject_view"
+            style="@style/SubjectViewStyle"
+            android:paddingTop="@dimen/compose_message_subject_top_padding"
+            android:paddingBottom="@dimen/compose_message_subject_bottom_padding"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:orientation="horizontal">
+
+            <com.android.messaging.ui.PlainTextEditText
+                android:background="@drawable/subject_editor_bubble"
+                android:id="@+id/compose_subject_text"
+                style="@style/ConversationComposeSubjectText"
+                android:hint="@string/compose_message_view_subject_hint_text"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:imeOptions="flagNoExtractUi" />
+
+            <ImageButton
+                android:id="@+id/delete_subject_button"
+                style="@style/AttachmentPreviewCloseButtonStyle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@null"
+                android:src="@drawable/ic_remove_light"
+                android:translationY="@dimen/compose_message_subject_cancel_top_offset"
+                android:contentDescription="@string/delete_subject_content_description" />
+
+        </RelativeLayout>
+
+        <!-- Holds all views that create the actual compose box -->
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <!-- Contains compose message bubble and character counter for SMS or attachments size
+                 for MMS which should be left aligned -->
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <!-- Contains media button and compose message bubble whose centers should be
+                vertically aligned -->
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="horizontal">
+
+                    <ImageButton
+                        android:id="@+id/attach_media_button"
+                        style="@style/ComposeMessageViewAttachMediaButtonStyle"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="center_vertical"
+                        android:src="@drawable/ic_attachment_dark"
+                        android:paddingTop="@dimen/compose_message_attachment_padding_topBottom"
+                        android:paddingBottom="@dimen/compose_message_attachment_padding_topBottom"
+                        android:contentDescription="@string/attachMediaButtonContentDescription" />
+
+                    <com.android.messaging.ui.PlainTextEditText
+                        android:id="@+id/compose_message_text"
+                        style="@style/ConversationComposeSendText"
+                        android:layout_height="wrap_content"
+                        android:layout_width="0dp"
+                        android:layout_weight="1"
+                        android:layout_gravity="center"
+                        android:background="@drawable/msg_bubble_input"
+                        android:hint="@string/compose_message_view_hint_text"
+                        android:imeOptions="actionSend|flagNoEnterAction|flagNoExtractUi" />
+
+                </LinearLayout>
+
+                <TextView
+                    android:id="@+id/message_body_size"
+                    style="@style/ComposeMessageViewMessageBodySizeStyle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:maxLines="1"
+                    android:visibility="invisible" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content">
+
+                <FrameLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ComposeMessageViewFrameLayoutStyle"
+                    android:layout_gravity="top" >
+                    <com.android.messaging.ui.conversation.SimIconView
+                        android:id="@+id/self_send_icon"
+                        android:layout_width="@dimen/conversation_message_contact_icon_size"
+                        android:layout_height="@dimen/conversation_message_contact_icon_size"
+                        android:importantForAccessibility="no"
+                        app:iconSize="normal"
+                        app:reveal="true"
+                        android:clickable="true" />
+                    <ImageButton
+                        android:id="@+id/send_message_button"
+                        android:layout_width="@dimen/conversation_message_contact_icon_size"
+                        android:layout_height="@dimen/conversation_message_contact_icon_size"
+                        android:src="@drawable/ic_send_light"
+                        android:background="@drawable/send_arrow_background"
+                        android:contentDescription="@string/sendButtonContentDescription"
+                        android:visibility="gone" />
+                </FrameLayout>
+
+                <TextView
+                    android:id="@+id/mms_indicator"
+                    style="@style/MmsIndicatorStyle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:maxLines="1"
+                    android:visibility="invisible"
+                    android:text="@string/mms_text" />
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/mediapicker_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0" />
+
+</com.android.messaging.ui.conversation.ComposeMessageView>
diff --git a/res/layout/contact_list_item_view.xml b/res/layout/contact_list_item_view.xml
new file mode 100644
index 0000000..71a7370
--- /dev/null
+++ b/res/layout/contact_list_item_view.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.contact.ContactListItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    style="@style/ContactListItemViewStyle"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:background="?android:attr/selectableItemBackground">
+
+    <TextView
+        style="@style/ContactListAlphabetHeader"
+        android:id="@+id/alphabet_header"
+        android:layout_height="wrap_content"
+        android:layout_width="56dp"
+        android:layout_gravity="center_vertical"
+        android:visibility="gone" />
+
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical">
+
+        <com.android.messaging.ui.ContactIconView
+            android:id="@+id/contact_icon"
+            android:layout_width="@dimen/contact_list_icon_size"
+            android:layout_height="@dimen/contact_list_icon_size"
+            android:importantForAccessibility="no"
+            app:iconSize="normal"
+            android:clickable="true" />
+
+        <ImageView
+            android:id="@+id/contact_checkmark"
+            android:layout_width="@dimen/contact_list_icon_size"
+            android:layout_height="@dimen/contact_list_icon_size"
+            android:src="@drawable/ic_checkmark_circle_blue"
+            android:visibility="gone"
+            android:importantForAccessibility="no"
+        android:contentDescription="@null"/>
+
+    </FrameLayout>
+
+    <LinearLayout
+        android:orientation="vertical"
+        style="@style/ContactListItemLinearLayoutStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical" >
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+            <TextView
+                android:id="@+id/contact_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingBottom="4dp"
+                android:singleLine="true"
+                android:maxLines="1"
+                android:ellipsize="end"
+                style="@style/ContactListItem" />
+
+            <ImageView android:id="@+id/work_profile_icon"
+                android:src="@drawable/ic_work_profile"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:scaleType="center"
+                android:layout_gravity="center_vertical"
+                android:visibility="gone" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TextView
+                android:id="@+id/contact_details"
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:maxLines="1"
+                android:ellipsize="end"
+                style="@style/ContactListItemDetail" />
+
+            <TextView
+                android:id="@+id/contact_detail_type"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="@style/ContactListItemDetailType" />
+        </LinearLayout>
+    </LinearLayout>
+</com.android.messaging.ui.contact.ContactListItemView>
diff --git a/res/layout/contact_picker_fragment.xml b/res/layout/contact_picker_fragment.xml
new file mode 100644
index 0000000..78350d7
--- /dev/null
+++ b/res/layout/contact_picker_fragment.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:minHeight="?attr/actionBarSize"
+        android:background="@color/action_bar_background_color"
+        app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
+
+        <com.android.messaging.ui.MaxHeightScrollView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:maxHeight="@dimen/compose_message_chips_view_max_height">
+
+            <com.android.messaging.ui.contact.ContactRecipientAutoCompleteView
+                android:id="@+id/recipient_text_view"
+                style="@style/RecipientEditTextView"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:minHeight="@dimen/compose_message_contacts_height"
+                android:popupBackground="@drawable/contact_popup_background"
+                android:dropDownWidth="match_parent"
+                android:hint="@string/recipient_hint"
+                app:avatarPosition="start"
+                app:chipHeight="@dimen/compose_message_chip_height"
+                app:chipPadding="@dimen/compose_message_chip_padding"
+                app:imageSpanAlignment="baseline"
+                app:unselectedChipTextColor="@color/chips_text_color"
+                app:unselectedChipBackgroundColor="@color/chips_background_color">
+
+                <!-- Put focus on the chips view by default so soft keyboard can be shown -->
+                <requestFocus />
+            </com.android.messaging.ui.contact.ContactRecipientAutoCompleteView>
+
+        </com.android.messaging.ui.MaxHeightScrollView>
+
+    </androidx.appcompat.widget.Toolbar>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+        <com.android.messaging.ui.CustomHeaderViewPager
+            android:id="@+id/contact_pager"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+
+        <View
+            android:id="@+id/compose_contact_divider"
+            android:layout_width="match_parent"
+            android:layout_height="4dp"
+            android:layout_gravity="top"
+            android:background="@drawable/compose_chips_divider_gradient"/>
+    </FrameLayout>
+</LinearLayout>
diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml
new file mode 100644
index 0000000..8879704
--- /dev/null
+++ b/res/layout/conversation_activity.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.ImeDetectFrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/conversation_and_compose_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/conversation_fragment_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <FrameLayout
+        android:id="@+id/contact_picker_fragment_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</com.android.messaging.ui.ImeDetectFrameLayout>
\ No newline at end of file
diff --git a/res/layout/conversation_fragment.xml b/res/layout/conversation_fragment.xml
new file mode 100644
index 0000000..0bf42f5
--- /dev/null
+++ b/res/layout/conversation_fragment.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:weightSum="1.0">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <!-- This FrameLayout will take all available height (excluding media picker)
+        but setting height to 0dp causes it not to shrink properly in KK, so a height of match_parent
+        works equally well -->
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_weight="1" >
+            <!-- Message list -->
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@android:id/list"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:listSelector="@android:color/transparent"
+                android:paddingTop="@dimen/action_bar_height"
+                android:clipToPadding="false" />
+
+            <View
+                android:id="@+id/conversation_compose_divider"
+                android:layout_width="match_parent"
+                android:layout_height="4dp"
+                android:layout_gravity="bottom"
+                android:background="@drawable/conversation_compose_divider_gradient"
+                android:alpha="0"
+                android:importantForAccessibility="no" />
+
+            <include layout="@layout/sim_selector_view"
+                android:id="@+id/sim_selector"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:visibility="gone" />
+        </FrameLayout>
+
+        <!-- Attachments to send, compose message view, media picker. -->
+        <include layout="@layout/compose_message_view"
+            android:id="@+id/message_compose_view_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/conversation_list_activity.xml b/res/layout/conversation_list_activity.xml
new file mode 100644
index 0000000..48f3b15
--- /dev/null
+++ b/res/layout/conversation_list_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.conversationlist.ConversationListFragment"
+    android:id="@+id/conversation_list_fragment"
+    android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/conversation_list_fragment.xml b/res/layout/conversation_list_fragment.xml
new file mode 100644
index 0000000..7fa2a9a
--- /dev/null
+++ b/res/layout/conversation_list_fragment.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/conversation_list_first_item_extra_padding"
+        android:clipToPadding="false"
+        android:listSelector="?android:attr/listSelector"
+        android:dividerHeight="0px" />
+
+    <include
+        layout="@layout/list_empty_view"
+        android:id="@+id/no_conversations_view"
+        android:visibility="gone"
+        android:layout_marginBottom="@dimen/conversation_list_empty_text_bottom_margin" />
+
+    <ImageView
+        style="@style/ConversationListFragmentStartNewButtonStyle"
+        android:id="@+id/start_new_conversation_button"
+        android:layout_width="@dimen/fab_size"
+        android:layout_height="@dimen/fab_size"
+        android:layout_gravity="bottom|end"
+        android:layout_marginBottom="@dimen/fab_bottom_margin"
+        android:paddingBottom="@dimen/fab_padding_bottom"
+        android:background="@drawable/fab_new_message_bg"
+        android:elevation="@dimen/fab_elevation"
+        android:scaleType="center"
+        android:src="@drawable/ic_add_white"
+        android:stateListAnimator="@animator/fab_anim"
+        android:contentDescription="@string/start_new_conversation"/>
+
+</FrameLayout>
diff --git a/res/layout/conversation_list_item_view.xml b/res/layout/conversation_list_item_view.xml
new file mode 100644
index 0000000..636616b
--- /dev/null
+++ b/res/layout/conversation_list_item_view.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversationlist.ConversationListItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <!-- The background displayed when the conversation is swiped sideways -->
+    <LinearLayout
+        android:id="@+id/crossSwipeBackground"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical|start"
+        android:baselineAligned="false"
+        android:background="@drawable/swipe_shadow"
+        android:visibility="gone"
+        android:padding="@dimen/conversation_list_item_view_padding">
+        <ImageView
+            android:id="@+id/crossSwipeArchiveIconLeft"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical|left"
+            android:visibility="gone"
+            android:src="@drawable/ic_archive_small_dark"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null"/>
+        <FrameLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+        <ImageView
+            android:id="@+id/crossSwipeArchiveIconRight"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical|right"
+            android:visibility="gone"
+            android:src="@drawable/ic_archive_small_dark"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null"/>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/swipeableContainer"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:importantForAccessibility="no" >
+        <LinearLayout
+            android:id="@+id/swipeableContent"
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="?android:attr/selectableItemBackground"
+            android:clipToPadding="false"
+            android:duplicateParentState="true"
+            android:padding="@dimen/conversation_list_item_view_padding">
+
+            <!-- Contact avatar on the left side of the view -->
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@android:color/transparent">
+                <com.android.messaging.ui.ContactIconView
+                    android:id="@+id/conversation_icon"
+                    android:layout_width="@dimen/conversation_list_contact_icon_size"
+                    android:layout_height="@dimen/conversation_list_contact_icon_size"
+                    android:importantForAccessibility="no"
+                    android:contentDescription="@null"
+                    app:iconSize="large"
+                    android:clickable="true"
+                    android:background="@android:color/transparent" />
+                <ImageView
+                    android:id="@+id/conversation_checkmark"
+                    android:layout_width="@dimen/conversation_list_contact_icon_size"
+                    android:layout_height="@dimen/conversation_list_contact_icon_size"
+                    android:src="@drawable/ic_checkmark_circle_blue"
+                    android:visibility="gone"
+                    android:importantForAccessibility="no"
+                    android:background="@android:color/transparent" />
+                <ImageView
+                    android:id="@+id/conversation_failed_status_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="bottom|end"
+                    android:src="@drawable/ic_failed_status_red"
+                    android:visibility="gone"
+                    android:importantForAccessibility="no"
+                    android:contentDescription="@null"
+                    android:background="@android:color/transparent" />
+            </FrameLayout>
+
+            <!-- The conversation name, message preview, etc -->
+            <LinearLayout
+                style="@style/ConversationListItemViewPaddingStyle"
+                android:orientation="vertical"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="top"
+                android:background="@android:color/transparent">
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@android:color/transparent">
+                    <LinearLayout
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1"
+                            android:background="@android:color/transparent">
+                        <ImageView
+                            android:id="@+id/conversation_notification_bell"
+                            style="@style/ConversationListNotificationBellPaddingStyle"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:src="@drawable/ic_notifications_off_small_light"
+                            android:visibility="gone"
+                            android:importantForAccessibility="no"
+                            android:contentDescription="@null"
+                            android:layout_gravity="center_vertical"
+                            android:background="@android:color/transparent" />
+                        <TextView
+                            android:id="@+id/conversation_name"
+                            style="@style/ConversationListItemViewConversationNameStyle"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:singleLine="true"
+                            android:layout_gravity="center_vertical"
+                            android:paddingBottom="2dp" />
+                    </LinearLayout>
+                    <ImageView
+                            android:id="@+id/work_profile_icon"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_gravity="right"
+                            android:background="@android:color/transparent"
+                            android:scaleType="center"
+                            android:src="@drawable/ic_work_profile"
+                            android:visibility="gone"/>
+                </LinearLayout>
+                <TextView
+                    android:id="@+id/conversation_subject"
+                    style="@style/ConversationListItemViewTextStyle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:paddingBottom="3dp"
+                    android:ellipsize="end"
+                    android:visibility="gone" />
+                <TextView
+                    android:id="@+id/conversation_snippet"
+                    style="@style/ConversationListItemViewTextStyle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:paddingBottom="3dp"
+                    android:ellipsize="end" />
+                <TextView
+                    android:id="@+id/conversation_timestamp"
+                    style="@style/ConversationListItemViewTextStyle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+            </LinearLayout>
+
+            <!-- The attachment preview on the right side of the view -->
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="top|end"
+                android:background="@android:color/transparent">
+                <com.android.messaging.ui.AsyncImageView
+                    android:id="@+id/conversation_image_preview"
+                    style="@style/ConversationListItemViewPaddingStyle"
+                    app:cornerRadius="@dimen/conversation_list_image_preview_corner_radius"
+                    android:layout_width="@dimen/conversation_list_image_preview_size"
+                    android:layout_height="@dimen/conversation_list_image_preview_size"
+                    android:visibility="gone"
+                    android:scaleType="centerCrop"
+                    android:contentDescription="@string/message_image_content_description"
+                    android:background="@android:color/transparent" />
+                <com.android.messaging.ui.AudioAttachmentView
+                    android:id="@+id/audio_attachment_view"
+                    android:layout_width="@dimen/conversation_list_image_preview_size"
+                    android:layout_height="@dimen/conversation_list_image_preview_size"
+                    app:layoutMode="subcompact"
+                    android:visibility="gone"
+                    android:background="@android:color/transparent" />
+            </FrameLayout>
+        </LinearLayout>
+    </FrameLayout>
+</com.android.messaging.ui.conversationlist.ConversationListItemView>
diff --git a/res/layout/conversation_message_view.xml b/res/layout/conversation_message_view.xml
new file mode 100644
index 0000000..daad600
--- /dev/null
+++ b/res/layout/conversation_message_view.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversation.ConversationMessageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    style="@style/ConversationMessageViewStyle"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <com.android.messaging.ui.ContactIconView
+        android:id="@+id/conversation_icon"
+        android:layout_width="@dimen/conversation_message_contact_icon_size"
+        android:layout_height="@dimen/conversation_message_contact_icon_size"
+        app:iconSize="normal"
+        android:clickable="true"
+        android:layout_gravity="center_vertical"
+        android:importantForAccessibility="no" />
+
+    <com.android.messaging.ui.conversation.ConversationMessageBubbleView
+        android:id="@+id/message_content"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical">
+
+        <LinearLayout
+            android:id="@+id/message_attachments"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:visibility="gone" >
+
+            <!-- Video, audio and vcard attachments (if present) will be added here -->
+
+            <com.android.messaging.ui.MultiAttachmentLayout
+                android:id="@+id/multiple_attachments"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone" />
+
+            <com.android.messaging.ui.AsyncImageView
+                android:id="@+id/message_image"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:minWidth="@dimen/conversation_message_photo_min_size"
+                android:minHeight="@dimen/conversation_message_photo_min_size"
+                android:adjustViewBounds="true"
+                android:scaleType="fitCenter"
+                android:layout_gravity="center_vertical"
+                android:visibility="gone"
+                app:placeholderDrawable="@drawable/attachment_image_placeholder_background"
+                app:cornerRadius="@dimen/attachment_rounded_corner_radius"
+                android:contentDescription="@string/message_image_content_description" />
+
+        </LinearLayout>
+
+        <com.android.messaging.ui.conversation.MessageBubbleBackground
+            android:id="@+id/message_text_and_info"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:id="@+id/message_title_layout"
+                android:orientation="vertical"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:importantForAccessibility="noHideDescendants" >
+
+                <TextView
+                    android:id="@+id/message_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ConversationMessageTitle" />
+
+                <TextView
+                    android:id="@+id/mms_info"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ConversationMessageInfo" />
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/subject_container"
+                android:orientation="horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:importantForAccessibility="noHideDescendants" >
+
+                <TextView
+                    android:id="@+id/subject_label"
+                    android:text="@string/conversation_message_view_subject_text"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ConversationMessage" />
+
+                <TextView
+                    android:id="@+id/subject_text"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ConversationMessage" />
+
+            </LinearLayout>
+
+            <TextView
+                android:id="@+id/message_text"
+                style="@style/ConversationMessage"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:importantForAccessibility="no" />
+
+            <com.android.messaging.ui.LineWrapLayout
+                android:id="@+id/message_metadata"
+                android:orientation="horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:importantForAccessibility="noHideDescendants" >
+
+                <TextView
+                    android:id="@+id/message_sender_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginRight="4dp"
+                    style="@style/ConversationMessageStatus"
+                    android:visibility="gone" />
+                <TextView
+                    android:id="@+id/message_status"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="@style/ConversationMessageStatus"
+                    android:visibility="gone" />
+                <TextView
+                    android:id="@+id/sim_name"
+                    style="@style/MessageSimIndicator"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:visibility="gone" />
+                <ImageView
+                    android:id="@+id/smsDeliveredBadge"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    style="@style/SmsDeliverdBadge"
+                    android:src="@drawable/ic_sms_delivery_ok"
+                    android:visibility="gone" />
+            </com.android.messaging.ui.LineWrapLayout>
+
+        </com.android.messaging.ui.conversation.MessageBubbleBackground>
+
+    </com.android.messaging.ui.conversation.ConversationMessageBubbleView>
+
+</com.android.messaging.ui.conversation.ConversationMessageView>
diff --git a/res/layout/copy_contact_dialog_view.xml b/res/layout/copy_contact_dialog_view.xml
new file mode 100644
index 0000000..15e07f7
--- /dev/null
+++ b/res/layout/copy_contact_dialog_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    style="@style/CopyContactDialogTextStyle"
+    android:ellipsize="end"
+    android:paddingTop="@dimen/copy_contact_dialog_top_padding"/>
\ No newline at end of file
diff --git a/res/layout/custom_header_view_pager.xml b/res/layout/custom_header_view_pager.xml
new file mode 100644
index 0000000..96f8fa8
--- /dev/null
+++ b/res/layout/custom_header_view_pager.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <com.android.messaging.ui.ViewPagerTabs
+        android:id="@+id/tab_strip"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:textAllCaps="true"
+        android:orientation="horizontal"
+        style="@style/PagerTabHeader" />
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+
+        <androidx.viewpager.widget.ViewPager
+            android:id="@+id/pager"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="2dp"
+            android:layout_gravity="top"
+            android:background="@drawable/compose_chips_divider_gradient"/>
+
+    </FrameLayout>
+</merge>
\ No newline at end of file
diff --git a/res/layout/debug_mmsconfig_activity.xml b/res/layout/debug_mmsconfig_activity.xml
new file mode 100644
index 0000000..4056317
--- /dev/null
+++ b/res/layout/debug_mmsconfig_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.debug.DebugMmsConfigFragment"
+    android:id="@+id/debug_mmsconfig_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/debug_mmsconfig_fragment.xml b/res/layout/debug_mmsconfig_fragment.xml
new file mode 100644
index 0000000..be61710
--- /dev/null
+++ b/res/layout/debug_mmsconfig_fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:divider="@null"
+    android:dividerHeight="0px" />
\ No newline at end of file
diff --git a/res/layout/debug_mmsconfig_item_view.xml b/res/layout/debug_mmsconfig_item_view.xml
new file mode 100644
index 0000000..a825ee5
--- /dev/null
+++ b/res/layout/debug_mmsconfig_item_view.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.debug.DebugMmsConfigItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="56dp"
+    android:background="@android:color/background_light"
+    android:gravity="center_vertical"
+    android:clickable="true"
+    style="@style/DebugMmsConfigItemStyle" >
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="match_parent"
+        android:singleLine="true"
+        android:maxLines="1"
+        android:gravity="center_vertical"/>
+    <Switch
+        android:id="@+id/switch_button"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:visibility="gone" />
+    <TextView
+        android:id="@+id/text_value"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:singleLine="true"
+        android:gravity="center_vertical"
+        android:visibility="gone"/>
+</com.android.messaging.ui.debug.DebugMmsConfigItemView>
diff --git a/res/layout/debug_sms_mms_from_dump_file_dialog.xml b/res/layout/debug_sms_mms_from_dump_file_dialog.xml
new file mode 100644
index 0000000..342f489
--- /dev/null
+++ b/res/layout/debug_sms_mms_from_dump_file_dialog.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="6dp"
+    android:background="@color/conversation_background"
+    >
+
+    <ListView android:id="@+id/dump_file_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false"
+        android:longClickable="false"/>
+
+</FrameLayout>
diff --git a/res/layout/enter_phone_number_view.xml b/res/layout/enter_phone_number_view.xml
new file mode 100644
index 0000000..825ac51
--- /dev/null
+++ b/res/layout/enter_phone_number_view.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<EditText
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="16dp"
+    android:paddingLeft="24dp"
+    android:paddingRight="24dp"
+    android:singleLine="true"
+    android:maxLines="1"
+    android:hint="@string/enter_phone_number_hint"
+    android:inputType="number|phone"
+    />
diff --git a/res/layout/fastscroll_preview.xml b/res/layout/fastscroll_preview.xml
new file mode 100644
index 0000000..ab72744
--- /dev/null
+++ b/res/layout/fastscroll_preview.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:paddingLeft="@dimen/fastscroll_preview_padding"
+    android:paddingRight="@dimen/fastscroll_preview_padding"
+    android:textColor="@color/fastscroll_preview_text_color"
+    android:textSize="@dimen/fastscroll_preview_text_size" />
diff --git a/res/layout/fastscroll_thumb.xml b/res/layout/fastscroll_thumb.xml
new file mode 100644
index 0000000..6f57056
--- /dev/null
+++ b/res/layout/fastscroll_thumb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:scaleType="fitXY" />
\ No newline at end of file
diff --git a/res/layout/fastscroll_track.xml b/res/layout/fastscroll_track.xml
new file mode 100644
index 0000000..6a35e94
--- /dev/null
+++ b/res/layout/fastscroll_track.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:scaleType="fitXY"
+    android:src="@drawable/fastscroll_track" />
diff --git a/res/layout/frequent_contacts_list_view.xml b/res/layout/frequent_contacts_list_view.xml
new file mode 100644
index 0000000..9cb0c3a
--- /dev/null
+++ b/res/layout/frequent_contacts_list_view.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ListView
+        android:id="@+id/frequent_contacts_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        android:clipToPadding="false"
+        android:divider="@null"
+        android:dividerHeight="0px"
+        android:fastScrollEnabled="true" />
+
+    <include
+        layout="@layout/list_empty_view"
+        android:id="@+id/empty_view"
+        android:visibility="gone" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/gallery_grid_item_view.xml b/res/layout/gallery_grid_item_view.xml
new file mode 100644
index 0000000..f8f3920
--- /dev/null
+++ b/res/layout/gallery_grid_item_view.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.mediapicker.GalleryGridItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/gallery_image_cell_size"
+    android:background="@color/gallery_image_default_background"
+    android:clickable="true">
+
+    <!-- Thumbnail for image and video contents. -->
+    <com.android.messaging.ui.AsyncImageView
+        android:id="@+id/thumbnail"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="centerCrop" />
+
+    <!-- Additional info such as icon, name and etc. -->
+    <RelativeLayout
+        android:id="@+id/additional_info"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"
+        android:orientation="vertical"
+        android:visibility="gone" >
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_above="@id/file_info" >
+            <ImageView
+                android:id="@+id/icon"
+                android:layout_width="@dimen/gallery_icon_size"
+                android:layout_height="@dimen/gallery_icon_size"
+                android:layout_gravity="center"
+                android:scaleType="fitCenter"
+                android:background="@color/background_item_transparent"
+                android:visibility="gone" />
+        </FrameLayout>
+
+        <!-- File info for audio contents only -->
+        <LinearLayout
+            android:id="@+id/file_info"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="4dp"
+            android:paddingLeft="4dp"
+            android:paddingRight="4dp"
+            android:orientation="vertical"
+            android:visibility="gone" >
+
+            <TextView
+                android:id="@+id/file_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
+
+            <TextView
+                android:id="@+id/file_type"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:gravity="right"
+                android:textAppearance="@android:style/TextAppearance.Material.Caption" />
+        </LinearLayout>
+    </RelativeLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:focusableInTouchMode="true"
+        android:background="@drawable/gallery_image_background_selector" />
+
+    <CheckBox
+        android:id="@+id/checkbox"
+        style="@style/GalleryGridItemViewCheckBoxStyle"
+        android:button="@drawable/gallery_checkbox_selector"
+        android:background="@null"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|end"
+        android:paddingTop="4dp"
+        android:visibility="gone"
+        android:contentDescription="@string/gallery_checkbox_content_description" />
+
+</com.android.messaging.ui.mediapicker.GalleryGridItemView>
diff --git a/res/layout/group_mms_setting_dialog.xml b/res/layout/group_mms_setting_dialog.xml
new file mode 100644
index 0000000..efc3b00
--- /dev/null
+++ b/res/layout/group_mms_setting_dialog.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<RadioGroup
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <RadioButton
+        android:id="@+id/disable_group_mms_button"
+        style="@style/GroupMmsSettingItem"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/disable_group_mms"/>
+
+    <RadioButton
+        android:id="@+id/enable_group_mms_button"
+        style="@style/GroupMmsSettingItem"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/enable_group_mms"/>
+
+</RadioGroup>
diff --git a/res/layout/license_activity.xml b/res/layout/license_activity.xml
new file mode 100644
index 0000000..1475ac2
--- /dev/null
+++ b/res/layout/license_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<WebView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+</WebView>
\ No newline at end of file
diff --git a/res/layout/list_empty_view.xml b/res/layout/list_empty_view.xml
new file mode 100644
index 0000000..aa4b4fb
--- /dev/null
+++ b/res/layout/list_empty_view.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.ListEmptyView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical">
+
+    <ImageView
+        android:id="@+id/empty_image_hint"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:importantForAccessibility="no"
+        android:contentDescription="@null"/>
+
+    <TextView
+        android:id="@+id/empty_text_hint"
+        android:gravity="center_horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginLeft="@dimen/list_empty_text_left_right_margin"
+        android:layout_marginRight="@dimen/list_empty_text_left_right_margin"
+        android:layout_marginTop="@dimen/list_empty_text_top_margin"
+        style="@style/ListEmptyText"/>
+</com.android.messaging.ui.ListEmptyView>
diff --git a/res/layout/mediapicker_audio_chooser.xml b/res/layout/mediapicker_audio_chooser.xml
new file mode 100644
index 0000000..795d2f8
--- /dev/null
+++ b/res/layout/mediapicker_audio_chooser.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.mediapicker.AudioRecordView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/white"
+    android:importantForAccessibility="no" >
+
+    <FrameLayout
+        android:id="@+id/mediapicker_enabled"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+
+        <TextView
+            android:id="@+id/hint_text"
+            style="@style/AudioPickerHintText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top|center"
+            android:layout_marginTop="16dp"
+            android:text="@string/audio_picker_hint_text"
+            android:importantForAccessibility="no" />
+
+        <com.android.messaging.ui.mediapicker.PausableChronometer
+            android:id="@+id/timer_text"
+            style="@style/AudioPickerTimerText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top|center"
+            android:layout_marginTop="16dp"
+            android:visibility="gone" />
+
+        <com.android.messaging.ui.mediapicker.SoundLevels
+            android:id="@+id/sound_levels"
+            android:layout_width="260dp"
+            android:layout_height="260dp"
+            android:layout_gravity="center"
+            android:focusableInTouchMode="false"
+            app:minLevelRadius="55dp"
+            app:maxLevelRadius="130dp"
+            app:primaryColor="@color/audio_picker_level_primary_color" />
+
+        <!-- View to make the touachable area larger for accessibility's two-finger touch -->
+        <FrameLayout
+            android:id="@+id/record_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:padding="30dp"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            android:contentDescription="@string/audio_record_view_content_description" >
+
+            <ImageView
+                android:id="@+id/record_button_visual"
+                android:layout_width="70dp"
+                android:layout_height="70dp"
+                android:layout_margin="30dp"
+                android:layout_gravity="center"
+                android:scaleType="center"
+                android:src="@drawable/ic_mp_audio_mic"
+                android:background="@drawable/audio_record_control_button_background"
+                android:importantForAccessibility="no"
+                android:contentDescription="@null" />
+        </FrameLayout>
+
+    </FrameLayout>
+
+    <!-- This view will hide all other views if the required permission is not granted -->
+    <TextView
+        android:id="@+id/missing_permission_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:visibility="gone" />
+
+</com.android.messaging.ui.mediapicker.AudioRecordView>
diff --git a/res/layout/mediapicker_camera_chooser.xml b/res/layout/mediapicker_camera_chooser.xml
new file mode 100644
index 0000000..27d26bd
--- /dev/null
+++ b/res/layout/mediapicker_camera_chooser.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<com.android.messaging.ui.mediapicker.CameraMediaChooserView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/black">
+
+    <FrameLayout
+        android:id="@+id/mediapicker_enabled"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <!-- Default to using the hardware rendered camera preview, we will fall back to
+        SoftwareCameraPreview in CameraMediaChooserView if needed -->
+        <com.android.messaging.ui.mediapicker.HardwareCameraPreview
+            android:id="@+id/camera_preview"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center" />
+
+        <com.android.messaging.ui.mediapicker.camerafocus.RenderOverlay
+            android:id="@+id/focus_visual"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <View
+            android:id="@+id/camera_shutter_visual"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@android:color/white"
+            android:visibility="gone" />
+
+        <!-- Need a background on this view in order for the ripple effect to have a place to draw -->
+        <FrameLayout
+            android:id="@+id/camera_button_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@android:color/transparent"
+            android:paddingTop="20dp"
+            android:layout_gravity="bottom">
+
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start|center_vertical"
+                style="@style/CameraChooserFrameStyle">
+
+                <ImageButton
+                    android:id="@+id/camera_swap_mode_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="48dp"
+                    android:minHeight="48dp"
+                    android:background="@drawable/transparent_button_background"
+                    android:src="@drawable/ic_mp_video_small_light"
+                    android:contentDescription="@string/camera_switch_to_video_mode"/>
+
+                <Chronometer
+                    android:id="@+id/camera_video_counter"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textColor="@android:color/white"
+                    android:textSize="18sp"
+                    android:padding="16dp"
+                    android:visibility="gone" />
+
+            </FrameLayout>
+
+            <ImageButton
+                android:id="@+id/camera_capture_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:minWidth="96dp"
+                android:minHeight="96dp"
+                android:background="@drawable/transparent_button_background"
+                android:src="@drawable/ic_checkmark_large_light"
+                android:contentDescription="@string/camera_take_picture"/>
+
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end|center_vertical"
+                android:paddingEnd="16dp">
+
+                <ImageButton
+                    android:id="@+id/camera_fullScreen_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="48dp"
+                    android:minHeight="48dp"
+                    android:background="@drawable/transparent_button_background"
+                    android:src="@drawable/ic_mp_full_screen_light"
+                    android:contentDescription="@string/camera_switch_full_screen" />
+
+                <ImageButton
+                    android:id="@+id/camera_swapCamera_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="48dp"
+                    android:minHeight="48dp"
+                    android:background="@drawable/transparent_button_background"
+                    android:visibility="gone"
+                    android:contentDescription="@string/camera_switch_camera_facing"/>
+
+                <ImageButton
+                    android:id="@+id/camera_cancel_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="48dp"
+                    android:minHeight="48dp"
+                    android:background="@drawable/transparent_button_background"
+                    android:src="@drawable/ic_remove_small_light"
+                    android:visibility="gone"
+                    android:contentDescription="@string/camera_cancel_recording" />
+
+            </FrameLayout>
+
+        </FrameLayout>
+
+    </FrameLayout>
+
+    <!-- This view will hide all other views if the required permission is not granted -->
+    <TextView
+        android:id="@+id/missing_permission_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:visibility="gone" />
+
+</com.android.messaging.ui.mediapicker.CameraMediaChooserView>
diff --git a/res/layout/mediapicker_contact_chooser.xml b/res/layout/mediapicker_contact_chooser.xml
new file mode 100644
index 0000000..dcace4f
--- /dev/null
+++ b/res/layout/mediapicker_contact_chooser.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2020 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/white"
+    android:importantForAccessibility="no" >
+
+    <FrameLayout
+        android:id="@+id/mediapicker_enabled"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+
+        <TextView
+            style="@style/ContactPickerHintText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top|center"
+            android:layout_marginTop="16dp"
+            android:text="@string/contact_picker_hint_text"
+            android:importantForAccessibility="no" />
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:scaleType="center"
+            android:src="@drawable/ic_person_light_large"
+            android:tint="@color/primary_color"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+    </FrameLayout>
+
+    <!-- This view will hide all other views if the required permission is not granted -->
+    <TextView
+        android:id="@+id/missing_permission_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:visibility="gone" />
+
+</FrameLayout>
diff --git a/res/layout/mediapicker_fragment.xml b/res/layout/mediapicker_fragment.xml
new file mode 100644
index 0000000..2e414bd
--- /dev/null
+++ b/res/layout/mediapicker_fragment.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<com.android.messaging.ui.mediapicker.MediaPickerPanel
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <com.android.messaging.ui.PagingAwareViewPager
+        android:id="@+id/mediapicker_view_pager"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/mediapicker_default_chooser_height" />
+    <LinearLayout
+        android:id="@+id/mediapicker_tabstrip"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:orientation="horizontal"
+        android:gravity="center" />
+</com.android.messaging.ui.mediapicker.MediaPickerPanel>
diff --git a/res/layout/mediapicker_gallery_chooser.xml b/res/layout/mediapicker_gallery_chooser.xml
new file mode 100644
index 0000000..b4f3c01
--- /dev/null
+++ b/res/layout/mediapicker_gallery_chooser.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    <com.android.messaging.ui.mediapicker.GalleryGridView
+        android:id="@+id/gallery_grid_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="6dp"
+        android:columnWidth="@dimen/gallery_image_cell_size"
+        android:numColumns="auto_fit"
+        android:verticalSpacing="6dp"
+        android:horizontalSpacing="6dp"
+        android:stretchMode="columnWidth"
+        android:gravity="center"
+        android:clipToPadding="false"
+        android:background="@android:color/white" />
+    <!-- This view will hide all other views if the required permission is not granted -->
+    <TextView
+        android:id="@+id/missing_permission_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:visibility="gone" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/mediapicker_location_chooser.xml b/res/layout/mediapicker_location_chooser.xml
new file mode 100644
index 0000000..9135299
--- /dev/null
+++ b/res/layout/mediapicker_location_chooser.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/place_picker_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:name="com.google.android.location.places.ui.placepicker.PlacePickerFragment" />
diff --git a/res/layout/mediapicker_location_container.xml b/res/layout/mediapicker_location_container.xml
new file mode 100644
index 0000000..6f476d3
--- /dev/null
+++ b/res/layout/mediapicker_location_container.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/place_picker_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <!-- This view will be hidden by the PlacePickerFragment if the required permission is granted -->
+    <TextView
+        android:id="@+id/missing_permission_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description" />
+    </FrameLayout>
diff --git a/res/layout/mediapicker_tab_button.xml b/res/layout/mediapicker_tab_button.xml
new file mode 100644
index 0000000..353c871
--- /dev/null
+++ b/res/layout/mediapicker_tab_button.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<!-- android:contentDescription is set in code -->
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="48dp"
+    android:layout_height="48dp"
+    android:background="@drawable/mediapicker_tab_button_background"
+    android:contentDescription="@null">
+</ImageButton>
\ No newline at end of file
diff --git a/res/layout/message_audio_attachment.xml b/res/layout/message_audio_attachment.xml
new file mode 100644
index 0000000..0854269
--- /dev/null
+++ b/res/layout/message_audio_attachment.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.AudioAttachmentView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="70dp"
+    android:importantForAccessibility="no"
+    style="@style/AudioAttachmentViewStyle" />
diff --git a/res/layout/message_vcard_attachment.xml b/res/layout/message_vcard_attachment.xml
new file mode 100644
index 0000000..0da6e2d
--- /dev/null
+++ b/res/layout/message_vcard_attachment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.PersonItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:paddingTop="@dimen/message_text_top_padding"
+    android:paddingBottom="@dimen/message_text_bottom_padding"
+    style="@style/MessageVcardAttachmentStyle" />
diff --git a/res/layout/message_video_attachment.xml b/res/layout/message_video_attachment.xml
new file mode 100644
index 0000000..8aa2061
--- /dev/null
+++ b/res/layout/message_video_attachment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.VideoThumbnailView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical"
+    android:minWidth="@dimen/video_message_min_size"
+    android:minHeight="@dimen/video_message_min_size"
+    app:mode="imageThumbnail" />
diff --git a/res/layout/mms_config_debug_fragment.xml b/res/layout/mms_config_debug_fragment.xml
new file mode 100644
index 0000000..27528f9
--- /dev/null
+++ b/res/layout/mms_config_debug_fragment.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_margin="16dp">
+        <TextView
+            android:id="@+id/sim_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/debug_sub_id_spinner_text" />
+        <Spinner
+            android:id="@+id/sim_selector"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="wrap_content" />
+    </LinearLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="#555555" />
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:divider="@null"
+        android:dividerHeight="0px" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/open_source_licenses.xml b/res/layout/open_source_licenses.xml
new file mode 100644
index 0000000..89995eb
--- /dev/null
+++ b/res/layout/open_source_licenses.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<WebView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/osl_web_view"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    />
diff --git a/res/layout/people_and_options_activity.xml b/res/layout/people_and_options_activity.xml
new file mode 100644
index 0000000..af879a0
--- /dev/null
+++ b/res/layout/people_and_options_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.conversationsettings.PeopleAndOptionsFragment"
+    android:id="@+id/people_and_options_fragment"
+    android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/people_and_options_fragment.xml b/res/layout/people_and_options_fragment.xml
new file mode 100644
index 0000000..be61710
--- /dev/null
+++ b/res/layout/people_and_options_fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:divider="@null"
+    android:dividerHeight="0px" />
\ No newline at end of file
diff --git a/res/layout/people_and_options_section_header.xml b/res/layout/people_and_options_section_header.xml
new file mode 100644
index 0000000..44b10c1
--- /dev/null
+++ b/res/layout/people_and_options_section_header.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/people_and_options_header"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/people_and_options_list_divider"/>
+
+    <TextView
+        android:id="@+id/header_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="16dp"
+        android:text="@string/participant_list_title"
+        style="@style/PeopleAndOptionsSectionHeader" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/people_list_item_view.xml b/res/layout/people_list_item_view.xml
new file mode 100644
index 0000000..e4c07e4
--- /dev/null
+++ b/res/layout/people_list_item_view.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.PersonItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:background="?android:attr/selectableItemBackground"
+    style="@style/PeopleListItemViewStyle" />
diff --git a/res/layout/people_options_item_view.xml b/res/layout/people_options_item_view.xml
new file mode 100644
index 0000000..8821eec
--- /dev/null
+++ b/res/layout/people_options_item_view.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversationsettings.PeopleOptionsItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="56dp"
+    android:gravity="center_vertical"
+    android:background="?android:attr/selectableItemBackground"
+    android:clickable="true"
+    style="@style/PeopleAndOptionsItemStyle">
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center_vertical">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:maxLines="1"
+            android:ellipsize="end"
+            style="@style/ParticipantListItem"
+            android:layout_gravity="center_vertical" />
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:maxLines="1"
+            android:ellipsize="end"
+            style="@style/ParticipantListItemDetail"
+            android:layout_gravity="center_vertical" />
+
+    </LinearLayout>
+
+    <androidx.appcompat.widget.SwitchCompat
+        android:id="@+id/switch_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:clickable="false"
+        android:visibility="gone" />
+
+</com.android.messaging.ui.conversationsettings.PeopleOptionsItemView>
diff --git a/res/layout/permission_check_activity.xml b/res/layout/permission_check_activity.xml
new file mode 100644
index 0000000..57f665c
--- /dev/null
+++ b/res/layout/permission_check_activity.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/permission_check_activity_background"
+    android:orientation="vertical" >
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/required_permissions_promo"
+        android:paddingTop="96dp"
+        style="@style/PromoScreenTextStyle.CenterAligned" />
+    <TextView
+        android:id="@+id/enable_permission_procedure"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:text="@string/enable_permission_procedure"
+        android:contentDescription="@string/enable_permission_procedure_description"
+        style="@style/PromoScreenTextStyle.CenterAligned"
+        android:visibility="invisible"/>
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:paddingTop="40dp"
+        android:src="@drawable/permissions"
+        android:scaleType="centerInside"
+        android:importantForAccessibility="no" />
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@android:color/white" />
+    <!-- Buttons -->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:orientation="horizontal" >
+        <TextView
+            android:id="@+id/exit"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="@string/exit"
+            style="@style/PromoScreenButtonStyle" />
+        <TextView
+            android:id="@+id/next"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="@string/next_with_arrow"
+            android:contentDescription="@string/next"
+            style="@style/PromoScreenButtonStyle" />
+        <TextView
+            android:id="@+id/settings"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="@string/settings_with_arrow"
+            android:contentDescription="@string/settings"
+            style="@style/PromoScreenButtonStyle"
+            android:visibility="gone"/>
+        </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/person_item_view.xml b/res/layout/person_item_view.xml
new file mode 100644
index 0000000..9645024
--- /dev/null
+++ b/res/layout/person_item_view.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<merge
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <com.android.messaging.ui.ContactIconView
+        android:id="@+id/contact_icon"
+        android:layout_width="@dimen/contact_list_icon_size"
+        android:layout_height="@dimen/contact_list_icon_size"
+        android:importantForAccessibility="no"
+        app:iconSize="normal"
+        android:layout_gravity="center_vertical" />
+
+    <LinearLayout
+        android:id="@+id/details_container"
+        android:orientation="vertical"
+        style="@style/ContactListItemLinearLayoutStyle"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:background="@android:color/transparent">
+
+        <TextView
+            android:id="@+id/name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:maxLines="1"
+            android:ellipsize="end"
+            style="@style/ParticipantListItem" />
+
+        <TextView
+            android:id="@+id/details"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:ellipsize="end"
+            style="@style/ContactListItemDetail" />
+
+    </LinearLayout>
+</merge>
diff --git a/res/layout/place_card.xml b/res/layout/place_card.xml
new file mode 100644
index 0000000..93b9e8c
--- /dev/null
+++ b/res/layout/place_card.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+   android:layout_width="wrap_content"
+   android:layout_height="wrap_content">
+
+    <com.android.messaging.ui.AsyncImageView
+        android:id="@+id/map_image"
+        android:layout_gravity="center_horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:scaleType="fitCenter"
+        android:adjustViewBounds="true" />
+
+    <TextView
+        android:id="@+id/place_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:maxLines="1"
+        android:ellipsize="end"
+        android:textSize="16sp"
+        android:textStyle="bold" />
+
+    <TextView
+        android:id="@+id/place_subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:maxLines="2"
+        android:ellipsize="end"
+        android:textSize="14sp" />
+
+    <TextView
+        android:id="@+id/place_notes"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="14sp" />
+
+</merge>
\ No newline at end of file
diff --git a/res/layout/settings_fragment.xml b/res/layout/settings_fragment.xml
new file mode 100644
index 0000000..b62b245
--- /dev/null
+++ b/res/layout/settings_fragment.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<ListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/settings_item_view.xml b/res/layout/settings_item_view.xml
new file mode 100644
index 0000000..a434c11
--- /dev/null
+++ b/res/layout/settings_item_view.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/settings_list_item_height"
+    android:gravity="center_vertical"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
+    android:background="?android:attr/selectableItemBackground" >
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:maxLines="1"
+        android:ellipsize="end"
+        style="@style/SettingsListItem" />
+
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:maxLines="2"
+        android:ellipsize="end"
+        style="@style/SettingsListItemDetail" />
+
+</LinearLayout>
diff --git a/res/layout/share_intent_activity.xml b/res/layout/share_intent_activity.xml
new file mode 100644
index 0000000..d1e59ff
--- /dev/null
+++ b/res/layout/share_intent_activity.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.conversationlist.ShareIntentFragment"
+    android:id="@+id/share_intent_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/res/layout/share_intent_conversation_list_view.xml b/res/layout/share_intent_conversation_list_view.xml
new file mode 100644
index 0000000..1dec1fe
--- /dev/null
+++ b/res/layout/share_intent_conversation_list_view.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:paddingTop="8dp"
+    android:orientation="vertical">
+  <FrameLayout
+      android:layout_width="match_parent"
+      android:layout_height="0dp"
+      android:layout_weight="1">
+      <androidx.recyclerview.widget.RecyclerView
+          android:id="@android:id/list"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:paddingTop="@dimen/conversation_list_first_item_extra_padding"
+          android:clipToPadding="false"
+          android:listSelector="?android:attr/listSelector"
+          android:dividerHeight="0px" />
+      <include
+          layout="@layout/list_empty_view"
+          android:id="@+id/no_conversations_view"
+          android:visibility="gone"/>
+  </FrameLayout>
+  <View
+      android:layout_width="match_parent"
+      android:layout_height="1dp"
+      android:background="#d2d2d2"/>
+</LinearLayout>
diff --git a/res/layout/sim_selector_item_view.xml b/res/layout/sim_selector_item_view.xml
new file mode 100644
index 0000000..a20c4a9
--- /dev/null
+++ b/res/layout/sim_selector_item_view.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversation.SimSelectorItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:background="?android:attr/selectableItemBackground"
+    android:padding="12dp"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/details_container"
+        android:orientation="vertical"
+        style="@style/SimSelectorItemLinearLayoutStyle"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical" >
+
+        <TextView
+            android:id="@+id/name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:maxLines="1"
+            android:ellipsize="end"
+            style="@style/SimSelectorItem" />
+
+        <TextView
+            android:id="@+id/details"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:maxLines="1"
+            android:ellipsize="end"
+            style="@style/SimSelectorItemDetail" />
+
+    </LinearLayout>
+
+    <com.android.messaging.ui.conversation.SimIconView
+        android:id="@+id/sim_icon"
+        android:layout_width="@dimen/sim_selector_icon_size"
+        android:layout_height="@dimen/sim_selector_icon_size"
+        android:importantForAccessibility="no"
+        android:layout_gravity="center_vertical"
+        android:elevation="3dp"
+        app:iconSize="normal" />
+
+</com.android.messaging.ui.conversation.SimSelectorItemView>
diff --git a/res/layout/sim_selector_view.xml b/res/layout/sim_selector_view.xml
new file mode 100644
index 0000000..816a2cc
--- /dev/null
+++ b/res/layout/sim_selector_view.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<com.android.messaging.ui.conversation.SimSelectorView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/sim_selector_background_gradient">
+
+    <ListView
+        android:id="@+id/sim_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:divider="@null"
+        android:dividerHeight="0px"
+        android:visibility="gone" />
+
+</com.android.messaging.ui.conversation.SimSelectorView>
diff --git a/res/layout/sms_free_storage_action_item_view.xml b/res/layout/sms_free_storage_action_item_view.xml
new file mode 100644
index 0000000..fd71904
--- /dev/null
+++ b/res/layout/sms_free_storage_action_item_view.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/action"
+    android:padding="8dp"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    style="@style/LowStorageActionItemStyle" />
diff --git a/res/layout/sms_mms_dump_file_list_item.xml b/res/layout/sms_mms_dump_file_list_item.xml
new file mode 100644
index 0000000..a939db2
--- /dev/null
+++ b/res/layout/sms_mms_dump_file_list_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/file"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip"
+    android:paddingTop="10dip"
+    android:paddingBottom="10dip"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentLeft="true"
+    android:textSize="16sp"
+    android:textColor="@color/compose_send_text_color"
+    android:singleLine="false"
+    style="@style/ConversationComposeSendText" />
diff --git a/res/layout/sms_storage_low_warning_dialog.xml b/res/layout/sms_storage_low_warning_dialog.xml
new file mode 100644
index 0000000..965cab6
--- /dev/null
+++ b/res/layout/sms_storage_low_warning_dialog.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="6dp"
+    android:background="@android:color/background_light">
+
+    <ListView android:id="@+id/free_storage_action_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false"
+        android:listSelector="?android:attr/selectableItemBackground"
+        android:longClickable="false"/>
+
+</FrameLayout>
diff --git a/res/layout/snack_bar.xml b/res/layout/snack_bar.xml
new file mode 100644
index 0000000..1cdabc3
--- /dev/null
+++ b/res/layout/snack_bar.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/snackbarContainer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <!--
+        First child is also a LinearLayout to preserve it's styles from getting
+        overridden by the LayoutParams set by the WindowManager.
+        Also, it is the view being animated within the root view.
+    -->
+
+   <LinearLayout
+        android:id="@+id/snack_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:background="#323232" >
+
+        <FrameLayout
+            android:id="@+id/snack_bar_message_wrapper"
+            style="@style/SnackBarMessageWrapper"
+            android:layout_marginTop="@dimen/snack_bar_top_bottom_margin"
+            android:layout_marginBottom="@dimen/snack_bar_top_bottom_margin"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" >
+            <TextView
+                android:id="@+id/snack_bar_message"
+                style="@style/SnackBarText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+        </FrameLayout>
+
+        <TextView
+            android:id="@+id/snack_bar_action"
+            style="@style/SnackBarText"
+            android:paddingLeft="@dimen/snack_bar_left_right_margin"
+            android:paddingRight="@dimen/snack_bar_left_right_margin"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical"
+            android:textColor="#EEFF41"
+            android:textAllCaps="true" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/test_activity.xml b/res/layout/test_activity.xml
new file mode 100644
index 0000000..a34b17a
--- /dev/null
+++ b/res/layout/test_activity.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+    <FrameLayout
+        android:id="@+id/test_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</FrameLayout>
diff --git a/res/layout/vcard_detail_activity.xml b/res/layout/vcard_detail_activity.xml
new file mode 100644
index 0000000..aa4c3b9
--- /dev/null
+++ b/res/layout/vcard_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fragment
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.VCardDetailFragment"
+    android:id="@+id/vcard_detail_fragment"
+    android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/vcard_detail_fragment.xml b/res/layout/vcard_detail_fragment.xml
new file mode 100644
index 0000000..8689df0
--- /dev/null
+++ b/res/layout/vcard_detail_fragment.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_layout_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ExpandableListView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:drawSelectorOnTop="false" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/video_thumbnail_view.xml b/res/layout/video_thumbnail_view.xml
new file mode 100644
index 0000000..7c009cb
--- /dev/null
+++ b/res/layout/video_thumbnail_view.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.android.messaging.ui.AsyncImageView
+        android:id="@+id/video_thumbnail_image"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:cornerRadius="@dimen/attachment_rounded_corner_radius" />
+
+    <ImageButton
+        android:id="@+id/video_thumbnail_play_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:background="@drawable/transparent_button_background"
+        android:src="@drawable/ic_video_play_light"
+        android:contentDescription="@string/video_thumbnail_view_play_button_content_description" />
+
+</merge>
\ No newline at end of file
diff --git a/res/layout/viewgroup_vertical_explode_animation_popup.xml b/res/layout/viewgroup_vertical_explode_animation_popup.xml
new file mode 100644
index 0000000..8a8aa60
--- /dev/null
+++ b/res/layout/viewgroup_vertical_explode_animation_popup.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<view
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.messaging.ui.animation.ViewGroupItemVerticalExplodeAnimation$VerticalExplodePopupRootView"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#55000000">
+
+    <ImageView
+        android:id="@+id/explode_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:importantForAccessibility="no" />
+
+</view>
diff --git a/res/layout/widget_conversation.xml b/res/layout/widget_conversation.xml
new file mode 100644
index 0000000..2c7edee
--- /dev/null
+++ b/res/layout/widget_conversation.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="@dimen/widget_margin"
+    android:background="@android:color/transparent" >
+    <LinearLayout
+        android:id="@+id/widget_header"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:orientation="horizontal"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:layout_alignParentTop="true">
+        <TextView
+            android:id="@+id/widget_label"
+            style="@style/WidgetConversationTitle"
+            android:layout_height="wrap_content"
+            android:layout_width="0dip"
+            android:layout_weight = "1"
+            android:layout_gravity="center_vertical"
+            android:freezesText="true" />
+        <ImageView
+            android:id="@+id/launcher_icon"
+            android:src="@drawable/ic_launcher"
+            android:layout_height="wrap_content"
+            android:layout_width="0dip"
+            android:layout_weight = "1"
+            android:scaleType="fitStart"
+            android:paddingTop="12dip"
+            android:paddingBottom="12dip"
+            android:visibility="gone"
+            android:importantForAccessibility="no" />
+        <ImageButton
+            android:id="@+id/widget_goto_conversation_list"
+            style="@style/WidgetHeaderImage"
+            android:layout_width="@dimen/widget_header_new_conv_button_width"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_widget_list"
+            android:background="?android:attr/selectableItemBackground"
+            android:contentDescription="@string/widget_conversation_list_content_description"
+            android:layout_gravity="center_vertical" />
+    </LinearLayout>
+    <ListView
+        android:id="@+id/message_list"
+        android:layout_below="@+id/top_line"
+        android:layout_above="@+id/bottom_line"
+        android:layout_marginTop="-2dp"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="true"
+        android:transcriptMode="alwaysScroll"
+        android:stackFromBottom="true"
+        android:overScrollMode="never"
+        android:divider="@null" />
+    <TextView
+        android:id="@+id/widget_configuration"
+        style="@style/WidgetConversationTitle"
+        android:layout_below="@+id/top_line"
+        android:layout_above="@+id/bottom_line"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:visibility="gone"
+        android:singleLine="false"
+        android:paddingRight="20dp"
+        android:paddingLeft="20dp"
+        android:paddingBottom="20dp"
+        android:text="@string/tap_to_configure" />
+    <ImageView
+        android:id="@id/top_line"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/widget_hr"
+        android:importantForAccessibility="no"
+        android:contentDescription="@null"
+        android:layout_marginTop="-2dp"
+        android:layout_below="@id/widget_header"
+        />
+    <ImageView
+        android:id="@id/bottom_line"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/widget_hr"
+        android:importantForAccessibility="no"
+        android:contentDescription="@null"
+        android:layout_marginTop="-2dp"
+        android:layout_alignParentBottom="true"
+        />
+</RelativeLayout>
diff --git a/res/layout/widget_conversation_list.xml b/res/layout/widget_conversation_list.xml
new file mode 100644
index 0000000..822fe55
--- /dev/null
+++ b/res/layout/widget_conversation_list.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="@dimen/widget_margin"
+    android:orientation="vertical">
+    <LinearLayout
+        android:id="@+id/widget_header"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/widget_header_height"
+        android:orientation="horizontal"
+        android:paddingLeft="8dip"
+        android:background="@drawable/widget_top_background"
+        android:gravity="center_vertical">
+        <TextView
+            android:id="@+id/widget_label"
+            style="@style/WidgetTitle"
+            android:layout_height="wrap_content"
+            android:layout_width="0dip"
+            android:layout_weight = "1"
+            android:contentDescription="@string/widget_title_content_description"
+            android:freezesText="true" />
+        <ImageButton
+            android:id="@+id/widget_compose"
+            style="@style/WidgetHeaderImage"
+            android:layout_width="@dimen/widget_header_new_conv_button_width"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_add_white"
+            android:background="?android:attr/selectableItemBackground"
+            android:contentDescription="@string/widget_new_conversation_content_description"
+            android:paddingRight="8dip"
+            android:paddingBottom="4dip" />
+    </LinearLayout>
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="#aaaaaa"
+        android:importantForAccessibility="no"
+        android:contentDescription="@null" />
+    <ListView
+        android:id="@+id/conversation_list"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:cacheColorHint="#00000000"
+        android:divider="@android:drawable/divider_horizontal_bright"
+        android:background="@drawable/widget_bottom_background" />
+</LinearLayout>
diff --git a/res/layout/widget_conversation_list_item.xml b/res/layout/widget_conversation_list_item.xml
new file mode 100644
index 0000000..e0115a2
--- /dev/null
+++ b/res/layout/widget_conversation_list_item.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget_conversation_list_item"
+    android:layout_width="match_parent"
+    style="@style/WidgetConversationListItemStyle"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip" >
+
+    <FrameLayout
+        android:id="@+id/avatarFrame"
+        android:layout_centerVertical="true"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@+id/avatarView"
+            style="@style/WidgetConversationListItemAvatar"
+            android:layout_width="@dimen/contact_icon_view_normal_size"
+            android:layout_height="@dimen/contact_icon_view_normal_size"
+            android:layout_centerVertical="true"
+            android:scaleType="fitXY"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+        <ImageView
+            android:id="@+id/conversation_failed_status_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/WidgetConversationItemFailed"
+            android:src="@drawable/ic_failed_status_red"
+            android:visibility="gone"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null"/>
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_centerVertical="true"
+        android:orientation="vertical"
+        style="@style/WidgetConversationListItemBody"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="6dip"
+                android:layout_alignParentTop="true"
+                android:gravity="center_vertical"
+                android:background="@android:color/transparent">
+                <ImageView
+                    android:id="@+id/conversation_notification_bell"
+                    style="@style/ConversationListNotificationBellPaddingStyle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@drawable/ic_notifications_off_small_light"
+                    android:visibility="gone"
+                    android:importantForAccessibility="no"
+                    android:contentDescription="@null"
+                    android:layout_gravity="center_vertical"
+                    android:background="@android:color/transparent" />
+
+                <TextView android:id="@+id/from"
+                    style="@style/WidgetConversationListItemFrom"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:textAppearance="?android:attr/textAppearanceMediumInverse"
+                    android:singleLine="true"
+                    android:textSize="18sp"
+                    android:textColor="@color/widget_text_color"
+                    android:ellipsize="marquee"  />
+
+                <TextView android:id="@+id/date"
+                    style="@style/WidgetConversationListItemDate"
+                    android:paddingTop="4dp"
+                    android:textSize="12sp"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceSmallInverse"
+                    android:singleLine="true"
+                    android:textColor="@color/widget_text_color" />
+            </LinearLayout>
+        </RelativeLayout>
+
+        <TextView android:id="@+id/snippet"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:maxLines="2"
+            android:textSize="13sp"
+            android:layout_marginBottom="5dip"
+            android:layout_alignParentBottom="true"
+            android:textColor="@color/widget_text_color"
+            android:ellipsize="end" />
+
+        <LinearLayout android:id="@+id/errorBlock"
+            android:orientation="vertical"
+            android:layout_alignParentBottom="true"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <TextView android:id="@+id/errorSnippet"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmallInverse"
+                android:maxLines="1"
+                android:textSize="13sp"
+                android:textColor="@color/widget_text_color"
+                android:ellipsize="end" />
+
+            <TextView android:id="@+id/errorText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmallInverse"
+                android:maxLines="2"
+                android:textSize="13sp"
+                android:layout_marginBottom="5dip"
+                android:textColor="@color/conversation_list_error"
+                android:ellipsize="end" />
+
+        </LinearLayout>
+    </LinearLayout>
+</RelativeLayout>
diff --git a/res/layout/widget_loading.xml b/res/layout/widget_loading.xml
new file mode 100644
index 0000000..8282b5d
--- /dev/null
+++ b/res/layout/widget_loading.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget_loading"
+    android:layout_width="match_parent"
+    android:layout_height="64sp" >
+    <TextView
+        android:id="@+id/loading_text"
+        style="@style/WidgetLoading"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:gravity="center"
+        android:textColor="@android:color/black"
+        android:textSize="12sp" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/widget_message_item_incoming.xml b/res/layout/widget_message_item_incoming.xml
new file mode 100644
index 0000000..786385b
--- /dev/null
+++ b/res/layout/widget_message_item_incoming.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget_message_item_incoming"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="8dp"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip" >
+
+    <FrameLayout
+        android:id="@+id/avatarFrame"
+        android:layout_gravity="top"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@+id/avatarShadow"
+            style="@style/WidgetConversationItemIncomingAvatarShadow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:src="@drawable/ic_widget_avatar_shadow"
+            android:layout_marginTop="-4dp"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+        <ImageView
+            android:id="@+id/avatarView"
+            style="@style/WidgetConversationItemAvatarIncoming"
+            android:layout_width="@dimen/contact_icon_view_normal_size"
+            android:layout_height="@dimen/contact_icon_view_normal_size"
+            android:layout_centerVertical="true"
+            android:scaleType="fitXY"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+        <ImageView
+            android:id="@+id/conversation_failed_status_icon"
+            style="@style/WidgetConversationItemFailed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_failed_status_red"
+            android:visibility="gone"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null"/>
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_gravity="top"
+        android:orientation="vertical"
+        style="@style/WidgetConversationItemBodyIncoming"
+        android:background="@drawable/widget_msg_bubble_incoming"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" >
+
+        <TextView android:id="@+id/message"
+            style="@style/WidgetConversationItemWidget"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:textSize="16sp"
+            android:paddingTop="6dp"
+            android:paddingLeft="6dp"
+            android:paddingRight="6dp"
+            android:layout_marginBottom="3dip"
+            android:layout_alignParentBottom="true"
+            android:textColor="@color/widget_incoming_text_color"
+            android:ellipsize="end" />
+
+        <TextView android:id="@+id/date"
+            style="@style/WidgetConversationItemDate"
+            android:paddingLeft="6dp"
+            android:paddingRight="6dp"
+            android:layout_marginBottom="9dip"
+            android:textSize="12sp"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:singleLine="true"
+            android:textColor="@color/timestamp_text_incoming" />
+
+        <FrameLayout
+            android:id="@+id/attachmentFrame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            <ImageView
+                android:id="@+id/attachment"
+                style="@style/WidgetConversationItemAttachment"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:importantForAccessibility="no"
+                android:adjustViewBounds="true"
+                android:contentDescription="@null"/>
+            <ImageView
+                android:id="@+id/playButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:visibility="gone"
+                android:src="@drawable/ic_video_play_light"
+                android:importantForAccessibility="no"
+                android:contentDescription="@null"/>
+        </FrameLayout>
+    </LinearLayout>
+</RelativeLayout>
diff --git a/res/layout/widget_message_item_outgoing.xml b/res/layout/widget_message_item_outgoing.xml
new file mode 100644
index 0000000..c3d734e
--- /dev/null
+++ b/res/layout/widget_message_item_outgoing.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget_message_item_outgoing"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="8dp"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip" >
+
+    <FrameLayout
+        android:id="@+id/avatarFrame"
+        android:layout_gravity="top"
+        style="@style/WidgetConversationItemAvatarOutgoing"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@+id/avatarShadow"
+            style="@style/WidgetConversationItemOutgoingAvatarShadow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:src="@drawable/ic_widget_avatar_shadow"
+            android:layout_marginTop="-4dp"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+        <ImageView
+            android:id="@+id/avatarView"
+            android:layout_width="@dimen/contact_icon_view_normal_size"
+            android:layout_height="@dimen/contact_icon_view_normal_size"
+            android:layout_centerVertical="true"
+            android:scaleType="fitXY"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null" />
+        <ImageView
+            android:id="@+id/conversation_failed_status_icon"
+            style="@style/WidgetConversationItemFailed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_failed_status_red"
+            android:visibility="gone"
+            android:importantForAccessibility="no"
+            android:contentDescription="@null"/>
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_gravity="top"
+        android:orientation="vertical"
+        style="@style/WidgetConversationItemBodyOutgoing"
+        android:background="@drawable/widget_msg_bubble_outgoing"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" >
+
+        <TextView android:id="@+id/message"
+            style="@style/WidgetConversationItemWidget"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:textSize="16sp"
+            android:paddingTop="6dp"
+            android:paddingLeft="6dp"
+            android:paddingRight="6dp"
+            android:layout_marginBottom="3dip"
+            android:layout_alignParentBottom="true"
+            android:textColor="@color/widget_outgoing_text_color"
+            android:ellipsize="end" />
+
+        <TextView android:id="@+id/date"
+            style="@style/WidgetConversationItemDate"
+            android:paddingLeft="6dp"
+            android:paddingRight="6dp"
+            android:layout_marginBottom="9dip"
+            android:textSize="12sp"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:singleLine="true"
+            android:textColor="@color/timestamp_text_outgoing" />
+
+        <FrameLayout
+            android:id="@+id/attachmentFrame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            <ImageView
+                android:id="@+id/attachment"
+                style="@style/WidgetConversationItemAttachment"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:importantForAccessibility="no"
+                android:adjustViewBounds="true"
+                android:contentDescription="@null"/>
+            <ImageView
+                android:id="@+id/playButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:visibility="gone"
+                android:src="@drawable/ic_video_play_light"
+                android:importantForAccessibility="no"
+                android:contentDescription="@null"/>
+        </FrameLayout>
+
+    </LinearLayout>
+</RelativeLayout>
diff --git a/res/layout/widget_missing_permission.xml b/res/layout/widget_missing_permission.xml
new file mode 100644
index 0000000..712ad02
--- /dev/null
+++ b/res/layout/widget_missing_permission.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:text="@string/required_permissions_promo"
+    android:gravity="center"
+    style="@android:style/TextAppearance.Medium"
+    android:background="@color/action_bar_background_color"
+    android:freezesText="true" />
diff --git a/res/layout/work_directory_header.xml b/res/layout/work_directory_header.xml
new file mode 100644
index 0000000..3c882f5
--- /dev/null
+++ b/res/layout/work_directory_header.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF A`NY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Layout used for list section separators. -->
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:text="@string/work_directory_display_name"
+        style="@style/DirectoryHeaderStyle"
+        />
diff --git a/res/menu/archived_conversation_list_menu.xml b/res/menu/archived_conversation_list_menu.xml
new file mode 100644
index 0000000..a3a2a19
--- /dev/null
+++ b/res/menu/archived_conversation_list_menu.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" >
+    <item
+        android:id="@+id/action_debug_options"
+        android:orderInCategory="9900"
+        android:title="@string/action_debug_options"
+        android:showAsAction="never"/>
+
+</menu>
diff --git a/res/menu/attachment_chooser_menu.xml b/res/menu/attachment_chooser_menu.xml
new file mode 100644
index 0000000..99345c9
--- /dev/null
+++ b/res/menu/attachment_chooser_menu.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+    <item
+        android:id="@+id/action_confirm_selection"
+        android:icon="@drawable/ic_checkmark_small_light"
+        android:orderInCategory="100"
+        android:title="@string/action_confirm_selection"
+        appcompat:showAsAction="always"/>
+</menu>
diff --git a/res/menu/compose_menu.xml b/res/menu/compose_menu.xml
new file mode 100644
index 0000000..a384f57
--- /dev/null
+++ b/res/menu/compose_menu.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    tools:context="com.android.messaging.ConversationActivity" >
+
+    <!-- This must always be the first item so it appears right next to the chip view -->
+    <item
+        android:id="@+id/action_delete_text"
+        android:icon="@drawable/ic_cancel_small_light"
+        android:orderInCategory="0"
+        android:title="@string/chips_text_delete_button_content_description"
+        appcompat:showAsAction="always"/>
+
+    <item
+        android:id="@+id/action_ime_dialpad_toggle"
+        android:icon="@drawable/ic_numeric_dialpad"
+        android:orderInCategory="100"
+        android:title="@string/numeric_text_keyboard_toggle_button_content_description"
+        appcompat:showAsAction="always"/>
+
+    <item
+        android:id="@+id/action_add_more_participants"
+        android:icon="@drawable/ic_people_add_light"
+        android:orderInCategory="110"
+        android:title="@string/add_more_participants_button_content_description"
+        appcompat:showAsAction="always"/>
+
+    <item
+        android:id="@+id/action_confirm_participants"
+        android:icon="@drawable/ic_checkmark_small_light"
+        android:orderInCategory="120"
+        android:title="@string/confrim_participants_button_content_description"
+        appcompat:showAsAction="always"/>
+
+</menu>
diff --git a/res/menu/conversation_fragment_select_menu.xml b/res/menu/conversation_fragment_select_menu.xml
new file mode 100644
index 0000000..7ce0829
--- /dev/null
+++ b/res/menu/conversation_fragment_select_menu.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item
+        android:id="@+id/share_message_menu"
+        android:title="@string/action_share"
+        android:icon="@drawable/ic_share_dark"
+        appcompat:showAsAction="collapseActionView|always" />
+    <item
+        android:id="@+id/forward_message_menu"
+        android:title="@string/message_context_menu_forward_message"
+        android:icon="@drawable/ic_forward_dark"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/save_attachment"
+        android:title="@string/save"
+        android:icon="@drawable/ic_save_dark"
+        appcompat:showAsAction="collapseActionView|always" />
+    <item
+        android:id="@+id/copy_text"
+        android:title="@string/message_context_menu_copy_text"
+        android:icon="@drawable/ic_content_copy_dark"
+        appcompat:showAsAction="collapseActionView|always"/>
+
+    <item
+        android:id="@+id/details_menu"
+        android:title="@string/message_context_menu_view_details"
+        android:icon="@drawable/ic_info_dark"
+        appcompat:showAsAction="collapseActionView|always"/>
+
+    <item
+        android:id="@+id/action_send"
+        android:icon="@drawable/ic_send_dark"
+        android:title="@string/action_send"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_download"
+        android:icon="@drawable/ic_file_download_dark"
+        android:title="@string/action_download"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_delete_message"
+        android:icon="@drawable/ic_delete_small_dark"
+        android:title="@string/action_delete_message"
+        appcompat:showAsAction="collapseActionView|always"/>
+</menu>
diff --git a/res/menu/conversation_list_fragment_menu.xml b/res/menu/conversation_list_fragment_menu.xml
new file mode 100644
index 0000000..a83a2a5
--- /dev/null
+++ b/res/menu/conversation_list_fragment_menu.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item android:id="@+id/action_start_new_conversation"
+        android:title="@string/start_new_conversation"
+        android:icon="@drawable/ic_add_white"
+        android:visible="false"
+        appcompat:showAsAction="ifRoom" />
+
+    <item
+        android:id="@+id/action_show_archived"
+        android:orderInCategory="200"
+        android:title="@string/action_menu_show_archived"
+        android:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_show_blocked_contacts"
+        android:orderInCategory="300"
+        android:title="@string/blocked_contacts_title"
+        appcompat:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="400"
+        android:title="@string/action_settings"
+        appcompat:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_debug_options"
+        android:orderInCategory="9900"
+        android:title="@string/action_debug_options"
+        appcompat:showAsAction="never"/>
+
+</menu>
diff --git a/res/menu/conversation_list_fragment_select_menu.xml b/res/menu/conversation_list_fragment_select_menu.xml
new file mode 100644
index 0000000..8704691
--- /dev/null
+++ b/res/menu/conversation_list_fragment_select_menu.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item
+        android:id="@+id/action_archive"
+        android:icon="@drawable/ic_archive_small_dark"
+        android:orderInCategory="50"
+        android:title="@string/action_archive"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_unarchive"
+        android:icon="@drawable/ic_archive_undo_small_dark"
+        android:orderInCategory="50"
+        android:title="@string/action_unarchive"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_delete"
+        android:icon="@drawable/ic_delete_small_dark"
+        android:orderInCategory="60"
+        android:title="@string/action_delete"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_notification_off"
+        android:icon="@drawable/ic_notifications_off_dark"
+        android:orderInCategory="70"
+        android:title="@string/action_notification_off"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_notification_on"
+        android:icon="@drawable/ic_notifications_on_dark"
+        android:orderInCategory="80"
+        android:title="@string/action_notification_on"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_add_contact"
+        android:icon="@drawable/ic_person_add_dark"
+        android:orderInCategory="90"
+        android:title="@string/action_add_contact"
+        appcompat:showAsAction="collapseActionView|always"/>
+    <item
+        android:id="@+id/action_block"
+        android:icon="@drawable/ic_dnd_on_dark"
+        android:orderInCategory="100"
+        android:title="@string/action_block"
+        appcompat:showAsAction="collapseActionView|always"/>
+</menu>
diff --git a/res/menu/conversation_menu.xml b/res/menu/conversation_menu.xml
new file mode 100644
index 0000000..57e561b
--- /dev/null
+++ b/res/menu/conversation_menu.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    tools:context="com.android.messaging.ConversationActivity" >
+
+    <item
+        android:id="@+id/action_call"
+        android:icon="@drawable/ic_phone_small_light"
+        android:orderInCategory="80"
+        android:title="@string/action_call"
+        appcompat:showAsAction="ifRoom"/>
+
+    <item
+        android:id="@+id/action_add_contact"
+        android:icon="@drawable/ic_person_add_light"
+        android:orderInCategory="90"
+        android:title="@string/action_add_contact"
+        android:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_people_and_options"
+        android:orderInCategory="100"
+        android:title="@string/action_people_and_options"
+        appcompat:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_archive"
+        android:orderInCategory="120"
+        android:title="@string/action_archive"
+        android:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_unarchive"
+        android:orderInCategory="130"
+        android:title="@string/action_unarchive"
+        android:showAsAction="never"/>
+
+    <item
+        android:id="@+id/action_delete"
+        android:orderInCategory="140"
+        android:title="@string/action_delete"
+        android:showAsAction="never"/>
+
+</menu>
diff --git a/res/menu/gallery_picker_menu.xml b/res/menu/gallery_picker_menu.xml
new file mode 100644
index 0000000..428f1e7
--- /dev/null
+++ b/res/menu/gallery_picker_menu.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item
+        android:id="@+id/action_multiselect"
+        android:icon="@drawable/ic_checkbox_outline_light"
+        android:orderInCategory="100"
+        android:title="@string/action_multiselect"
+        appcompat:showAsAction="always"/>
+
+    <item
+        android:id="@+id/action_confirm_multiselect"
+        android:icon="@drawable/ic_checkmark_small_light"
+        android:orderInCategory="101"
+        android:title="@string/action_confirm_multiselect"
+        appcompat:showAsAction="always"/>
+</menu>
diff --git a/res/menu/photo_view_menu.xml b/res/menu/photo_view_menu.xml
new file mode 100644
index 0000000..10a4367
--- /dev/null
+++ b/res/menu/photo_view_menu.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item
+        android:id="@+id/action_share"
+        android:title="@string/action_share"
+        android:actionProviderClass="android.widget.ShareActionProvider"
+        android:showAsAction="ifRoom"/>
+    <item
+        android:id="@+id/action_save"
+        android:title="@string/save"
+        android:icon="@drawable/ic_save_light"
+        android:showAsAction="ifRoom"/>
+
+</menu>
diff --git a/res/menu/settings_menu.xml b/res/menu/settings_menu.xml
new file mode 100644
index 0000000..3002be8
--- /dev/null
+++ b/res/menu/settings_menu.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <item
+        android:id="@+id/action_license"
+        android:orderInCategory="100"
+        android:title="@string/menu_license"
+        android:showAsAction="never"/>
+
+</menu>
diff --git a/res/menu/vcard_detail_fragment_menu.xml b/res/menu/vcard_detail_fragment_menu.xml
new file mode 100644
index 0000000..ea923cb
--- /dev/null
+++ b/res/menu/vcard_detail_fragment_menu.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:appcompat="http://schemas.android.com/apk/res-auto" >
+
+    <item
+        android:id="@+id/action_add_contact"
+        android:icon="@drawable/ic_person_add_light"
+        android:orderInCategory="100"
+        android:title="@string/action_add_contact"
+        appcompat:showAsAction="always"/>
+</menu>
diff --git a/res/raw/audio_end.wav b/res/raw/audio_end.wav
new file mode 100644
index 0000000..01d08f5
--- /dev/null
+++ b/res/raw/audio_end.wav
Binary files differ
diff --git a/res/raw/audio_initiate.wav b/res/raw/audio_initiate.wav
new file mode 100644
index 0000000..e335d0d
--- /dev/null
+++ b/res/raw/audio_initiate.wav
Binary files differ
diff --git a/res/raw/db_op_debug.wav b/res/raw/db_op_debug.wav
new file mode 100644
index 0000000..b807636
--- /dev/null
+++ b/res/raw/db_op_debug.wav
Binary files differ
diff --git a/res/raw/message_failure.wav b/res/raw/message_failure.wav
new file mode 100644
index 0000000..270a0b7
--- /dev/null
+++ b/res/raw/message_failure.wav
Binary files differ
diff --git a/res/raw/message_inc_thread.wav b/res/raw/message_inc_thread.wav
new file mode 100644
index 0000000..7dce364
--- /dev/null
+++ b/res/raw/message_inc_thread.wav
Binary files differ
diff --git a/res/raw/message_sent.wav b/res/raw/message_sent.wav
new file mode 100644
index 0000000..1d45718
--- /dev/null
+++ b/res/raw/message_sent.wav
Binary files differ
diff --git a/res/raw/server_request_debug.wav b/res/raw/server_request_debug.wav
new file mode 100644
index 0000000..864a7dd
--- /dev/null
+++ b/res/raw/server_request_debug.wav
Binary files differ
diff --git a/res/transition/explode.xml b/res/transition/explode.xml
new file mode 100644
index 0000000..a3a94ba
--- /dev/null
+++ b/res/transition/explode.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<explode/>
\ No newline at end of file
diff --git a/res/transition/fade.xml b/res/transition/fade.xml
new file mode 100644
index 0000000..e3617dc
--- /dev/null
+++ b/res/transition/fade.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<fade/>
\ No newline at end of file
diff --git a/res/values-af/arrays.xml b/res/values-af/arrays.xml
new file mode 100644
index 0000000..d780ddc
--- /dev/null
+++ b/res/values-af/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"geen onderwerp nie"</item>
+    <item msgid="272485471009191934">"geen onderwerp nie"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nee"</item>
+    <item msgid="3084376867445867895">"Goed"</item>
+    <item msgid="3155097332660174689">"Hê-hê"</item>
+    <item msgid="2611328818571146775">"Dankie"</item>
+    <item msgid="4881335087096496747">"Ek stem saam"</item>
+    <item msgid="2422296858597420738">"Lekker"</item>
+    <item msgid="4805581752819452687">"Op pad"</item>
+    <item msgid="4746700499431366214">"OK, laat ek jou later antwoord"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
new file mode 100644
index 0000000..901bd27
--- /dev/null
+++ b/res/values-af/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Boodskappe"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Boodskappe"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Kies gesprek"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Instellings"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Stuur boodskap"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Voeg \'n aanhegsel by"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hulp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Welkom"</string>
+    <string name="skip" msgid="7238879696319945853">"Slaan oor"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Volgende &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Volgende"</string>
+    <string name="exit" msgid="1905187380359981199">"Gaan uit"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Instellings &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Instellings"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Boodskappe het toestemming nodig vir SMS, foon en kontakte."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Jy kan toestemmings verander in Instellings &gt; Programme &gt; Boodskappe &gt; Toestemmings."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Jy kan toestemmings verander in Instellings, Programme, Boodskappe, Toestemmings."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Gereeldes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alle kontakte"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Stuur na <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Neem foto\'s of video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Kies prente van hierdie toestel af"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Neem oudio op"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Kies foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Die media is gekies."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Die media is nie gekies nie."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> gekies"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"prent <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"prent"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Neem oudio op"</string>
+    <string name="action_share" msgid="2143483844803153871">"Deel"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Nou net"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nou"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> uur</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> uur</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dae</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> weke</item>
+      <item quantity="one">\'n week</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> maande</item>
+      <item quantity="one">\'n maand</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> jaar</item>
+      <item quantity="one">\'n jaar</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Klas 0-boodskap"</string>
+    <string name="save" msgid="5081141452059463572">"Stoor"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Toestel het min spasie. Boodskappe sal ouer boodskappe outomaties uitvee om spasie beskikbaar te stel."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Bergingspasie word min"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Boodskappe sal dalk nie boodskappe stuur of ontvang voordat meer spasie op jou toestel beskikbaar is nie."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Min SMS-berging. Jy sal dalk boodskappe moet uitvee."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Bevestig jou foonnommer"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Hierdie eenmalige stap sal sorg dat Boodskappe jou groepboodskappe toepaslik aflewer."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Foonnommer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Vee alle boodskappe met media uit"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Vee boodskappe ouer as <xliff:g id="DURATION">%s</xliff:g> uit"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Vee boodskappe ouer as <xliff:g id="DURATION">%s</xliff:g> outomaties uit"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignoreer"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Vee alle boodskappe met media uit?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Vee boodskappe ouer as <xliff:g id="DURATION">%s</xliff:g> uit?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Vee boodskappe ouer as <xliff:g id="DURATION">%s</xliff:g> uit en skakel outomatiese uitvee aan?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> het gesê"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Jy het gesê"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Boodskap van <xliff:g id="SENDER">%s</xliff:g> af"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Jy het \'n boodskap gestuur"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Stuur tans …"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nie gestuur nie. Raak om weer te probeer."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nie gestuur nie. Probeer tans weer …"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Herstuur of vee uit"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Maak asseblief \'n stemoproep na nooddienste. Jou SMS kon nie in hierdie stadium afgelewer word nie."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Het misluk"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nuwe MMS-boodskap om af te laai"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nuwe MMS-boodskap"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Kon nie aflaai nie"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Raak om weer te probeer"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Raak om af te laai"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Laai af of vee uit"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Laai tans af …"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Boodskap het verval of is nie beskikbaar nie"</string>
+    <string name="mms_info" msgid="3402311750134118165">"grootte: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, verval: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Kan nie stuur nie. Ontvanger nie geldig nie."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Diens nie in netwerk geaktiveer nie"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Kon weens netwerkprobleem nie stuur nie"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Boodskap het verval of is nie beskikbaar nie"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Geen onderwerp nie)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Onbekende afsender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Afgelewer"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Kon nie boodskap <xliff:g id="SUBJECT">%1$s</xliff:g> van <xliff:g id="FROM">%2$s</xliff:g> aflaai nie."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Kon nie databasishandeling voltooi nie weens lae geheue"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Boodskap nie gestuur nie"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Sommige boodskappe is nie in Boodskappe gestuur nie"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> boodskappe in <xliff:g id="CONVERSATIONS">%d</xliff:g> gesprekke</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> boodskappe in een gesprek</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Boodskap het nie afgelaai nie"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Sommige boodskappe is nie in Boodskappe afgelaai nie"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> boodskappe in <xliff:g id="CONVERSATIONS">%d</xliff:g> gesprekke</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> boodskappe in een gesprek</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Boodskap aan <xliff:g id="NUMBER">%1$s</xliff:g> nie gestuur nie"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Maak asseblief \'n stemoproep na nooddienste. Jou SMS na <xliff:g id="NUMBER">%1$s</xliff:g> kon nie in hierdie stadium afgelewer word nie."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nuwe boodskappe</item>
+      <item quantity="one">Nuwe boodskap</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Begin"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera nie beskikbaar nie"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera nie beskikbaar nie"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video-opname nie beskikbaar nie"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Kan nie media stoor nie"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Kan nie foto neem nie"</string>
+    <string name="back" msgid="1477626055115561645">"Terug"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Geargiveer"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Vee uit"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Argiveer"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Deargiveer"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Skakel kennisgewings af"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Skakel kennisgewings aan"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Voeg kontak by"</string>
+    <string name="action_download" msgid="7786338136368564146">"Laai af"</string>
+    <string name="action_send" msgid="377635240181672039">"Stuur"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Vee uit"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vee hierdie boodskap uit?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Hierdie handeling kan nie ontdoen word nie."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Vee uit"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Vee hierdie gesprekke uit?</item>
+      <item quantity="one">Vee hierdie gesprek uit?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Vee uit"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Kanselleer"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Aan"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Kies verskeie prente"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Bevestig keuse"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Kan nie oudio opneem nie. Probeer weer."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Kan nie oudio speel nie. Probeer weer."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Kon nie oudio stoor nie. Probeer weer."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Raak en hou"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Prent"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Oudiosnit"</string>
+    <string name="notification_video" msgid="4331423498662606204">"video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontakkaartjie"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Laai af"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Antwoord via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Antwoord via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Antwoord"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> deelnemers</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> deelnemer</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ek"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontak geblokkeer en geargiveer"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontak gedeblokkeer en gedeargiveer"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> geargiveer"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> gedeargiveer"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Kennisgewings afgeskakel"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Kennisgewings aangeskakel"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Alles is gereed. Raak om weer te stuur."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Boodskappe is suksesvol as die verstek-SMS-program gestel."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Gooi aanhegsels weg</item>
+      <item quantity="one">Gooi aanhegsel weg</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Oudio-aanhegsel"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Speel oudio-aanhegsel"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Wag"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Boodskap vanaf <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mislukte boodskap van <xliff:g id="SENDER">%1$s</xliff:g> af: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Boodskap van <xliff:g id="SENDER">%1$s</xliff:g> af: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ongestuurde boodskap aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Stuur tans boodskap aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Kon nie boodskap aan <xliff:g id="CONTACT">%1$s</xliff:g> stuur nie: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Boodskap aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mislukte boodskap van <xliff:g id="SENDER">%1$s</xliff:g> af: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Boodskap van <xliff:g id="SENDER">%1$s</xliff:g> af: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ongestuurde boodskap aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Stuur tans boodskap aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Kon nie boodskap aan <xliff:g id="GROUP">%1$s</xliff:g> stuur nie: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Boodskap aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tyd: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Kon nie boodskap stuur nie. Raak om weer te probeer."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Gesprek met <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Vee onderwerp uit"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Neem video op"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Vang \'n stilprent vas"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Neem foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Begin video opneem"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Skakel na volskerm-kamera oor"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Wissel tussen voorste en agterste kamera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Staak opname en heg video aan"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stop video-opname"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto\'s uit Boodskappe"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto\'s is na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"-album gestoor</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto is na \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"-album gestoor</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video\'s is na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"-album gestoor</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video is na \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"-album gestoor</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> aanhegsels is na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"-album gestoor</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> aanhegsel is na \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"-album gestoor</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> aanhegsels is na \"Aflaaie\" gestoor</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> aanhegsel is na \"Aflaaie\" gestoor</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> aanhegsels is gestoor</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> aanhegsel is gestoor</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Kon <xliff:g id="QUANTITY_1">%d</xliff:g> aanhegsels nie stoor nie</item>
+      <item quantity="one">Kon <xliff:g id="QUANTITY_0">%d</xliff:g> aanhegsel nie stoor nie</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS-aanhegsel gestoor"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Instellings"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Geargiveer"</string>
+    <string name="action_close" msgid="1840519376200478419">"Maak toe"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Gevorderd"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Ontfout"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Kennisgewings"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Klank"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Stil"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibreer"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Geblokkeer"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-afleweringverslae"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Versoek \'n afleweringsverslag vir elke SMS wat jy stuur"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Haal outomaties op"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Gaan haal MMS-boodskappe outomaties"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Outoherwinning wanneer swerf"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Laai MMS outomaties af terwyl geswerf word"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Groepboodskappe"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Gebruik MMS om \'n enkele boodskap te stuur wanneer daar veelvuldige ontvangers is"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Verstek-SMS-program"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Verstek-SMS-program"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Jou foonnommer"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Onbekend"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Klanke vir uitgaande boodskappe"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Gooi SMS weg"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Stort rou data van ontvangde SMS in eksterne berginglêer"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Gooi MMS weg"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Stort rou data van ontvangde MMS in eksterne berginglêer"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Draadlose waarskuwings"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Boodskapopsies"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopieer teks"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Bekyk besonderhede"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Vee uit"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Stuur aan"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Boodskapbesonderhede"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipe: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Teksboodskap"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimediaboodskap"</string>
+    <string name="from_label" msgid="1947831848146564875">"Van: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Aan: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Gestuur: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Ontvang: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Onderwerp: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Grootte: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioriteit: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Hoog"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normaal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Laag"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Versteekte afsenderadres"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Kan nie boodskap stuur terwyl aanhegsels gelaai word nie."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Kan nie aanhegsel laai nie. Probeer weer."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Netwerk is nie gereed nie. Probeer weer."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Vee teks uit"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Wissel tussen invoer van teks en syfers"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Voeg meer deelnemers by"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Bevestig deelnemers"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Begin nuwe gesprek"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Kies hierdie item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Speel video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Mense en opsies"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Ontfout"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Mense en opsies"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Algemeen"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Mense in hierdie gesprek"</string>
+    <string name="action_call" msgid="6596167921517350362">"Maak \'n oproep"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Stuur boodskap"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Stuur boodskap&lt;br/&gt;&lt;small&gt;van <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; af"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Stuur foto\'s</item>
+      <item quantity="one">Stuur foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Stuur oudio\'s</item>
+      <item quantity="one">Stuur oudio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Stuur video\'s</item>
+      <item quantity="one">Stuur video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Stuur kontakkaarte</item>
+      <item quantity="one">Stuur kontakkaart</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Stuur aanhegsels</item>
+      <item quantity="one">Stuur aanhegsel</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> aanhegsels is gereed om te stuur</item>
+      <item quantity="one">Een aanhegsel is gereed om te stuur</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Stuur terugvoer"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Bekyk in Google Play Winkel"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Weergawe-inligting"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Weergawe %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Oopbronlisensies"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Kennisgewings"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Aanhegsellimiet is bereik"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Kon nie aanhegsel laai nie."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Voeg by kontakte?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Voeg kontak by"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Onderwerp"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Onderwerp: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Laai tans kontakkaart"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kon nie kontakkaart laai nie"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Bekyk kontakkaart"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakte</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontak</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontakkaarte"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Verjaardag"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Aanstuurboodskap"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Antwoord"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS gedeaktiveer"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Stel Boodskappe as die verstek-SMS-program om te stuur"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Stel Boodskappe as die verstek-SMS-program"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Verander"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Stel Boodskappe as die verstek-SMS-program om boodskappe te ontvang"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Geen voorkeur-SIM vir die stuur van SMS-boodskappe gekies nie"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Hierdie program word nie deur die toesteleienaar toegelaat nie."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Goed"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Te veel deelnemers aan \'n gesprek"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Ongeldige kontakte</item>
+      <item quantity="one">Ongeldige kontak</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kon nie kameraprent laai nie"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Jy: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Konsep"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Sodra jy \'n nuwe gesprek begin, sal jy dit hier gelys sien"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Geargiveerde gesprekke verskyn hier"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Laai tans gesprekke …"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Prent"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Oudiosnit"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontakkaartjie"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Ontdoen"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Herprobeer"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Voer \'n kontaknaam of foonnommer in om \'n nuwe boodskap te begin"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokkeer"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokkeer <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Deblokkeer <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokkeer <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Jy sal steeds boodskappe van hierdie nommer af ontvang, maar sal nie meer in kennis gestel word nie. Hierdie gesprek sal geargiveer word."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Geblokkeerde kontakte"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DEBLOKKEER"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Geblokkeerde kontakte"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Kies prent uit dokumentbiblioteek"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Stuur tans boodskap"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Boodskap gestuur"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Sellulêre data is afgeskakel. Gaan jou instellings na."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Kan nie boodskappe in vliegtuigmodus stuur nie"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Kon nie boodskap stuur nie"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Boodskap afgelaai"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Sellulêre data is afgeskakel. Gaan jou instellings na."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Kan nie boodskappe in vliegtuigmodus aflaai nie"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Boodskap kon nie afgelaai word nie"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nul"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Een"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Twee"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Drie"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Vier"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Vyf"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Ses"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sewe"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Agt"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nege"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Kan nie boodskap met <xliff:g id="CARRIERNAME">%1$s</xliff:g> stuur nie, fout <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Kan nie boodskap met onbekende diensverskaffer stuur nie, fout <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Boodskap nie gestuur nie: diens nie in netwerk geaktiveer nie"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Boodskap nie gestuur nie: ongeldige bestemmingsadres"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Boodskap nie gestuur nie: ongeldige boodskap"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Boodskap nie gestuur nie: inhoud word nie gesteun nie"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Boodskap nie gestuur nie: boodskap word nie gesteun nie"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Boodskap nie gestuur nie; te groot"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nuwe boodskap"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Bekyk"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Prent"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Kon nie \'n toepaslike program vind nie"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Verwyder ontvanger"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nuwe boodskap"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Kanselleer"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Wysig toegangspunt"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nie gestel nie"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Naam"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-volmag"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-poort"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-tipe"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Vee APN uit"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nuwe APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Stoor"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Gooi weg"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Die naamveld kan nie leeg wees nie."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Die APN kan nie leeg wees nie."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-veld moet 3 syfers wees."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Die MNC-veld moet uit 2 of 3 syfers bestaan."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Stel tans verstekinstellings vir APN terug."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Stel terug na verstek"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Terugstel van verstek-APN-instellings voltooi."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Titelloos"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"APN\'e"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN\'e"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nuwe APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"APN-instellings is nie vir hierdie gebruiker beskikbaar nie"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopieer na knipbord?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopieer"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"aan <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Algemeen"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Gevorderd"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Algemene instellings"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Gevorderde instellings"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\"-SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Stuur individuele SMS-boodskappe aan alle ontvangers. Net jy sal enige antwoorde kry"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Stuur \'n enkele MMS aan alle ontvangers"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Onbekende nommer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nuwe boodskap"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nuwe boodskap."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-selekteerder"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> gekies, SIM-selekteerder"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Wysig onderwerp"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Kies SIM of wysig onderwerp"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Raak en hou om oudio op te neem"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Begin nuwe gesprek"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Boodskappe"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Boodskappe-lys"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Boodskappe"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nuwe boodskap"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Gespreklys"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Laai tans gesprekke"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Laai tans boodskappe"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Bekyk nog gesprekke"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Bekyk nog boodskappe"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Gesprek uitgevee"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Gesprek is uitgevee. Raak om \'n ander Boodskappe-gesprek te wys"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Geblokkeer"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Gedeblokkeer"</string>
+    <string name="db_full" msgid="8459265782521418031">"Daar is min bergingspasie. Sommige data kan verloor word."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Kies aanhegsels"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Bevestig keuse"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> gekies"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Verwyder asseblief een of meer aanhegsels en probeer weer."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Jy kan probeer om jou boodskap te stuur, maar dit sal dalk nie afgelewer word tensy jy een of meer aanhegsels verwyder nie."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Jy kan net een video per boodskap stuur. Verwyder bykomende video\'s en probeer weer."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Boodskappe kon nie aanhegsel laai nie."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Stuur in elk geval"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Kon nie gesprek begin nie"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> gekies"</string>
+</resources>
diff --git a/res/values-am/arrays.xml b/res/values-am/arrays.xml
new file mode 100644
index 0000000..225008e
--- /dev/null
+++ b/res/values-am/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ርዕሰ-ጉዳይ የሌለው"</item>
+    <item msgid="272485471009191934">"ምንም ርእስ የለውም"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"አዎ"</item>
+    <item msgid="6049132459802288033">"አይ"</item>
+    <item msgid="3084376867445867895">"እሺ"</item>
+    <item msgid="3155097332660174689">"ሃሃ"</item>
+    <item msgid="2611328818571146775">"እናመሰግናለን"</item>
+    <item msgid="4881335087096496747">"እስማማለሁ"</item>
+    <item msgid="2422296858597420738">"በጣም ጥሩ"</item>
+    <item msgid="4805581752819452687">"እየመጣሁ ነኝ"</item>
+    <item msgid="4746700499431366214">"እሺ፣ በኋላ ላይ ላግኝዎት"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
new file mode 100644
index 0000000..bea9e6f
--- /dev/null
+++ b/res/values-am/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"መልዕክት መላኪያ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"መልዕክት መላኪያ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"ውይይት ምረጥ"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ቅንብሮች"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"መልዕክት ላከ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ዓባሪ አክል"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"እገዛ"</string>
+    <string name="welcome" msgid="2857560951820802321">"እንኳን በደህና መጡ"</string>
+    <string name="skip" msgid="7238879696319945853">"ዝለል"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ቀጣይ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"ቀጣይ"</string>
+    <string name="exit" msgid="1905187380359981199">"ውጣ"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ቅንብሮች &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ቅንብሮች"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"አላላክ የኤስኤምኤስ፣ ስልክ እና እውቂያዎች ፍቃድ ያስፈልገዋል።"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ፍቃዶችን በቅንብሮች &gt; መተግበሪያዎች &gt; አላላክ &gt; ፍቃዶች ውስጥ መለወጥ ይችላሉ።"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ፍቃዶችን በቅንብሮች፣ መተግበሪያዎች፣ አላላክ፣ ፍቃዶች ውስጥ መለወጥ ይችላሉ።"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ተደጋጋሚዎች"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ሁሉም ዕውቂያዎች"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"ወደ <xliff:g id="DESTINATION">%s</xliff:g> ላክ"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ስዕሎችን አንሳ ወይም ቪዲዮ ቅረጽ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ከዚህ መሣሪያ ላይ ምስሎችን ይምረጡ"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ተሰሚ ቅረጽ"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ፎቶ ይምረጡ"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"ሚዲያው ተመርጧል።"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ሚዲያው አልተመረጠም።"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ተመርጠዋል"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ምስል <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ምስል"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ተሰሚ ቅረጽ"</string>
+    <string name="action_share" msgid="2143483844803153871">"አጋራ"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ገና አሁን"</string>
+    <string name="posted_now" msgid="867560789350406701">"አሁን"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ደቂቃዎች</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ደቂቃዎች</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ሰዓቶች</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ሰዓቶች</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ቀኖች</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ቀኖች</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ሳምንቶች</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ሳምንቶች</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ወሮች</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ወሮች</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ዓመቶች</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ዓመቶች</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"የመደብ 0 መልዕክት"</string>
+    <string name="save" msgid="5081141452059463572">"አስቀምጥ"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"መሣሪያው አነስተኛ ቦታ ነው ያለው። አላላክ ቦታን ለማስለቀቅ የቆዩ መልዕክቶችን በራስ ሰር ይሰርዛል።"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"የማከማቻ ቦታ እያለቀ ነው"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"መሣሪያዎ ላይ ተጨማሪ ቦታ እስኪገኝ ድረስ አላላክ መልዕክቶችን ላይልክ ወይም ላይቀበል ይችላል።"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ዝቅተኛ የኤስኤምኤስ ማከማቻ። መልዕክቶችን መሰረዝ ሊኖርብዎ ይችላል።"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ስልክ ቁጥርዎን ያረጋግጡ"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ይሄ የአንድ ጊዜ እርምጃ አላላክ የቡድን መልዕክቶችዎን በአግባቡ እንደሚልክ ያረጋግጣል።"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ስልክ ቁጥር"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ማህደረመረጃ ያላቸው ሁሉንም መልዕክቶች ሰርዝ"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"ከ<xliff:g id="DURATION">%s</xliff:g> በላይ የቆዩ መልዕክቶችን ሰርዝ"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"ከ<xliff:g id="DURATION">%s</xliff:g> በላይ የቆዩ መልዕክቶችን በራስ-ሰር ሰርዝ"</string>
+    <string name="ignore" msgid="7063392681130898793">"ችላ በል"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"ማህደረመረጃ ያላቸው ሁሉም መልዕክቶች ይሰረዙ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"ከ<xliff:g id="DURATION">%s</xliff:g> በላይ የቆዩ መልዕክቶች ይሰረዙ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"ከ<xliff:g id="DURATION">%s</xliff:g> በላይ የቆዩ መልዕክቶች ይሰረዙ እና ራስ-ሰር ሰራዥ ይብራ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> እንዲህ ብለዋል፦"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"እርስዎ እንዲህ ብለዋል፦"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"መልዕክት ከ<xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"እርስዎ መልዕክት ልከዋል"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"በመላክ ላይ…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"አልተላከም። እንደገና ለመሞከር ይንኩ።"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"አልተላከም። እንደገና በመሞከር ላይ…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ዳግም ላክ ወይም ሰርዝ"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"ወደ ድንገተኛ አገልግሎቶች እባክዎ የድምፅ ጥሪ ያድርጉ። የእርስዎ የጽሑፍ መልዕክት አሁን ላይ ሊደርስ አይችልም።"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"አልተሳካም"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"አዲስ የሚወርድ የኤምኤምኤስ መልዕክት"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"አዲስ የኤምኤምኤስ መልዕክት"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ማውረድ አልተቻለም"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"እንደገና ለመሞከር ይንኩ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ለማውረድ ይንኩ"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"አውርድ ወይም ሰርዝ"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"በማውረድ ላይ…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"መልዕክቱ ጊዜው አልፎበታል ወይም አይገኝም።"</string>
+    <string name="mms_info" msgid="3402311750134118165">"መጠን፦ <xliff:g id="MESSAGESIZE">%1$s</xliff:g>፣ ጊዜው የሚያልፍበት፦ <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"መላክ አይቻልም። ተቀባይ ልክ አይደለም።"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"አገልግሎት በአውታረ መረብ ላይ አልገበረም"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"በአውታረ መረብ ችግር ምክንያት መላክ አልተቻለም"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"መልዕክቱ ጊዜው አልፎበታል ወይም አይገኝም።"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ርዕስ ጉዳይ የለውም)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ያልታወቀ ላኪ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ደርሷል"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"መልዕክት <xliff:g id="SUBJECT">%1$s</xliff:g> ከ<xliff:g id="FROM">%2$s</xliff:g> ማውረድ አልተቻለም።"</string>
+    <string name="low_memory" msgid="5300743415198486619">"በአነስተኛ ማህደረ ትውስታ ምክንያት የውሂብ ጎታ ክወና ማጠናቀቅ አልተቻለም"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"መልዕክት አልተላከም"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"አንዳንድ መልዕክቶች በአላላክ ውስጥ አልተላኩም"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> መልዕክቶች በ<xliff:g id="CONVERSATIONS">%d</xliff:g> ውይይቶች ውስጥ</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> መልዕክቶች በ<xliff:g id="CONVERSATIONS">%d</xliff:g> ውይይቶች ውስጥ</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"መልዕክት አልወረደም"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"አንዳንድ መልዕክቶች በአላላክ ውስጥ አልወረዱም"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> መልዕክቶች በ<xliff:g id="CONVERSATIONS">%d</xliff:g> ውይይቶች ውስጥ</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> መልዕክቶች በ<xliff:g id="CONVERSATIONS">%d</xliff:g> ውይይቶች ውስጥ</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"ወደ <xliff:g id="NUMBER">%1$s</xliff:g> የሚሄድ መልዕክት አልተላከም"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"ወደ ድንገተኛ አገልግሎቶች እባክዎ የድምፅ ጥሪ ያድርጉ። የእርስዎ ወደ <xliff:g id="NUMBER">%1$s</xliff:g> የጽሑፍ መልዕክት አሁን ላይ ሊደርስ አይችልም።"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> አዲስ መልዕክቶች</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> አዲስ መልዕክቶች</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ጀምር"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ካሜራ ሊገኝ አይችልም"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ካሜራ ሊገኝ አይችልም"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"የቪዲዮ ቀረጻ ሊገኝ አይችልም"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"ማህደረ መረጃን ማስቀመጥ አይቻልም"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ስዕል ማንሳት አልተቻለም"</string>
+    <string name="back" msgid="1477626055115561645">"ተመለስ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"በማህደር ተቀምጧል"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ሰርዝ"</string>
+    <string name="action_archive" msgid="5437034800324083170">"በማህደር አስቀምጥ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ከማህደር አስወጣ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"ማሳወቂያዎችን አጥፋ"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"ማሳወቂያዎችን አብራ"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"እውቂያ አክል"</string>
+    <string name="action_download" msgid="7786338136368564146">"አውርድ"</string>
+    <string name="action_send" msgid="377635240181672039">"ላክ"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ሰርዝ"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ይህን መልዕክት ይሰረዝ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ይህ እርምጃ ሊቀለበስ አይችልም።"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ሰርዝ"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">እነዚህ ውይይቶች ይሰርዙ?</item>
+      <item quantity="other">እነዚህ ውይይቶች ይሰርዙ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ሰርዝ"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ይቅር"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ለ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"በርካታ ምስሎችን ምረጥ"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ምርጫ አረጋግጥ"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ድምፅን መቅዳት አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ድምፅን ማጫወት አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ድምፅን ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ነካ ያድርጉ እና ይያዙ"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"፣ "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">"፦ "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ስዕል"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"የተሰሚ ቅንጥብ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ቪዲዮ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"የእውቂያ ካርድ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"አውርድ"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"በኤስኤምኤስ በኩል መልስ ስጥ"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"በኤምኤምኤስ በኩል ምላሽ ስጥ"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ምላሽ ስጥ"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ተሳታፊዎች</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ተሳታፊዎች</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"እኔ"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"እውቂያ ታግዶ በማህደር ውስጥ ተቀምጧል"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"እውቂያ እገዳው ተነስቷል እና ከቤተማከማቻ ወጥቷል"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> በማህደር ተቀምጧል"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ከማህደር ወጥተዋል"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ማሳወቂያዎች ጠፍተዋል"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"ማሳወቂያዎች በርተዋል"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"ሁሉም ተቀናብሯል። እንደገና ላክ የሚለውን ይንኩ።"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"የአላላክ በተሳካ ሁኔታ እንደ ነባሪ የኤስኤምኤስ መተግበሪያ ተዘጋጅቷል።"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">ዓባሪዎችን አስወግድ</item>
+      <item quantity="other">ዓባሪዎችን አስወግድ</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"የኦዲዮ ዓባሪ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"የኦዲዮ ዓባሪ ያጫውቱ"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ለአፍታ አቁም"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"መልእክት ከ <xliff:g id="SENDER">%1$s</xliff:g>፦ <xliff:g id="MESSAGE">%2$s</xliff:g>።"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"ያልተሳካ መልዕክት ከ<xliff:g id="SENDER">%1$s</xliff:g>፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"ከ<xliff:g id="SENDER">%1$s</xliff:g> የመጣ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"ወደ <xliff:g id="CONTACT">%1$s</xliff:g> የሚሄድ ያልተላከ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"መልዕክት ወደ <xliff:g id="CONTACT">%1$s</xliff:g> በመላክ ላይ፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"ያልተሳካ ወደ <xliff:g id="CONTACT">%1$s</xliff:g> የሚሄድ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"ወደ <xliff:g id="CONTACT">%1$s</xliff:g> የሚሄድ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"ያልተሳካ መልዕክት ከ<xliff:g id="SENDER">%1$s</xliff:g>፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>። <xliff:g id="GROUPINFO">%4$s</xliff:g>።"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"መልዕክት ከ<xliff:g id="SENDER">%1$s</xliff:g>፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>። <xliff:g id="GROUPINFO">%4$s</xliff:g>።"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"ወደ <xliff:g id="GROUP">%1$s</xliff:g> የሚሄድ ያልተላከ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"መልዕክት ወደ <xliff:g id="GROUP">%1$s</xliff:g> በመላክ ላይ፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"ያልተሳካ ወደ <xliff:g id="GROUP">%1$s</xliff:g> የሚሄድ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"ወደ <xliff:g id="GROUP">%1$s</xliff:g> የሚሄድ መልዕክት፦ <xliff:g id="MESSAGE">%2$s</xliff:g>። ሰዓት፦ <xliff:g id="TIME">%3$s</xliff:g>።"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ያልተሳካ መልዕክት። ዳግም ለመሞከር ይንኩ።"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"ከ<xliff:g id="PARTICIPANTS">%s</xliff:g> ጋር ውይይት"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"ርዕሰ ጉዳይ ሰርዝ"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ቪዲዮ ቅረጽ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"የቆመ ምስል አንሳ"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ፎቶ አንሳ"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ቪዲዮ መቅረጽ ጀምር"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"ወደ የሙሉ ማያ ገጽ ካሜራ ቀይር"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"በፊት እና ኋላ ካሜራ መካከል ቀያይር"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"መቅረጽ አቁም እና ቪዲዮ አያይዝ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ቪዲዮ መቅዳትን አቁም"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"ፎቶዎችን በመልዕክት መላክ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ፎቶዎች ወደ የ«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ፎቶዎች ወደ የ«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ቪዲዮዎች ወደ የ«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ቪዲዮዎች ወደ የ«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ዓባሪዎች ወደ «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ዓባሪዎች ወደ «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» አልበም ተቀምጠዋል</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎች ወደ «ውርዶች» ተቀምጠዋል</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎች ወደ «ውርዶች» ተቀምጠዋል</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎች ተቀምጠዋል</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎች ተቀምጠዋል</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎችን ማስቀመጥ አልተቻለም</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ዓባሪዎችን ማስቀመጥ አልተቻለም</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"የኤምኤምኤስ ዓባሪ ተቀምጧል"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ቅንብሮች"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"በማህደር ተቀምጧል"</string>
+    <string name="action_close" msgid="1840519376200478419">"ዝጋ"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"ኤምኤምኤስ"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"የላቀ"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"አርም"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"ማሳወቂያዎች"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ድምፅ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"ፀጥታ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ንዘር"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ታግዷል"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"የኤስኤምኤስ መላክ ሪፖርቶች"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ለሚልኩት እያንዳንዱ ኤስኤምኤስ የመላኪያ ሪፖርት ጠይቅ"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"በራስ- ሰርስረህ አውጣ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"የኤምኤምኤስ መልዕክቶችን በራስ-ሰር ሰርስረህ አውጣ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"በእንቅስቃሴ ላይ በራስ-ሰር ሰርስረህ አውጣ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"የስልክ አገልግሎት ሰጪ በሚቀየርበት ጊዜ ኤምኤምኤስን በራስ-ሰር ሰርስረህ አውጣ"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"የቡድን መልዕክት መላላኪያ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ብዙ ተቀባዮች ሲኖሩ አንዲት መልዕክት ለመላክ ኤምኤምኤስ ይጠቀሙ"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ነባሪ የኤስኤምኤስ መተግበሪያ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ነባሪ የኤስኤምኤስ መተግበሪያ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"ስልክ ቁጥርዎ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"የማይታወቅ"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"የወጪ መልዕክት ድምጾች"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"ኤስኤምኤስ አራግፍ"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"የመጡ የኤስኤምኤስ ጥሬ ውሂብ ወደ ውጫዊ የማከማቻ ፋይል ላይ አራግፍ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"ኤምኤምኤስ አራግፍ"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"የመጡ የኤምኤምኤስ ጥሬ ውሂብ ወደ ውጫዊ የማከማቻ ፋይል ላይ አራግፍ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ገመድ አልባ ማንቂያዎች"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"የመልዕክት አማራጮች"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ጽሁፍ ገልብጥ"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"ዝርዝሮችን ይመልከቱ"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ሰርዝ"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ያስተላልፉ"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"የመልዕክት ዝርዝሮች"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ዓይነት፦ "</string>
+    <string name="text_message" msgid="7415419755252205721">"የፅሁፍ መልዕክት"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ማህደረ ብዙ መረጃመልዕክት"</string>
+    <string name="from_label" msgid="1947831848146564875">"ከ፦ "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ለ፦ "</string>
+    <string name="sent_label" msgid="5186286057597137301">"የተላከው፦ "</string>
+    <string name="received_label" msgid="4442494712757995203">"የደረሰው፦ "</string>
+    <string name="subject_label" msgid="1887378451808609152">"ርዕሰ ጉዳይ፦ "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"መጠን፦ "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ቅድሚያ የሚሰጠው፦ "</string>
+    <string name="sim_label" msgid="2706003016582772108">"ሲም፦ "</string>
+    <string name="priority_high" msgid="728836357310908368">"ከፍተኛ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"መደበኛ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"ዝቅ ያለ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"ሲም <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"የተደበቀ የላኪ አድራሻ"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"አባሪዎችን በመጫን ላይ እያለ መልዕክት መላክ አይችልም።"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ዓባሪን መጫን አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"አውታረ መረቡ ዝግጁ አይደለም። እንደገና ይሞክሩ።"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ጽሑፍ ሰርዝ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ጽሑፍ እና ቁጥሮችን በማስገባት መካከል ይቀያይሩ"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"ተጨማሪ ተሳታፊዎችን ያክሉ"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ተሳታፊዎችን ያረጋግጡ"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"አዲስ ውይይት ጀምር"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ይህን ንጥል ምረጥ"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ቪዲዮ አጫውት"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ሰዎች እና አማራጮች"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"አርም"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ሰዎች እና አማራጮች"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"አጠቃላይ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"በዚህ ውይይት ውስጥ ያሉ ሰዎች"</string>
+    <string name="action_call" msgid="6596167921517350362">"ደውል"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"መልዕክት ላክ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"መልዕክት ይላኩ&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ፎቶዎችን ይላኩ</item>
+      <item quantity="other">ፎቶዎችን ይላኩ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ኦዲዮዎች ይላኩ</item>
+      <item quantity="other">ኦዲዮዎች ይላኩ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">ቪዲዮዎችን ይላኩ</item>
+      <item quantity="other">ቪዲዮዎችን ይላኩ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">የእውቂያ ካርዶችን ይላኩ</item>
+      <item quantity="other">የእውቂያ ካርዶችን ይላኩ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">ዓባሪዎችን ይላኩ</item>
+      <item quantity="other">ዓባሪዎችን ይላኩ</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ዓባሪዎችን ለመላክ የተዘጋጁ ዓባሪዎች</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ዓባሪዎችን ለመላክ የተዘጋጁ ዓባሪዎች</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ግብረመልስ ላክ"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"በGoogle Play መደብር ውስጥ ይመልከቱ"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"የስሪት መረጃ"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ስሪት %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"የክፍት ምንጭ ፍቃዶች"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"ማሳወቂያዎች"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"የዓባሪ ገደብ ተደርሷል"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ዓባሪን መጫን አልተሳካም።"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"ወደ እውቂያ ይታከል?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"እውቅያ ያክሉ"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ርዕሰ ጉዳይ"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"ርዕሰ ጉዳይ፦ "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"የእውቂያ ካርድ በመጫን ላይ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"የእውቂያ ካርድን መጫን አልተቻለም"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"የእውቂያ ካርድ ይመልከቱ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> እውቂያዎች</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> እውቂያዎች</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"የአውቂያ ካርዶች"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"የልደት ቀን"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ማስታወሻዎች"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"መልዕክት አስተላልፍ"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ምላሽ ስጥ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"ኤስኤምኤስ ተሰናክሏል"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ለመላክ፣ የአላላክን እንደ ነባሪ የኤስኤምኤስ መተግበሪያ ያዘጋጁት"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"አላላክን እንደ ነባሪ የኤስኤምኤስ መተግበሪያ ያዘጋጁት"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ለውጥ"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"መልዕክቶችን ለመቀበል የአላላክን እንደ ነባሪ የኤስኤምኤስ መተግበሪያ አድርገው ያዘጋጁት"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"ኤስ ኤም ኤስ መልዕክቶችን ለመላክ ምንም ተመራጭ ሲም አልተመረጠም"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ይህ መተግበሪያ በመሣሪያው ባለቤት አይፈቀድም።"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"እሺ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"በአንድ ውይይት ውስጥ በጣም ብዙ ተሳታፊዎች"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">ልክ ያልሆኑ እውቂያዎች</item>
+      <item quantity="other">ልክ ያልሆኑ እውቂያዎች</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"የካሜራ ምስልን መጫን አልተቻለም"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"እርስዎ፦ "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>፦ "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ረቂቅ"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"አንዴ አዲስ ውይይት ከጀመሩ በኋላ እዚህ ተዘርዝሮ ያዩታል"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"በቤተመዛግብት እንዲቀመጡ የተደረጉ ውይይቶች እዚህ ላይ ብቅ ያላሉ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"ውይይቶች በመስቀል ላይ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ስዕል"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"የተሰሚ ቅንጥብ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ቪዲዮ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"የእውቂያ ካርድ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"ኤምኤምኤስ"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"ቀልብስ"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"እንደገና ይሞክሩ"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"አዲስ መልዕክት ለመጀመር የእውቂያ ስም ወይም ስልክ ቁጥር ያስገቡ"</string>
+    <string name="action_block" msgid="9032076625645190136">"አግድ"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>ን አግድ"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"የ<xliff:g id="DESTINATION">%s</xliff:g> እገዳን አንሳ"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> ይታገድ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ከዚህ ቁጥር መልዕክቶችን መቀበልዎን ይቀጥላሉ ነገርግን ከእንግዲህ እንዲያውቁት አይደረጉም። ይህ ውይይት በቤተመዛግብት ይቀመጣል።"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"የታገዱ እውቂያዎች"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"እገዳ አንሳ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"የታገዱ እውቂያዎች"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ከሰነዶች ቤተመዛግብት ምስል ይምረጡ"</string>
+    <string name="sending_message" msgid="6363584950085384929">"መልዕክት በመላክ ላይ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"መልዕክት ተልኳል"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል። ቅንብሮችዎን ያረጋግጡ።"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"በአይሮፕላን ሁኔታ ላይ እያለ መልዕክቶችን መላክ አይቻልም"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"መልዕክቱ ሊላክ አልቻለም"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"መልዕክት ወርዷል"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል። ቅንብሮችዎን ያረጋግጡ።"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"መልዕክቶችን በአውሮፕላን ሁነታ ላይ ማውረድ አይቻልም"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"መልዕክት ሊወርድ አልቻለም"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"ዜሮ"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"አንድ"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"ሁለት"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"ሶስት"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"አራት"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"አምስት"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ስድስት"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ሰባት"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ስምንት"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ዘጠኝ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"መልዕክት በ<xliff:g id="CARRIERNAME">%1$s</xliff:g> መላክ አልተቻለም፣ ስህተት <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"መልዕክት ባልታወቀ አገልግሎት አቅራቢ መላክ አልተቻለም፣ ስህተት <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"የተላለፈ፦ <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"መልዕክት አልተላከም፦ አገልግሎቱ በአውታረ መረብ ላይ አልገበረም።"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"መልዕክት አልተላከም፦ ልክ ያልሆነ የመድረሻ አድራሻ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"መልዕክት አልተላከም፦ ልክ ያልሆነ መልዕክት"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"መልዕክት አልተላከም፦ የማይደገፍ ይዘት"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"መልዕክት አልተላከም፦ የማይደገፍ መልዕክት"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"መልዕክት አልተላከም፦ በጣም ትልቅ ነው"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"አዲስ መልዕክት"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ይመልከቱ"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ምስል"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"አግባብ የሆነውን መተግበሪያ ማግኘት አልተቻለም"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"ተቀባይ አስወግድ"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"አዲስ መልዕክት"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ተወው"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"የመድረሻ ነጥብ ያርትዑ"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"አልተዘጋጀም"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ስም"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"ኤ.ፒ.ኤን."</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"የMMS እጅ አዙር"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"የMMS ወደብ"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"የኤ.ፒ.ኤን አይነት"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"ኤ.ፒ.ኤን. ሰርዝ"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"አዲስ ኤ.ፒ.ኤን."</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"አስቀምጥ"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ጣለው"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"የስም መስክ ባዶ ሊሆን አይችልም"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"ኤ.ፒ.ኤን. ባዶ መሆን አይችልም።"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"የMCC መስክ 3 አሀዝ መሆን አለበት።"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"የMNC መስክ 2 ወይም 3 አሀዝ መሆን አለበት።"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ነባሪ የኤ.ፒ.ኤን. ቅንብሮችን እነበረበት መመለስ።"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ወደ ነባሪ ዳግም አስጀምር"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"የዳግም አስጀምር ነባሪ ኤ.ፒ.ኤን. ቅንብሮች ተጠናቀዋል።"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ርዕስ አልባ"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"የመዳረሻ ነጥብ ስም"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"ኤ.ፒ.ኤኖች."</string>
+    <string name="menu_new" msgid="8286285392706532511">"አዲስ ኤ.ፒ.ኤን."</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"የመዳረሻ  ነጥብ ስም ቅንብሮች ለዚህ ተጠቃሚ አይገኙም"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ወደ የቅንጥብ ሰሌዳ ይቀዳ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ቅዳ"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ለ<xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"አጠቃላይ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"የላቀ"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"አጠቃላይ ቅንብሮች"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"የላቁ ቅንብሮች"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"የ«<xliff:g id="SIM_NAME">%s</xliff:g>» ሲም"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"የነጠላ ኤስኤምኤስ መልዕክቶችን ለሁሉም ተቀባዮች ይላኩ። እርስዎ ብቻ ነዎት ማንኛቸውም ምላሾችን የሚቀበሉት"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"አንዲት ኤምኤምኤስ ለሁሉም ተቀባዮች ይላኩ"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"ያልታወቀ ቁጥር"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"አዲስ መልዕክት"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"አዲስ መልዕክት"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"ሲም መራጭ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ተመርጧል፣ የሲም መራጭ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ርዕሰ ጉዳይ ያርትዑ"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"ሲም ይምረጡ ወይም ርዕሰ ጉዳይን ያርትዑ"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ተሰሚን ለመቅረጽ ይንኩና ይያዙ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"አዲስ ውይይት ጀምር"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"አላላክ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"የአላላክ ዝርዝር"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"አላላክ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"አዲስ መልዕክት"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"የውይይት ዝርዝር"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"ውይይቶችን በመጫን ላይ"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"መልዕክቶች በመስቀል ላይ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"ተጨማሪ ውይይቶችን ይመልከቱ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"ተጨማሪ መልዕክቶችን አሳይ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"ውይይት ተሰርዟል"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ውይይት ተሰርዟል። የተለየ የአላላክ ውይይት ለማሳየት ይንኩ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ታግዷል"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"አልታገደም"</string>
+    <string name="db_full" msgid="8459265782521418031">"የማከማቻ ቦታ ዝቅተኛ ነው። አንዳንድ ውሂብ ሊጠፋ ይችላል።"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ዓባሪዎችን ይምረጡ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ምርጫ አረጋግጥ"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ተመርጠዋል"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"እባክዎ አንድ ወይም ተጨማሪ ዓባሪዎችን ያስወግዱና እንደገና ይሞክሩ።"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"መልዕክትዎን ለመላክ መሞከር ይችላሉ፣ ነገር ግን አንድ ወይም ተጨማሪ ዓባሪዎችን እስኪያስወግዱ ድረስ ላይደርስ ይችላል።"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"በአንድ መልዕክት አንድ ቪዲዮ ብቻ ለመላክ ይችላሉ። እባክዎ ተጨማሪ ቪዲዮዎችን ያስወግዱ እና እንደገና ይሞክሩ።"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"አላላክ አባሪን መጫን አልቻለም።"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ለማንኛውም ላክ"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"ውይይት መጀመር አልተቻለም"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ተመርጧል"</string>
+</resources>
diff --git a/res/values-ar/arrays.xml b/res/values-ar/arrays.xml
new file mode 100644
index 0000000..0cf1702
--- /dev/null
+++ b/res/values-ar/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"بدون موضوع"</item>
+    <item msgid="272485471009191934">"بدون موضوع"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"نعم"</item>
+    <item msgid="6049132459802288033">"لا"</item>
+    <item msgid="3084376867445867895">"موافق"</item>
+    <item msgid="3155097332660174689">"هاها"</item>
+    <item msgid="2611328818571146775">"شكرًا"</item>
+    <item msgid="4881335087096496747">"أوافق"</item>
+    <item msgid="2422296858597420738">"لطيف"</item>
+    <item msgid="4805581752819452687">"في الطريق"</item>
+    <item msgid="4746700499431366214">"حسنًا، سأتناول ذلك لاحقًا"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
new file mode 100644
index 0000000..1a0f4b9
--- /dev/null
+++ b/res/values-ar/strings.xml
@@ -0,0 +1,623 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"المراسلة"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"المراسلة"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"تحديد محادثة"</string>
+    <string name="action_settings" msgid="1329008122345201684">"الإعدادات"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"إرسال رسالة"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"إضافة مرفق"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"مساعدة"</string>
+    <string name="welcome" msgid="2857560951820802321">"مرحبًا"</string>
+    <string name="skip" msgid="7238879696319945853">"تخطٍ"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"‏التالي &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"التالي"</string>
+    <string name="exit" msgid="1905187380359981199">"خروج"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"‏الإعدادات &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"الإعدادات"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"‏يحتاج تطبيق المراسلة إلى إذن للوصول إلى الرسائل القصيرة SMS والهاتف وجهات الاتصال."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"‏يمكنك تغيير الأذونات من خلال الإعدادات &gt; التطبيقات &gt; المراسلة &gt; الأذونات."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"يمكنك تغيير الأذونات من خلال الانتقال إلى الإعدادات، التطبيقات، المراسلة، الأذونات."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"من يتم الاتصال بهم بشكل متكرر"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"كل جهات الاتصال"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"إرسال إلى <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"التقاط الصور أو الفيديو"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"اختيار صور من هذا الجهاز"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"تسجيل الصوت"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"اختيار صورة"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"تم تحديد الوسائط."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"تم إلغاء تحديد الوسائط."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"تم تحديد <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"صورة <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"صورة"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"تسجيل الصوت"</string>
+    <string name="action_share" msgid="2143483844803153871">"المشاركة"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"للتو"</string>
+    <string name="posted_now" msgid="867560789350406701">"الآن"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
+      <item quantity="two">دقيقتان (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> دقائق</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> من الدقائق</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> دقيقة</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> ساعة</item>
+      <item quantity="two">ساعتان (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> ساعات</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> ساعة</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> من الساعات</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ساعة</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> يوم</item>
+      <item quantity="two">يومان (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> أيام</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> يومًا</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> من الأيام</item>
+      <item quantity="one">يوم واحد (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> أسبوع</item>
+      <item quantity="two">أسبوعان (<xliff:g id="COUNT">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> أسابيع</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> أسبوعًا</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الأسابيع</item>
+      <item quantity="one">أسبوع</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> شهر</item>
+      <item quantity="two">شهران (<xliff:g id="COUNT">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> أشهر</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> شهرًا</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الأشهر</item>
+      <item quantity="one">شهر</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> عام</item>
+      <item quantity="two">عامان (<xliff:g id="COUNT">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> أعوام</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> عامًا</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الأعوام</item>
+      <item quantity="one">عام</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"رسالة من الفئة 0"</string>
+    <string name="save" msgid="5081141452059463572">"حفظ"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"مساحة الجهاز منخفضة. سيحذف تطبيق المراسلة الرسائل القديمة تلقائيًا لتحرير مساحة."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"مساحة التخزين منخفضة"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"ربما لا يرسل تطبيق المراسلة رسائل أو يتلقاها ما لم تتوفر المزيد من المساحة على جهازك."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"‏سعة تخزين الرسائل القصيرة SMS منخفضة. ربما تحتاج إلى حذف بعض الرسائل."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"تأكيد رقم الهاتف"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ستضمن هذه الخطوة - التي يتم تنفيذها مرة واحدة فقط - تسليم تطبيق المراسلة لرسائلك الجماعية بشكل صحيح."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"رقم الهاتف"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"حذف جميع الرسائل التي تتضمن وسائط"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"حذف الرسائل الأقدم من <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"حذف الرسائل الأقدم من <xliff:g id="DURATION">%s</xliff:g> تلقائيًا"</string>
+    <string name="ignore" msgid="7063392681130898793">"تجاهل"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"هل تريد حذف كل الرسائل التي تتضمن ملفات وسائط؟"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"هل تريد حذف الرسائل الأقدم من <xliff:g id="DURATION">%s</xliff:g>؟"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"هل تريد حذف الرسائل الأقدم من <xliff:g id="DURATION">%s</xliff:g> وتشغيل الحذف التلقائي؟"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"قال <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"أنت قلت"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"رسالة من <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"لقد أرسلت رسالة"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"جارٍ الإرسال..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"لم يتم إرسال الرسالة. المس لإعادة المحاولة."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"لم يتم إرسال الرسالة. جارٍ إعادة المحاولة…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"إعادة إرسال أو حذف"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"الرجاء إجراء مكالمة صوتية لخدمات الطوارئ. يتعذر توصيل رسالتك النصية في الوقت الحالي."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"أخفق الإرسال"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"هناك رسالة وسائط متعددة جديدة للتنزيل"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"رسالة وسائط متعددة جديدة"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"تعذر التنزيل"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"المس لإعادة المحاولة"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"المس للتنزيل"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"تنزيل أو حذف"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"جارٍ التنزيل…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"انتهت صلاحية الرسالة أو ليست متاحة"</string>
+    <string name="mms_info" msgid="3402311750134118165">"الحجم: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>، تاريخ انتهاء الصلاحية: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"يتعذر الإرسال. المستلم غير صالح."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"لم يتم تنشيط الخدمة على الشبكة"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"تعذر الإرسال بسبب حدوث مشكلة في الشبكة"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"انتهت صلاحية الرسالة أو ليست متاحة"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(بلا موضوع)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"مرسل غير معروف"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"تم التسليم"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"تعذر تنزيل الرسالة <xliff:g id="SUBJECT">%1$s</xliff:g> من <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"تعذر إتمام تشغيل قاعدة البيانات نظرًا لانخفاض الذاكرة"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"لم يتم إرسال الرسالة"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"لم يتم إرسال بعض الرسائل في تطبيق المراسلة"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="zero"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثة</item>
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في محادثتين (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثات</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثة</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> من المحادثات</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> من الرسائل في محادثة واحدة</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"لم يتم تنزيل الرسالة"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"لم يتم تنزيل بعض الرسائل في تطبيق المراسلة"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="zero"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثة</item>
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في محادثتين (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثات</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> محادثة</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> من الرسائل في <xliff:g id="CONVERSATIONS">%d</xliff:g> من المحادثات</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> من الرسائل في محادثة واحدة</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"لم يتم إرسال رسالة إلى <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"الرجاء إجراء مكالمة صوتية لخدمات الطوارئ. يتعذر إرسال رسالتك النصية إلى <xliff:g id="NUMBER">%1$s</xliff:g> في الوقت الحالي."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="zero">ليست هناك أية رسالة جديدة (<xliff:g id="MESSAGES">%d</xliff:g>)</item>
+      <item quantity="two">رسالتان (<xliff:g id="MESSAGES">%d</xliff:g>) جديدتان</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> رسائل جديدة</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> رسالة جديدة</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> من الرسائل الجديدة</item>
+      <item quantity="one">رسالة جديدة</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"بدء"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"لا تتوفر كاميرا"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"لا تتوفر كاميرا"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ميزة التقاط الفيديو غير متاحة"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"يتعذر حفظ ملف الوسائط"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"لا يمكن التقاط الصورة"</string>
+    <string name="back" msgid="1477626055115561645">"رجوع"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"المؤرشفة"</string>
+    <string name="action_delete" msgid="4076795795307486019">"حذف"</string>
+    <string name="action_archive" msgid="5437034800324083170">"أرشيف"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"إزالة من الأرشيف"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"إيقاف الإشعارات"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"تشغيل الإشعارات"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"إضافة جهة اتصال"</string>
+    <string name="action_download" msgid="7786338136368564146">"تنزيل"</string>
+    <string name="action_send" msgid="377635240181672039">"إرسال"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"حذف"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"هل تريد حذف هذه الرسالة؟"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"لا يمكن التراجع عن هذا الإجراء."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"حذف"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="zero">ليست هناك محادثات.</item>
+      <item quantity="two">هل تريد حذف هاتين المحادثتين؟</item>
+      <item quantity="few">هل تريد حذف هذه المحادثات؟</item>
+      <item quantity="many">هل تريد حذف هذه المحادثات؟</item>
+      <item quantity="other">هل تريد حذف هذه المحادثات؟</item>
+      <item quantity="one">هل تريد حذف هذه الدردشة؟</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"حذف"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"إلغاء"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"إلى"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"تحديد صور متعددة"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"تأكيد الاختيار"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"يتعذر تسجيل الصوت. أعد المحاولة."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"يتعذر تشغيل الصوت. أعد المحاولة."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"تعذر حفظ الصوت. أعد المحاولة."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"اللمس مع الاستمرار"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"، "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"الصورة"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"مقطع صوتي"</string>
+    <string name="notification_video" msgid="4331423498662606204">"الفيديو"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"بطاقة جهة الاتصال"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"تنزيل"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"‏الرد عبر رسالة قصيرة SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"الرد عبر رسالة وسائط متعددة"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"الرد"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="zero">ليس هناك أي مشارك (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="two">مشاركان (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> مشاركين</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> مشاركًا</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> من المشاركين</item>
+      <item quantity="one">مشارك واحد (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"أنا"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"تم حظر جهة الاتصال وأرشفتها"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"تم إلغاء حظر جهة الاتصال وإلغاء أرشفتها"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"تم وضع <xliff:g id="COUNT">%d</xliff:g> في الأرشيف"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"تمت إزالة <xliff:g id="COUNT">%d</xliff:g> من الأرشيف"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"تم تعطيل الإشعارات"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"تم تشغيل الإشعارات"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"اكتمل الإعداد. المس \"إرسال\" مرة أخرى."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"‏تم تعيين تطبيق المراسلة كتطبيق الرسائل القصيرة SMS الافتراضي بنجاح."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="zero">ليست هناك مرفقات</item>
+      <item quantity="two">تجاهل المرفقين</item>
+      <item quantity="few">تجاهل المرفقات</item>
+      <item quantity="many">تجاهل المرفقات</item>
+      <item quantity="other">تجاهل المرفقات</item>
+      <item quantity="one">تجاهل المرفق</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"مرفق صوتي"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"تشغيل المرفق الصوتي"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"إيقاف مؤقت"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"رسالة من <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"رسالة تعذر إرسالها من <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"رسالة من <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"رسالة لم يتم إرسالها إلى <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"جارٍ إرسال رسالة إلى <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"رسالة تعذر إرسالها إلى <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"رسالة إلى <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"رسالة تعذر إرسالها من <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"رسالة من <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"رسالة لم يتم إرسالها إلى <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"جارٍ إرسال رسالة إلى <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"رسالة تعذر إرسالها إلى <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"رسالة إلى <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. الوقت: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"رسالة تعذر إرسالها. المس لإعادة المحاولة."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"محادثة مع <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"حذف الموضوع"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"التقاط فيديو"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"التقاط صورة ثابتة"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"التقاط صورة"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"بدء تسجيل الفيديو"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"التبديل إلى الكاميرا بملء الشاشة"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"التبديل بين الكاميرا الأمامية والخلفية"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"وقف التسجيل وإرفاق مقطع الفيديو"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"إيقاف تسجيل الفيديو"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"صور المراسلة"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="zero">لم يتم حفظ أية صورة (<xliff:g id="QUANTITY_2">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="two">تم حفظ صورتين (<xliff:g id="QUANTITY_2">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> صور في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> صورة في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> من الصور في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">تم حفظ صورة واحدة (<xliff:g id="QUANTITY_0">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="zero">لم يتم حفظ أي مقطع فيديو (<xliff:g id="QUANTITY_2">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="two">تم حفظ مقطعي فيديو (<xliff:g id="QUANTITY_2">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> مقاطع فيديو في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> مقطع فيديو في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> من مقاطع الفيديو في الألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">تم حفظ مقطع فيديو واحد (<xliff:g id="QUANTITY_0">%d</xliff:g>) في الألبوم \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="zero">لم يتم حفظ أي مرفق (<xliff:g id="QUANTITY_2">%d</xliff:g>) في ألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="two">تم حفظ مرفقين (<xliff:g id="QUANTITY_2">%d</xliff:g>) في ألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> مرفقات في ألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> مرفقًا في ألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other">تم حفظ <xliff:g id="QUANTITY_2">%d</xliff:g> من المرفقات في ألبوم \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">تم حفظ مرفق <xliff:g id="QUANTITY_0">%d</xliff:g> في ألبوم \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="zero">لم يتم حفظ أي مرفق (<xliff:g id="QUANTITY_1">%d</xliff:g>) في \"التنزيلات\"</item>
+      <item quantity="two">تم حفظ مرفقين (<xliff:g id="QUANTITY_1">%d</xliff:g>) في \"التنزيلات\"</item>
+      <item quantity="few">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقات في \"التنزيلات\"</item>
+      <item quantity="many">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقًا في \"التنزيلات\"</item>
+      <item quantity="other">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> من المرفقات في \"التنزيلات\"</item>
+      <item quantity="one">تم حفظ مرفق واحد (<xliff:g id="QUANTITY_0">%d</xliff:g>) في \"التنزيلات\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="zero">لم يتم حفظ أية مرفقات (<xliff:g id="QUANTITY_1">%d</xliff:g>)</item>
+      <item quantity="two">تم حفظ مرفقين (<xliff:g id="QUANTITY_1">%d</xliff:g>)</item>
+      <item quantity="few">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقات</item>
+      <item quantity="many">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقًا</item>
+      <item quantity="other">تم حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> من المرفقات</item>
+      <item quantity="one">تم حفظ مرفق واحد <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="zero">لم يتعذر حفظ أية مرفقات (<xliff:g id="QUANTITY_1">%d</xliff:g>)</item>
+      <item quantity="two">تعذر حفظ مرفقين (<xliff:g id="QUANTITY_1">%d</xliff:g>)</item>
+      <item quantity="few">تعذر حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقات</item>
+      <item quantity="many">تعذر حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> مرفقًا</item>
+      <item quantity="other">تعذر حفظ <xliff:g id="QUANTITY_1">%d</xliff:g> من المرفقات</item>
+      <item quantity="one">تعذر حفظ مرفق واحد (<xliff:g id="QUANTITY_0">%d</xliff:g>)</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"تم حفظ مرفق رسالة الوسائط المتعددة"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"الإعدادات"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"المؤرشفة"</string>
+    <string name="action_close" msgid="1840519376200478419">"إغلاق"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"رسالة وسائط متعددة"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"إعدادات متقدمة"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"تصحيح الأخطاء"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"الإشعارات"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"الصوت"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"صامت"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"اهتزاز"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"محظور"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"‏تقارير تسليم الرسائل القصيرة SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"‏طلب تقرير تسليم لكل رسالة قصيرة SMS ترسلها"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"استرداد تلقائي"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"استرداد رسائل الوسائط المتعددة تلقائيًا"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"استرداد تلقائي للتجوال"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"استرداد رسائل الوسائط المتعددة عند التجوال تلقائيًا"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"المراسلة الجماعية"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"يمكنك استخدام رسائل الوسائط المتعددة لإرسال رسالة واحدة عندما يكون هناك عدة مستلمين"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"‏تطبيق الرسائل القصيرة SMS الافتراضي"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"‏تطبيق الرسائل القصيرة SMS الافتراضي"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"رقم هاتفك"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"غير معروف"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"أصوات الرسائل الصادرة"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"‏تفريغ الرسائل القصيرة SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"‏تفريغ البيانات الأولية للرسائل القصيرة SMS في ملف تخزين خارجي"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"تفريغ رسائل الوسائط المتعددة"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"تفريغ البيانات الأولية لرسائل الوسائط المتعددة في ملف تخزين خارجي"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"تنبيهات لاسلكية"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"خيارات الرسالة"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"نسخ النص"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"عرض التفاصيل"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"حذف"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"إعادة توجيه"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"تفاصيل الرسالة"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"النوع: "</string>
+    <string name="text_message" msgid="7415419755252205721">"رسالة نصية"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"رسالة وسائط متعددة"</string>
+    <string name="from_label" msgid="1947831848146564875">"من: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"إلى: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"تاريخ الإرسال: "</string>
+    <string name="received_label" msgid="4442494712757995203">"تاريخ التلقي: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"الموضوع: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"الحجم: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"الأولوية: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"عالية"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"عادية"</string>
+    <string name="priority_low" msgid="7398724779026801851">"منخفضة"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"عنوان المرسل المخفي"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"يتعذر إرسال رسالة أثناء تحميل المرفقات."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"يتعذر تحميل المرفق. أعد المحاولة."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"الشبكة ليست جاهزة بعد. يمكنك إعادة المحاولة."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"حذف النص"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"التبديل بين إدخال النص والأرقام"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"إضافة مزيد من المشاركين"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"تأكيد المشاركين"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"بدء محادثة جديدة"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"تحديد هذا العنصر"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"تشغيل الفيديو"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"الأشخاص والخيارات"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"تصحيح الأخطاء"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"الأشخاص والخيارات"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"عام"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"الأشخاص في هذه المحادثة"</string>
+    <string name="action_call" msgid="6596167921517350362">"إجراء مكالمة"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"إرسال رسالة"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"‏إرسال رسالة&lt;br/&gt;&lt;small&gt;من <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="zero">ليست هناك صور لإرسالها</item>
+      <item quantity="two">إرسال الصورتين</item>
+      <item quantity="few">إرسال الصور</item>
+      <item quantity="many">إرسال الصور</item>
+      <item quantity="other">إرسال الصور</item>
+      <item quantity="one">إرسال الصورة</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="zero">ليست هناك ملفات صوت لإرسالها</item>
+      <item quantity="two">إرسال ملفيّ الصوت</item>
+      <item quantity="few">إرسال ملفات الصوت</item>
+      <item quantity="many">إرسال ملفات الصوت</item>
+      <item quantity="other">إرسال ملفات الصوت</item>
+      <item quantity="one">إرسال ملف الصوت</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="zero">ليست هناك ملفات فيديو لإرسالها</item>
+      <item quantity="two">إرسال ملفي الفيديو</item>
+      <item quantity="few">إرسال ملفات الفيديو</item>
+      <item quantity="many">إرسال ملفات الفيديو</item>
+      <item quantity="other">إرسال ملفات الفيديو</item>
+      <item quantity="one">إرسال ملف الفيديو</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="zero">ليست هناك بطاقات جهة اتصال لإرسالها</item>
+      <item quantity="two">إرسال بطاقتي جهة الاتصال</item>
+      <item quantity="few">إرسال بطاقات جهة الاتصال</item>
+      <item quantity="many">إرسال بطاقات جهة الاتصال</item>
+      <item quantity="other">إرسال بطاقات جهة الاتصال</item>
+      <item quantity="one">إرسال بطاقة جهة الاتصال</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="zero">ليست هناك مرفقات لإرسالها</item>
+      <item quantity="two">إرسال المرفقين</item>
+      <item quantity="few">إرسال المرفقات</item>
+      <item quantity="many">إرسال المرفقات</item>
+      <item quantity="other">إرسال المرفقات</item>
+      <item quantity="one">إرسال المرفق</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="zero">لم يتم تحديد أي مرفقات</item>
+      <item quantity="two">مرفقان (<xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>) جاهزان للإرسال</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> مرفقات جاهزة للإرسال</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> مرفقًا جاهزًا للإرسال</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> من المرفقات الجاهزة للإرسال</item>
+      <item quantity="one">مرفق واحد جاهز للإرسال</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"إرسال تعليقات"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"‏عرض في متجر Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"معلومات الإصدار"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"‏الإصدار %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"تراخيص برامج مفتوحة مصدر"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"الإشعارات"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"تم بلوغ حد المرفقات"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"أخفق تحميل المرفق."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"إضافة إلى جهات الاتصال؟"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"إضافة جهة اتصال"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"الموضوع"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"الموضوع: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"جارٍ تحميل بطاقة جهة الاتصال"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"تعذر تحميل بطاقة جهة الاتصال"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"عرض بطاقة جهة الاتصال"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="zero">ليست هناك أية جهة اتصال (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="two">جهتا اتصال (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> جهات اتصال</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> جهة اتصال</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> من جهات الاتصال</item>
+      <item quantity="one">جهة اتصال واحدة (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"بطاقات جهات الاتصال"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"تاريخ الميلاد"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ملاحظات"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"إعادة توجيه الرسالة"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"رد"</string>
+    <string name="plus_one" msgid="9010288417554932581">"1+"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"‏تم تعطيل الرسائل القصيرة SMS"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"‏للإرسال، عيّن تطبيق المراسلة كتطبيق الرسائل القصيرة SMS الافتراضي"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"‏يجب تعيين تطبيق المراسلة كتطبيق الرسائل القصيرة SMS الافتراضي"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"تغيير"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"‏لاستلام رسائل، عيّن تطبيق المراسلة كتطبيق الرسائل القصيرة SMS الافتراضي"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"‏لم يتم تحديد شريحة SIM المفضلة لإرسال رسائل قصيرة SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"لم يتم السماح لهذا التطبيق بواسطة مالك الجهاز."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"موافق"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"هناك عدد كبير جدًا من المشاركين في محادثة"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="zero">ليست هناك جهات اتصال غير صالحة</item>
+      <item quantity="two">جهتا اتصال غير صالحتين</item>
+      <item quantity="few">جهات اتصال غير صالحة</item>
+      <item quantity="many">جهات اتصال غير صالحة</item>
+      <item quantity="other">جهات اتصال غير صالحة</item>
+      <item quantity="one">جهة اتصال غير صالحة</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"يتعذر تحميل صورة الكاميرا"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"أنت: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"مسودة"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"بعد بدء دردشة جديدة، ستظهر مدرجة هنا"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"الإشعارات المؤرشفة تظهر هنا"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"جارٍ تحميل المحادثات..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"صورة"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"مقطع صوتي"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"فيديو"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"بطاقة جهة الاتصال"</string>
+    <string name="mms_text" msgid="1528791558806015806">"رسالة وسائط متعددة"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"تراجع"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"إعادة المحاولة"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"أدخل اسم جهة اتصال أو رقم هاتف لبدء رسالة جديدة"</string>
+    <string name="action_block" msgid="9032076625645190136">"حظر"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"حظر <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"إلغاء حظر <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"هل تريد حظر <xliff:g id="DESTINATION">%s</xliff:g>؟"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ستستمر في استلام الرسائل من هذا الرقم ولكن لن يتم إرسال إشعارات إليك مرة أخرى. ستتم أرشفة هذه المحادثة."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"جهات الاتصال المحظورة"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"إلغاء الحظر"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"جهات الاتصال المحظورة"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"اختيار صورة من مكتبة المستندات"</string>
+    <string name="sending_message" msgid="6363584950085384929">"جارٍ إرسال الرسالة"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"تم إرسال الرسالة"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"تم إيقاف اتصال بيانات الجوّال. تحقق من إعداداتك."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"يتعذر إرسال رسائل في وضع الطائرة"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"تعذر إرسال الرسالة"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"تم تنزيل الرسالة"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"تم إيقاف اتصال بيانات الجوّال. تحقق من إعداداتك."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"يتعذر تنزيل الرسائل في وضع الطائرة"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"تعذر تنزيل الرسالة"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"صفر"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"واحد"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"اثنان"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"ثلاثة"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"أربعة"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"خمسة"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ستة"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"سبعة"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ثمانية"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"تسعة"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"يتعذر إرسال الرسالة مع <xliff:g id="CARRIERNAME">%1$s</xliff:g>، الخطأ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"يتعذر إرسال الرسالة مع مشغِّل شبكة جوّال غير معروف، الخطأ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"إعادة التوجيه: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"لم يتم إرسال الرسالة: لم يتم تنشيط الخدمة على الشبكة"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"لم يتم إرسال الرسالة: عنوان الوجهة غير صالح"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"لم يتم إرسال الرسالة: رسالة غير صالحة"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"لم يتم إرسال الرسالة: محتوى غير متوافق"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"لم يتم إرسال الرسالة: رسالة غير متوافقة"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"لم يتم إرسال الرسالة: الحجم كبير جدًا"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"رسالة جديدة"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"عرض"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"صورة"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"تعذر العثور على تطبيق مناسب"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"إزالة المستلم"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"رسالة جديدة"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"إلغاء"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"تعديل نقطة الدخول"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"لم يتم التعيين"</string>
+    <string name="apn_name" msgid="1572691851070894985">"الاسم"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"الخادم الوكيل لرسائل الوسائط المتعددة"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"منفذ رسائل الوسائط المتعددة"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"‏نوع APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"‏حذف APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"‏APN جديد"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"حفظ"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"تجاهل"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"لا يمكن أن يكون حقل الاسم فارغًا."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"‏لا يمكن أن يكون APN فارغًا."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"‏يجب أن يكون حقل MCC من ثلاثة أرقام."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"‏يجب أن يتكون حقل MNC من رقمين أو ثلاثة أرقام."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"‏جارٍ استعادة إعدادات APN الافتراضية."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"إعادة تعيين إلى الإعداد الافتراضي"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"‏اكتملت إعادة تعيين إعدادات APN الافتراضية."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"بلا عنوان"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"أسماء نقاط الدخول"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"‏أسماء نقاط الدخول (APN)"</string>
+    <string name="menu_new" msgid="8286285392706532511">"‏APN جديد"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"إعدادات اسم نقطة الدخول ليست متوفرة لهذا المستخدم"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"هل تريد النسخ في الحافظة؟"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"نسخ"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"إلى <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"عام"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"إعدادات متقدمة"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"الإعدادات العامة"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"إعدادات متقدمة"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"‏شريحة SIM من \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"إرسال رسالة قصيرة واحدة إلى جميع المستلمين. ولن تصل الردود إلا إليك"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"إرسال رسالة وسائط متعددة إلى جميع المستلمين"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"رقم غير معروف"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"رسالة جديدة"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"رسالة جديدة."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"‏محدد SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"‏تم اختيار <xliff:g id="SIM_0">%1$s</xliff:g>، أداة اختيار شريحة SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"تعديل الموضوع"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"‏تحديد SIM أو تعديل الموضوع"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"المس مع الاستمرار لتسجيل الصوت"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"بدء محادثة جديدة"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"المراسلة"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"قائمة المراسلة"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"المراسلة"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"رسالة جديدة"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"قائمة المحادثات"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"جارٍ تحميل المحادثات."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"جارٍ تحميل الرسائل"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"عرض المزيد من المحادثات"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"عرض المزيد من الرسائل"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"تم حذف المحادثة"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"تم حذف المحادثة. المس لعرض محادثة مختلفة في تطبيق المراسلة"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"تم الحظر"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"تم إلغاء الحظر"</string>
+    <string name="db_full" msgid="8459265782521418031">"مساحة التخزين منخفضة. ربما يتم فقد بعض البيانات."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"تحديد المرفقات"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"تأكيد التحديد"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"تم تحديد <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"يُرجى إزالة مرفق أو أكثر وإعادة المحاولة."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"يمكنك محاولة إرسال الرسالة، ولكن ربما لا يتم تسليمها ما لم تتم إزالة مرفق أو أكثر من هذه الرسالة."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"لا يمكنك إرسال أكثر من مقطع فيديو واحد لكل رسالة. يُرجى إزالة مقاطع الفيديو الإضافية وإعادة المحاولة."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"أخفق تطبيق المراسلة في تحميل المرفق."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"إرسال على أية حال"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"لا يمكن بدء المحادثة"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"تم اختيار <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-az/arrays.xml b/res/values-az/arrays.xml
new file mode 100644
index 0000000..f4b43e4
--- /dev/null
+++ b/res/values-az/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"mövzu yoxdur"</item>
+    <item msgid="272485471009191934">"mövzusuz"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Hə"</item>
+    <item msgid="6049132459802288033">"Yox"</item>
+    <item msgid="3084376867445867895">"Ok"</item>
+    <item msgid="3155097332660174689">"Heh"</item>
+    <item msgid="2611328818571146775">"Çox sağ olun"</item>
+    <item msgid="4881335087096496747">"Razıyam"</item>
+    <item msgid="2422296858597420738">"Nizza"</item>
+    <item msgid="4805581752819452687">"Yolumda"</item>
+    <item msgid="4746700499431366214">"Ok, Sizinlə sonra əlaqə saxlayacam"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
new file mode 100644
index 0000000..56b4274
--- /dev/null
+++ b/res/values-az/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mesajlaşma"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mesajlaşma"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Söhbəti seç"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ayarlar"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Mesaj göndər"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Qoşma əlavə edin"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Yardım"</string>
+    <string name="welcome" msgid="2857560951820802321">"Xoş gəlmisiniz"</string>
+    <string name="skip" msgid="7238879696319945853">"Ötürün"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Sonrakı &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Növbəti"</string>
+    <string name="exit" msgid="1905187380359981199">"Çıxış"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"&amp;gt ayarlar;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ayarlar"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mesajlaşma SMS, Telefon və Kontaktlara icazə istəyir."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"İcazələri Ayarlar &gt; Tətbiqlər &gt; Mesajlaşma &gt; İcazələr bölməsindən dəyişə bilərsiniz."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"İcazələri Ayarlar, Tətbiqlər, Mesajlaşma, İcazələr bölməsindən dəyişə bilərsiniz."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Tez-tez olanlar"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Bütün kontaktlar"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> ünvanına göndərin"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Şəkilləri və ya videonu çəkin"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Bu cihazdan şəkillər seçin"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Səs yazın"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Foto seçin"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Media seçildi."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Media seçilmədi."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> seçilib"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"təsvir <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"təsvir"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Səs yazın"</string>
+    <string name="action_share" msgid="2143483844803153871">"Paylaş"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"İndicə"</string>
+    <string name="posted_now" msgid="867560789350406701">"İndi"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dəq</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dəq</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> saat</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> saat</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> gün</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> gün</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> həftə</item>
+      <item quantity="one">bir həftə</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ay</item>
+      <item quantity="one">bir ay</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> il</item>
+      <item quantity="one">bir il</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Klass 0 mesaj"</string>
+    <string name="save" msgid="5081141452059463572">"Yadda saxlayın"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Cihazda boş yer azdır. Yer boşaltmaq üçün Mesajlaşma köhnə mesajları avtomatik siləcək."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Yaddaş ehtiyatı qurtarır"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Mesajlaşma cihazınızda kifayət qədər yaddaş olmayana kimi mesaj göndərə və qəbul etməyə bilər."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS yaddaşı azdır. Mesajları silmə ehtiyacı hiss edə bilərsiniz."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Telefon nömrənizi təsdiq edin"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Bu bir addımlı mərhələ Mesajlaşmanın qrup mesajlarınızı düzgün şəkildə çatdıracağını təmin edəcək."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefon nömrəsi"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Media ilə olan bütün mesajları silin"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> müddətindən əvvəl köhnə mesajları silin"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> müddətindən köhnə mesajlar avtomatik silinsin"</string>
+    <string name="ignore" msgid="7063392681130898793">"İqnor edin"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Bütün mesajlar media ilə birlikdə silinsin?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> müddətindən köhnə mesajlar silinsin?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> müddətindən köhnə mesajlar avtomatik silinsin və avtomatik silinmə aktiv olsun?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> bildirib"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Bildirdiniz"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> tərəfindən mesaj:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Mesajı göndərdiniz"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Göndərilir..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Göndərilmədi. Yenidən cəhd etmək üçün toxunun."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Göndərilmədi. Yenidən cəhd edilir..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Resend or delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Lütfən, təcili yardım xidmətlərinə səsli zəng edin. Mətn mesajınız bu vaxt çatdırıla bilməz."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Alınmadı"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Yükləmək üçün yeni MMS mesajı"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Yeni MMS mesajı"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Yüklənmədi"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Yenidən cəhd etmək üçün toxun"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Yükləmək üçün toxun"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Yüklə və ya sil"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Yüklənir..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mesajın vaxtı bitib və ya mövcud deyil"</string>
+    <string name="mms_info" msgid="3402311750134118165">"size: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Göndərə bilmir. Alıcı etibarsızdır."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Xidmət şəbəkədə aktiv deyil"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Şəbəkə probleminə görə göndərmək olmadı"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mesajın vaxtı keçib və ya əlçatmazdır"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Mövzusuz)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Naməlum göndərən"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Çatdırılıb"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="SUBJECT">%1$s</xliff:g> mesajı <xliff:g id="FROM">%2$s</xliff:g> bölməsindən endirilə bilmir."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Az yaddaş ilə əlaqədar olaraq verilənlər bazası əməliyyatı tamamlana bilmədi"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mesaj göndərilmədi"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Bəzi mesajlar Mesajlaşmada göndərilməyib"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> söhbətdə <xliff:g id="MESSAGES_1">%d</xliff:g> mesaj</item>
+      <item quantity="one">bir söhbətdə <xliff:g id="MESSAGES_0">%d</xliff:g> mesaj</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mesaj endirilmədi"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Bəzi mesajlar Mesajlaşmada endirilməyib"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> söhbətdə <xliff:g id="MESSAGES_1">%d</xliff:g> mesaj</item>
+      <item quantity="one">bir söhbətdə <xliff:g id="MESSAGES_0">%d</xliff:g> mesaj</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> nömrəsinə mesaj göndərilmədi"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Lütfən, təcili yardım xidmətlərinə səsli zəng edin. Mətn mesajınız <xliff:g id="NUMBER">%1$s</xliff:g> nömrəsinə bu vaxt çatdırıla bilməz."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> yeni mesaj</item>
+      <item quantity="one">Yeni mesaj</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Başla"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera əlçatmazdır"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera əlçatmazdır"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video çəkiliş əlçatmazdır"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Medianı yadda saxlamaq olmur"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Şəkil çəkmək mümkün deyil"</string>
+    <string name="back" msgid="1477626055115561645">"Geri"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arxivləşmiş"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Sil"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arxiv"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Arxivdən çıxarın"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Bildirişləri deaktiv edin"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Bildirişləri aktivləşdirin"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Kontakt əlavə edin"</string>
+    <string name="action_download" msgid="7786338136368564146">"Endirin"</string>
+    <string name="action_send" msgid="377635240181672039">"Göndər"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Sil"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Bu mesaj silinsin?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Bu əməliyyat geri qaytarıla bilməz."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Sil"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Bu söhbətlər silinsin?</item>
+      <item quantity="one">Bu söhbət silinsin?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Sil"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Ləğv et"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kimə"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Çox şəkil seçin"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Seçimi təsdiq edin"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Audionu qeydə almaq olmur. Yenidən cəhd edin."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Audionu oxutmaq olmur. Yenidən cəhd edin."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Audionu saxlamaq olmadı. Yenidən cəhd edin."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Toxunun və saxlayın"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Şəkil"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio klip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videolar"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontakt kartı"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Endirin"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ilə cavab verin"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS vasitəsilə cavab verin"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Cavabla"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> iştirakçı</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> iştirakçı</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Mən"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt bloklandı və arxivləndi"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt blokdan və arxivdən çıxarıldı"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arxivlənib"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> arxivdən çıxarıldı"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Bildirişlər deaktiv edildi"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Bildirişlər aktiv edildi"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Hamısı hazırdır. Göndərmək üçün toxunun."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mesajlaşma uğurla defolt SMS tətbiqi seçildi."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Qoşmaları ləğv edin</item>
+      <item quantity="one">Qoşmanı ləğv edin</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio qoşma"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Audio qoşmanı ifa et"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pauza"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> adlı göndərəndən mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> adlı göndərənin mesajı getmədi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> adlı göndərən tərəfindən mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> adlı əlaqəyə göndərilməmiş mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> adlı əlaqəyə mesaj göndərilir: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> adlı əlaqəyə mesaj göndərilmədi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> adlı əlaqəyə mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> adlı göndərənin mesajı getmədi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> adlı göndərən tərəfindən mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> istifadəçisinə göndərilməmiş mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> istifadəçisinə mesaj göndərilir: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> istifadəçisinə mesaj göndərilmədi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> istifadəçisinə mesaj: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaxt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mesaj göndərilmədi. Təkrar cəhd etmək üçün toxunun."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> ilə söhbət"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Mövzunu silin"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video çəkin"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Durğun şəkli çəkin"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Şəkil çəkin"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Video çəkilişə başlayın"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Tam ekranlı kameraya keçin"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Ön və arxa kameralar arasında seçim edin"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Çəkilişi dayandırın və videonu qoşun"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Video qeydi dayandırın"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto mesajlaşma"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> qoşma \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> qoşma \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albomunda yadda saxlanıldı</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> qoşma \"Endirilənlər\" qovluğunda yadda saxlanıldı</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> qoşma \"Endirilənlər\" qovluğunda yadda saxlanıldı</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> qoşma yadda saxlanıldı</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> qoşma yadda saxlanıldı</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> qoşma yadda saxlanıla bilmədi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> qoşma yadda saxlanıla bilmədi</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS qoşması yadda saxlandı"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ayarlar"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arxivləşmiş"</string>
+    <string name="action_close" msgid="1840519376200478419">"Bağla"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Qabaqcıl"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Sazlama"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Bildirişlər"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Səs"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Səssiz"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Titrət"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloklanmış"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS çatdırma xətaları"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Hər göndərdiyiniz SMS üçün çatdırılma raportu tələb edin"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Avtomatik əldə edin"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS mesajları avtomatik əldə edin"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Rouminq zamanı avtomatik əldə edin"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Rominq zamanı MMS-i avtomatim bərpa edin"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Qrup mesajlaşması"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Bir neçə alıcının olduğu halda bir mesaj göndərmək üçün MMS istifadə edin"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Defolt SMS proqramı"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Defolt SMS proqramı"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Telefon nömrəniz"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Naməlum"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Gedən mesaj səsləri"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Damp SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Damp xarici saxlanma faylına emal edilməmiş SMS datası qəbul etdi"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Damp MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Damp xarici saxlanma faylına emal edilməmiş MMS datası qəbul etdi"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Simsiz siqnallar"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Mesaj seçimləri"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Mətni kopyalayın"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Detallara baxın"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Sil"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Yönləndir"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Mesaj detalları"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Növ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mətn mesajı"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia mesajı"</string>
+    <string name="from_label" msgid="1947831848146564875">"Kimdən: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kimə: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Göndərilən: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Qəbul edilən: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Mövzu: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Ölçü: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Yüksək"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Aşağı"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Gizli göndərici ünvanı"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Qoşmalar yüklənən zaman mesaj göndərmək olmur."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Qoşma yüklənə bilmir. Yenidən cəhd edin."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Şəbəkə hazır deyil. Yenidən cəhd edin."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Mətni silin"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Mətn və nömrə daxiletməsi arasında seçim edin"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"İştirakçı əlavə edin"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"İştirakçıları təsdiq edin"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Yeni söhbətə başlayın"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Bu elementi seçin"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Videonu oxut"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Adamlar və seçimlər"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Sazlama"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Adamlar və seçimlər"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Ümumi"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Bu söhbətdəki adamlar"</string>
+    <string name="action_call" msgid="6596167921517350362">"Zəng edin"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Mesaj göndərin"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Mesaj göndərin&lt;br/&gt;&lt;kiçik&gt;buradan: <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/kiçik&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Fotolar göndərin</item>
+      <item quantity="one">Foto göndərin</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Audioları göndərin</item>
+      <item quantity="one">Audio göndərin</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Videoları göndərin</item>
+      <item quantity="one">Video göndərin</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Kontakt kartlarını göndərin</item>
+      <item quantity="one">Kontakt kartını göndərin</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Qoşmaları göndərin</item>
+      <item quantity="one">Qoşma göndərin</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> qoşma göndərilmə üçün hazırdır</item>
+      <item quantity="one">1 qoşma göndərilmə üçün hazırdır</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Geri əlaqə göndərin"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store\'də bax"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versiya haqqında"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versiya %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Açıq mənbə lisenziyaları"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Bildirişlər"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Qoşma limitini keçdi"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Qoşmanı yükləyə bilmədi."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Kontaktlara əlavə edilsin?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Kontakt əlavə edin"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Mövzu"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Mövzu: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontakt kartı yüklənir"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kontakt kartını yükləmək alınmadı"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Kontakt kartına baxın"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontakt kartları"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Doğum günü"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Qeydlər"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Mesajı yönləndirin"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Cavablayın"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS deaktivdir"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Göndərmək üçün Mesajlaşmanı defolt SMS tətbiqi kimi ayarlayın"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Mesajlaşmanı defolt SMS tətbiqi kimi ayarlayın"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Dəyişin"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Mesaj qəbul etmək üçün Mesajlaşmanı defolt SMS tətbiqi kimi ayarlayın"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS göndərmək üçün tərcih olunan SIM seçilməyib"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Bu tətbiqə cihaz sahibi tərəfindən icazə verilmir."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Ok"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Söhbətdə həddən çox iştirakçı var"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Yanlış kontakt</item>
+      <item quantity="one">Yanlış kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kamera şəklini yükləmək olmur"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Siz: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Qaralama"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Söhbətə başlayan kimi onu burada siyahılanmış görəcəksiniz"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arxivlənmiş söhbətlər burada görünür"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Söhbətlər yüklənir…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Şəkil"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio klip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Əlaqə kartı"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Geri"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Yenidən cəhd edin"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Yeni mesaja başlamaq üçün kontakt adını və ya telefon nömrəsini daxil edin"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blok edin"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> bloklayın"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> blokdan çıxarın"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> bloklansın?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Bu nömrədən mesaj almağa davam edəcəksiniz, lakin mesajın gəlməsinə dair bildiriş olmayacaq. Söhbət arxivlənəcək."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Bloklanmış kontaktlar"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"BLOKDAN ÇIXARIN"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Bloklanmış kontaktlar"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Sənəd kitabxanasından şəkil seçin"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Mesaj göndərilir"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mesaj göndərildi"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobil data deaktivdir. Ayarları yoxlayın."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Təyyarə rejimində mesaj göndərmək olmur"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Mesaj göndərilə bilmədi"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mesaj yükləndi"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobil data deaktivdir. Ayarları yoxlayın."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Təyyarrə rejimində mesajları endirə bilməz"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Mesaj endirilə bilmədi"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Sıfır"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Bir"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"İki"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Üç"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Dörd"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Beş"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Altı"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Yeddi"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Səkkiz"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Doqquz"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Mesajı <xliff:g id="CARRIERNAME">%1$s</xliff:g> ilə göndərmək olmur, xəta <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Mesajı naməlum operator ilə göndərmək olmur, xəta <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Yön: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mesaj göndərilmədi. Xidmət şəbəkədə aktivləşdirilməyib."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mesaj göndərilmədi: Etibarsız təyinat ünvanı"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mesaj göndərilmədi: etibarsız mesaj"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mesaj göndərilmədi: dəstəklənməyən məzmun"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mesaj göndərilmədi: dəstəklənməyən mesaj"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mesaj göndərilmədi: çox böyükdür"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Yeni mesaj"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Göstər"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Təsvir"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Uyğun tətbiqi tapmaq olmadı"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Qəbuledicini silin"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Yeni mesaj"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Ləğv et"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit access point"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ayarlanmayıb"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Ad"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proksi"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS por"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN növü"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN silin"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Yeni APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Yadda saxlayın"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"İmtina edin"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Ad sahəsi boş ola bilməz."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN boş ola bilməz."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC sahəsində 3 rəqəm olmalıdır."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC sahəsi 2 və ya 3 rəqəm olmalıdır."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Defolt APN ayarları bərpa olunur."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Sıfırlayın"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Varsayılan APN ayarlarının sıfırlanması tamamlandı."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Başlıqsız"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Çatma Nöqtəsi Adları"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Yeni APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Giriş Nöqtəsi Ad Ayarları bu istifadəçi üçün əlçatmazdır"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Panoya kopyalansın?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopyalayın"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"Buraya: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Ümumi"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Qabaqcıl"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ümumi ayarlar"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Qabaqcıl ayarlar"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Bütün alıcılara fərdi SMS göndər. Hər hansı bir cavabı özünüz olacaq"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Bütün alıcılara bir MMS göndər"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Naməlum nömrə"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Yeni mesaj"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Yeni mesaj."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM seçicisi"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> seçildi, SIM seçicisi"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Mövzunu dəyiş"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SİM seçin və ya mövzu redaktə edin"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Səs yazmaq üçün basın və saxlayın"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Yeni söhbətə başla"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mesajlaşma"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Mesajlaşma Siyahısı"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mesajlaşma"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Yeni mesaj"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Söhbət siyahısı"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Söhbətlər yüklənir"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Mesajlar yüklənir"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Daha çox söhbət görüntülə"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Daha çox mesaja bax"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Söhbət silinib"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Söhbət silindi. Başqa Mesajlaşma söhbəti göstərmək üçün toxunun"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloklanıb"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blokdan çıxarılıb"</string>
+    <string name="db_full" msgid="8459265782521418031">"Yaddaş yeri azdır. Bəzi məlumatlar itə bilər."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Qoşmaları seçin"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Seçimi təsdiq edin"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> seçilib"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Lütfən, bir və ya daha çox qoşmanı silin və yenidən cəhd edin."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Mesajınızı göndərməyə cəhd edə bilərsiniz, lakin bir və ya daha çox qoşmanı silmədiyiniz halda, mesaj çatmaya bilər."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Hər mesaja yalnız bir video yükləyə bilərsiniz. Əlavə videoları silin və yenidən cəhd edin."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mesajlaşma qoşmanı yükləyə bilmədi."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"İstənilən halda göndərin"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Söhbətə başlamaq olmadı"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> seçilmiş"</string>
+</resources>
diff --git a/res/values-bg/arrays.xml b/res/values-bg/arrays.xml
new file mode 100644
index 0000000..ac036c4
--- /dev/null
+++ b/res/values-bg/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"без тема"</item>
+    <item msgid="272485471009191934">"няма тема"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Да"</item>
+    <item msgid="6049132459802288033">"Не"</item>
+    <item msgid="3084376867445867895">"ОK"</item>
+    <item msgid="3155097332660174689">"Ха-ха"</item>
+    <item msgid="2611328818571146775">"Благодаря"</item>
+    <item msgid="4881335087096496747">"Приемам"</item>
+    <item msgid="2422296858597420738">"Чудесно"</item>
+    <item msgid="4805581752819452687">"Идвам"</item>
+    <item msgid="4746700499431366214">"OK, ще се свържа с теб по-късно"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
new file mode 100644
index 0000000..c1b8401
--- /dev/null
+++ b/res/values-bg/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Съобщения"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Съобщения"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Избиране на разговор"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Настройки"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Изпращане на съобщение"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Добавяне на прикачен файл"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Помощ"</string>
+    <string name="welcome" msgid="2857560951820802321">"Добре дошли"</string>
+    <string name="skip" msgid="7238879696319945853">"Пропускане"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Напред &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Напред"</string>
+    <string name="exit" msgid="1905187380359981199">"Изход"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Настройки &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Настройки"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Приложението Съобщения се нуждае от разрешение за SMS, телефон и контакти."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Можете да промените разрешенията от „Настройки“ &gt; „Приложения“ &gt; „Съобщения“ &gt; „Разрешения“."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Можете да промените разрешенията от „Настройки“, „Приложения“, „Съобщения“, „Разрешения“."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Често търсени"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Всички контакти"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Изпращане до <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Правете снимки или видеоклипове"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Избиране на изображения от това устройство"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Запишете звук"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Избиране на снимка"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Мултимедийният файл е избран."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Изборът на мултимедиен файл е премахнат."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Избрахте <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"изображение от <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"изображение"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Запис на звук"</string>
+    <string name="action_share" msgid="2143483844803153871">"Споделяне"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Току-що"</string>
+    <string name="posted_now" msgid="867560789350406701">"Сега"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> мин</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> мин</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> часа</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> час</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> дни</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ден</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> седмици</item>
+      <item quantity="one">една седмица</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> месеца</item>
+      <item quantity="one">един месец</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> години</item>
+      <item quantity="one">една година</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Съобщения от клас 0"</string>
+    <string name="save" msgid="5081141452059463572">"Запазване"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Мястото на устройството не е достатъчно. Приложението Съобщения автоматично ще изтрие по-старите кореспонденции, за да освободи място."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Мястото в хранилището е на изчерпване"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Възможно е Съобщения да не изпраща, нито да получава съобщения, докато на устройството не се освободи повече място."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Мястото в хранилището за SMS намалява. Може да се наложи да изтриете съобщения."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Потвърждаване на телефонния ви номер"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Тази еднократна стъпка ще гарантира, че Съобщения ще доставя правилно груповите ви съобщения."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Телефонен номер"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Изтриване на всички съобщения с мултимедия"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Изтриване на съобщенията, по-стари от <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Автоматично изтриване на съобщенията, по-стари от <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Пренебрегване"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Да се изтрият ли всички съобщения с медийни файлове?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Да се изтрият ли съобщенията, по-стари от <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Да се изтрият ли съобщенията, по-стари от <xliff:g id="DURATION">%s</xliff:g>, и да се включи ли функцията за автоматично изтриване?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> каза"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Казахте"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Съобщение от <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Изпратихте съобщение"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Изпраща се…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Не е изпратено. Докоснете за нов опит."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Не е изпратено. Извършва се нов опит…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Повторно изпращане или изтриване"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Моля, осъществете гласово обаждане до спешните служби. Понастоящем текстовото ви съобщение не можа да бъде доставено."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Не бе успешно"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Ново MMS съобщение за изтегляне"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Ново MMS съобщение"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Не можа да се изтегли"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Докоснете за нов опит"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Докоснете за изтегляне"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Изтегляне или изтриване"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Изтегля се…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Съобщението е с изтекла валидност или не е налице"</string>
+    <string name="mms_info" msgid="3402311750134118165">"размер: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, валидност: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Не може да се изпрати. Получателят не е валиден."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Услугата не е активирана за мрежата"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Не можа да се изпрати поради проблем с мрежата"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Съобщението е с изтекла валидност или не е налице"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Без тема)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Неизвестен подател"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Доставено"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Съобщението „<xliff:g id="SUBJECT">%1$s</xliff:g>“ от <xliff:g id="FROM">%2$s</xliff:g> не можа да се изтегли."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Операцията в базата от данни не можа да завърши поради недостиг на памет"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Съобщението не е изпратено"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Някои съобщения в приложението Съобщения не са изпратени"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> съобщения в <xliff:g id="CONVERSATIONS">%d</xliff:g> разговора</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> съобщения в един разговор</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Съобщението не е изтеглено"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Някои съобщения в приложението Съобщения не са изтеглени"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> съобщения в <xliff:g id="CONVERSATIONS">%d</xliff:g> разговора</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> съобщения в един разговор</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Съобщението до <xliff:g id="NUMBER">%1$s</xliff:g> не е изпратено"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Моля, осъществете гласово обаждане до спешните служби. Понастоящем текстовото ви съобщение до <xliff:g id="NUMBER">%1$s</xliff:g> не можа да бъде доставено."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> нови съобщения</item>
+      <item quantity="one">Ново съобщение</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Стартиране"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Няма достъп до камерата"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Няма достъп до камерата"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Функцията за заснемане на видео не е налице"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Медийният файл не може да се запази"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Не може да се направи снимка"</string>
+    <string name="back" msgid="1477626055115561645">"Назад"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архивирани"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Изтриване"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архивиране"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Деархивиране"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Изключване на известията"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Включване на известията"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Добавяне на контакт"</string>
+    <string name="action_download" msgid="7786338136368564146">"Изтегляне"</string>
+    <string name="action_send" msgid="377635240181672039">"Изпращане"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Изтриване"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Да се изтрие ли това съобщение?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Това действие не може да се отмени."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Изтриване"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Да се изтрият ли тези разговори?</item>
+      <item quantity="one">Да се изтрие ли този разговор?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Изтриване"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Отказ"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"До"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Избиране на няколко изображения"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Потвърждаване на избора"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Аудиото не може да се запише. Опитайте отново."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Аудиото не може да се възпроизведе. Опитайте отново."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Аудиото не можа да се запази. Опитайте отново."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Докоснете и задръжте"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  ,"</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  :"</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Снимка"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудиоклип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видеоклип"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Визитна картичка"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Изтегляне"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Отговор чрез SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Отговор чрез MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Отговор"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> участници</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> участник</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Аз"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Контактът е блокиран и архивиран"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Контактът е отблокиран и деархивиран"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Архивирахте <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Деархивирахте <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Известията са изключени"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Известията са включени"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Готово. Докоснете „Изпращане“ отново."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Успешно зададохте Съобщения като стандартно приложение за SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Отхвърляне на прикачените файлове</item>
+      <item quantity="one">Отхвърляне на прикачения файл</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Прикачен аудиофайл"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Пускане на прикачения аудиофайл"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Пауза"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Съобщение от <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Неуспешно съобщение от <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Съобщение от <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Неизпратено съобщение до <xliff:g id="CONTACT">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Изпраща се съобщение до <xliff:g id="CONTACT">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Неуспешно съобщение до <xliff:g id="CONTACT">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Съобщение до <xliff:g id="CONTACT">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Неуспешно съобщение от <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Съобщение от <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Неизпратено съобщение до <xliff:g id="GROUP">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Изпраща се съобщение до <xliff:g id="GROUP">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Неуспешно съобщение до <xliff:g id="GROUP">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Съобщение до <xliff:g id="GROUP">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Неуспешно съобщение. Докоснете, за да опитате отново."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Разговор с/ъс <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Изтриване на темата"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Заснемане на видеоклип"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Заснемане на кадър"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Правене на снимка"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Стартиране на записване на видеоклип"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Превключване към камера на цял екран"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Превключване между предната и задната камера"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Спиране на записването и прикачване на видеоклипа"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Спиране на видеозаписа"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Снимки в Съобщения"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> снимки са запазени в албума „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> снимка е запазена в албума „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> видеоклипа са запазени в албума „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> видеоклип е запазен в албума „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> прикачени файла са запазени в албума „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> прикачен файл е запазен в албума „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прикачени файла са запазени в „Изтегляния“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> прикачен файл е запазен в „Изтегляния“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прикачени файла са запазени</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> прикачен файл е запазен</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прикачени файла не можаха да бъдат запазени</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> прикачен файл не можа да се запази</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Запазен прикачен файл от MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Настройки"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архивирани"</string>
+    <string name="action_close" msgid="1840519376200478419">"Затваряне"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Разширени"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Отстраняване на грешки"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Известия"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Звук"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Тих режим"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Вибриране"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Блокирано"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Отчети за получаване на SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Заявяване на отчет за доставка за всеки изпратен от вас SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Автоматично извличане"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Автоматично извличане на мултимедийните съобщения (MMS)"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Автоматично извличане при роуминг"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Автоматично извличане на MMS при роуминг"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Групови съобщения"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Използвайте MMS, за да изпратите едно съобщение, когато има няколко получатели"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Стандартно приложение за SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Стандартно приложение за SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Вашият телефонен номер"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Няма информация"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Звуци за изходящи съобщения"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Разтоварване на SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Разтоварване на необработените данни от получените SMS съобщения във файл във външното хранилище"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Разтоварване на MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Разтоварване на необработените данни от получените MMS съобщения във файл във външното хранилище"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Безжични сигнали"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Опции на съобщението"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Копиране на текста"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Преглед на подробностите"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Изтриване"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Напред"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Подробности за съобщението"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Тип: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Текстово съобщение"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мултимедийно съобщение"</string>
+    <string name="from_label" msgid="1947831848146564875">"От: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"До: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Изпратено: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Получено: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Тема: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Размер: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Приоритет: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Висок"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Нормален"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Нисък"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Скрит адрес на изпращача"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Съобщението не може да се изпрати, докато прикачените файлове се зареждат."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Прикаченият файл не може да се зареди. Опитайте отново."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Мрежата не е готова. Опитайте отново."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Изтриване на текста"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Превключване между букви и цифри"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Добавяне на още участници"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Потвърждаване на участниците"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Начало на нова кореспонденция"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Избиране на този елемент"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Пускане на видеоклипа"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Хора и опции"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Отстраняване на грешки"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Хора и опции"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Общи настройки"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Хора в този разговор"</string>
+    <string name="action_call" msgid="6596167921517350362">"Обаждане по телефона"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Изпращане на съобщение"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Изпращане на съобщение&lt;br/&gt;&lt;small&gt;от <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Изпращане на снимките</item>
+      <item quantity="one">Изпращане на снимката</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Изпращане на аудиозаписите</item>
+      <item quantity="one">Изпращане на аудиозаписа</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Изпращане на видеоклиповете</item>
+      <item quantity="one">Изпращане на видеоклипа</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Изпращане на визитните картички</item>
+      <item quantity="one">Изпращане на визитната картичка</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Изпращане на прикачените файлове</item>
+      <item quantity="one">Изпращане на прикачения файл</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прикачени файла са готови за изпращане</item>
+      <item quantity="one">Един прикачен файл е готов за изпращане</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Изпращане на отзиви"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Преглед в Google Play Магазин"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Информация за версията"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Версия %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Лицензи за отворен код"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Известия"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Ограничението за прикачени файлове е достигнато"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Зареждането на прикачения файл не бе успешно."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Да се добави ли към контактите?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Добавяне на контакт"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Тема"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Тема: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"„<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g>“ – „<xliff:g id="MESSAGETEXT">%2$s</xliff:g>“"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Визитната картичка се зарежда"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Визитната картичка не можа да се зареди"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Преглед на визитната картичка"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контакта</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> контакт</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Визитни картички"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Рожден ден"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Бележки"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Препращане на съобщението"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Отговор"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS съобщенията са деактивирани"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"За да изпращате съобщения, задайте Съобщения като стандартно приложение за SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Задайте Съобщения като стандартно приложение за SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Промяна"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"За да получавате съобщения, задайте Съобщения като стандартно приложение за SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Няма избрана предпочитана SIM карта за изпращане на SMS съобщения"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Това приложение не е разрешено от собственика на устройството."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ОK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Твърде много участници в разговора"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Контактите са невалидни</item>
+      <item quantity="one">Контактът е невалиден</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Изображението от камерата не можа да се зареди"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Вие: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Чернова"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Когато започнете нов разговор, ще го видите посочен тук"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Тук се показват архивираните кореспонденции"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Кореспонденциите се зареждат…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Снимка"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудиоклип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видеоклип"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Визитна картичка"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Отмяна"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Повторен опит"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Въведете име на контакт или телефонен номер, за да започнете ново съобщение"</string>
+    <string name="action_block" msgid="9032076625645190136">"Блокиране"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Блокиране на <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Отблокиране на <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Да се блокира ли <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Ще продължите да получавате съобщения от този номер, но вече няма да бъдете известявани. Кореспонденцията ще се архивира."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Блокирани контакти"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ОТБЛОКИРАНЕ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Блокирани контакти"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Избиране на изображение от библиотеката с документи"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Съобщението се изпраща"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Съобщението е изпратено"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Мобилните данни са изключени. Проверете настройките си."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Не можете да изпращате съобщения в самолетен режим"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Съобщението не можа да се изпрати"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Съобщението е изтеглено"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Мобилните данни са изключени. Проверете настройките си."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Съобщенията не могат да се изтеглят в самолетен режим"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Съобщението не можа да бъде изтеглено"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"нула"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"едно"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"две"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"три"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"четири"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"пет"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"шест"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"седем"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"осем"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"девет"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Съобщението не може да се изпрати с/ъс <xliff:g id="CARRIERNAME">%1$s</xliff:g> – грешка <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Съобщението не може да се изпрати с неизвестен оператор – грешка <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Препр.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Съобщението не е изпратено: Услугата не е активирана за мрежата"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Съобщението не е изпратено: невалиден целеви адрес"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Съобщението не е изпратено: невалидно съобщение"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Съобщението не е изпратено: неподдържано съдържание"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Съобщението не е изпратено: неподдържано съобщение"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Съобщението не е изпратено: твърде голямо"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Ново съобщение"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Преглед"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Изображение"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Не можа да бъде намерено подходящо приложение"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Премахване на получателя"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Ново съобщение"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Отказ"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Редактиране на точката за достъп"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Не е зададено"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Име"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Име на точката за достъп (APN)"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS прокси сървър"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS порт"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"Mобилен код на държава"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"Код на мобилна мрежа (MNC)"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Тип на името на точката за достъп (APN)"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Изтриване на името на точката за достъп (APN)"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Ново име на точката за достъп (APN)"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Запазване"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Отхвърляне"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Полето за име трябва да се попълни."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Името на точката за достъп (APN) трябва да се попълни."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Полето за мобилен код на държавата трябва да е 3 цифри."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Полето за код на мобилна мрежа (MNC) трябва да е с 2 или 3 цифри."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Стандартните настройки за името на точката за достъп (APN) се възстановяват."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Възстановяване на стандартните"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Възстановяването на стандартните настройки за името на точката за достъп (APN) завърши."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Без име"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Имена на точката за достъп"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Имена на точката за достъп (APN)"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Ново име на точката за достъп (APN)"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Настройките за име на точката за достъп не са налице за този потребител"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Да се копира ли в буферната памет?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Копиране"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"до „<xliff:g id="SIM_NAME">%s</xliff:g>“"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Общи настройки"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Разширени настройки"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Общи настройки"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Разширени настройки"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM карта „<xliff:g id="SIM_NAME">%s</xliff:g>“"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Изпращане на отделни SMS съобщения до всички участници. Само вие ще получавате отговорите"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Изпращане на един MMS до всички участници"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Неизвестен номер"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Ново съобщение"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Ново съобщение."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Инструмент за избор на SIM карта"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Избрахте „<xliff:g id="SIM_0">%1$s</xliff:g>“ – инструмент за избиране на SIM карти"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Редактиране на темата"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Избиране на SIM карта или редактиране на темата"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Докоснете и задръжте, за да запишете аудио"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Начало на нова кореспонденция"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Съобщения"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Списък със съобщения"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Съобщения"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Ново съобщение"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Списък с кореспонденции"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Кореспонденциите се зареждат"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Съобщенията се зареждат"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Преглед на още кореспонденции"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Преглед на още съобщения"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Кореспонденцията бе изтрита"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Разговорът е изтрит. Докоснете за показване на друг от Съобщения"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Блокирано"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Отблокирано"</string>
+    <string name="db_full" msgid="8459265782521418031">"Мястото в хранилището е малко. Може да изгубите някои данни."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Избиране на прикачени файлове"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Потвърждаване на избора"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Избрахте <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Моля, премахнете един или повече прикачени файлове и опитайте отново."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Можете да опитате да изпратите съобщението си, но е възможно то да не бъде доставено, ако не премахнете един или повече прикачени файлове."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Можете да изпращате само по един видеоклип с всяко съобщение. Моля, премахнете допълнителните клипове и опитайте отново."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Зареждането на прикачения файл от Съобщения не бе успешно."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Изпращане въпреки това"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Разговорът не можа да започне"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Избрахте <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-bn/arrays.xml b/res/values-bn/arrays.xml
new file mode 100644
index 0000000..bdf164c
--- /dev/null
+++ b/res/values-bn/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"কোনো বিষয় নেই"</item>
+    <item msgid="272485471009191934">"বিষয়হীন"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"হ্যাঁ"</item>
+    <item msgid="6049132459802288033">"না"</item>
+    <item msgid="3084376867445867895">"ঠিক আছে"</item>
+    <item msgid="3155097332660174689">"হিহি"</item>
+    <item msgid="2611328818571146775">"ধন্যবাদ"</item>
+    <item msgid="4881335087096496747">"আমি রাজি"</item>
+    <item msgid="2422296858597420738">"সুন্দর"</item>
+    <item msgid="4805581752819452687">"রাস্তায় আছি"</item>
+    <item msgid="4746700499431366214">"ঠিক আছে, পরে আপনার সঙ্গে এই নিয়ে কথা বলছি"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
new file mode 100644
index 0000000..96af70b
--- /dev/null
+++ b/res/values-bn/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"বার্তাপ্রেরণ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"বার্তাপ্রেরণ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"কথোপকথন নির্বাচন করুন"</string>
+    <string name="action_settings" msgid="1329008122345201684">"সেটিংস"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"বার্তা পাঠান"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"একটি সংযুক্তি যোগ করুন"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"সহায়তা"</string>
+    <string name="welcome" msgid="2857560951820802321">"স্বাগতম"</string>
+    <string name="skip" msgid="7238879696319945853">"এড়িয়ে যান"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"পরবর্তী &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"পরবর্তী"</string>
+    <string name="exit" msgid="1905187380359981199">"প্রস্থান করুন"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"সেটিংস &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"সেটিংস"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"SMS, ফোন এবং পরিচিতিগুলিতে বার্তাপ্রেরণ -এর অনুমতির প্রয়োজন।"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"আপনি সেটিংস &gt; অ্যাপ্লিকেশানগুলি &gt; বার্তাপ্রেরণ &gt; অনুমতিগুলি এ অনুমতিগুলি পরিবর্তন করতে পারেন৷"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"আপনি সেটিংস, অ্যাপ্লিকেশানগুলি, বার্তাপ্রেরণ, অনুমতিগুলি এ অনুমতিগুলি পরিবর্তন করতে পারেন৷"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"প্রায়শই ব্যবহৃত"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"সকল পরিচিতি"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> এ পাঠান"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ছবি বা ভিডিও ক্যাপচার করুন"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"এই ডিভাইস থেকে চিত্র নির্বাচন করুন"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"অডিও রেকর্ড করুন"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ফটো চয়ন করুন"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"মিডিয়া নির্বাচিত হয়েছে।"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"মিডিয়া নির্বাচিত হয় নি।"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g>টি নির্বাচন করা হয়েছে"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"চিত্র <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"চিত্র"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"অডিও রেকর্ড করুন"</string>
+    <string name="action_share" msgid="2143483844803153871">"ভাগ করুন"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"এইমাত্র"</string>
+    <string name="posted_now" msgid="867560789350406701">"এখনই"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> মিনিট</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> মিনিট</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টা</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ঘণ্টা</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> সপ্তাহ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> সপ্তাহ</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> মাস</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> মাস</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> বছর</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> বছর</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ক্লাস ০ বার্তা"</string>
+    <string name="save" msgid="5081141452059463572">"সংরক্ষণ করুন"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ডিভাইসে কম জায়গা আছে। বার্তাপ্রেরণ জায়গা খালি করতে স্বয়ংক্রিয়ভাবে পুরানো পাঠ্য বার্তাগুলি মুছে ফেলবে।"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"সঞ্চয়স্থান পূর্ণ হতে চলেছে"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"আপনার ফোনে অরো বেশি সঞ্চয়স্থান উপলব্ধ না থাকলে, বার্তাপ্রেরণ বার্তাগুলি পাঠাতে বা গ্রহণ করতে নাও পারে৷"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS সংগ্রহস্থল বেশি নেই৷ আপনাকে বার্তা মুছতে হতে পারে৷"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"আপনার ফোন নম্বর নিশ্চিত করুন"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"এই এককালীন ধাপটি নিশ্চিত করে যে বার্তাপ্রেরণ গোষ্ঠী বার্তাগুলিকে সঠিকভাবে বিতরণ করবে৷"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ফোন নম্বর"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"মিডিয়ার সাথে সমস্ত বার্তা মুছুন"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> এর থেকে পুরানো বার্তাগুলি মুছুন"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g>-এর থেকে পুরানো বার্তা স্বংয়ক্রিয়ভাবে মুছুন"</string>
+    <string name="ignore" msgid="7063392681130898793">"উপেক্ষা করুন"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"মিডিয়ার সমন্বিত সমস্ত বার্তা মুছুন"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g>-এর থেকে পুরানো বার্তাগুলি মুছবেন?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g>-এর থেকে পুরানো বার্তা মুছে দিন এবং স্বয়ংক্রিয়ভাবে মোছা চালু করবেন?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> বলেছেন"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"আপনি বলেছেন"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> এর থেকে বার্তা"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"আপনি একটি বার্তা পাঠিয়েছেন"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"পাঠানো হচ্ছে..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"পাঠানো হয়নি। আবার চেষ্টা করতে স্পর্শ করুন।"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"পাঠানো হয়নি। আবার চেষ্টা হচ্ছে…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"আবার পাঠান অথবা মুছে ফেলুন"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"অনুগ্রহ করে জরুরি পরিষেবাগুলিতে একটি ভয়েস কল করুন৷ আপনার পাঠ্য বার্তাগুলিকে এই মূহুর্তে বিতরণ করা যাবে না৷"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ব্যর্থ হয়েছে"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ডাউনলোড করার জন্য নতুন MMS বার্তা"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"নতুন MMS বার্তা"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ডাউনলোড করা যায়নি"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"আবার চেষ্টা করতে স্পর্শ করুন"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ডাউনলোড করার জন্য স্পর্শ করুন"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ডাউনলোড করুন অথবা মুছুন"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ডাউনলোড হচ্ছে..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"বার্তার মেয়াদ শেষ হয়ে গেছে বা অনুপলব্ধ"</string>
+    <string name="mms_info" msgid="3402311750134118165">"আকার: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, মেয়াদ শেষ: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"পাঠানো যাবে না। প্রাপক বৈধ নয়।"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"নেটওয়ার্কে পরিষেবা সক্রিয় নেই"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"নেটওয়ার্ক সমস্যার কারণে পাঠানো যায়নি"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"বার্তার মেয়াদ শেষ হয়ে গেছে বা অনুপলব্ধ"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(কোনো বিষয় নেই)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"অজ্ঞাত প্রেরক"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"পৌঁছে দেওয়া হয়েছে"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> থেকে <xliff:g id="SUBJECT">%1$s</xliff:g> বার্তা ডাউনলোড করা যায়নি।"</string>
+    <string name="low_memory" msgid="5300743415198486619">"কম মেমরি থাকার কারণে ডেটাবেস ক্রিয়াকলাপ সম্পন্ন করা যায়নি"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"বার্তা পাঠানো হয়নি"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"বার্তাপ্রেরণ এ কিছু বার্তা পাঠানো হয়নি"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g>টি কথোপকথনে <xliff:g id="MESSAGES_1">%d</xliff:g>টি বার্তা রয়েছে</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>টি কথোপকথনে <xliff:g id="MESSAGES_1">%d</xliff:g>টি বার্তা রয়েছে</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"বার্তা ডাউনলোড করা যাবে না"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"বার্তাপ্রেরণ এ কিছু বার্তা ডাউনলোড করা যায়নি"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g>টি কথোপকথনে <xliff:g id="MESSAGES_1">%d</xliff:g>টি বার্তা রয়েছে</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>টি কথোপকথনে <xliff:g id="MESSAGES_1">%d</xliff:g>টি বার্তা রয়েছে</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> এ বার্তা পাঠানো হয়নি"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"অনুগ্রহ করে জরুরি পরিষেবাগুলিতে একটি ভয়েস কল করুন৷ <xliff:g id="NUMBER">%1$s</xliff:g> এ পাঠানো আপনার পাঠ্য বার্তাগুলিকে এই মূহুর্তে বিতরণ করা যাবে না৷"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g>টি নতুন বার্তা</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g>টি নতুন বার্তা</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"আরম্ভ"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ক্যামেরা উপলব্ধ নয়"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ক্যামেরা উপলব্ধ নয়"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ভিডিও ক্যাপচার উপলব্ধ নয়"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"মিডিয়া সংরক্ষণ করা যাবে না"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ছবি তুলতে পারবেন না"</string>
+    <string name="back" msgid="1477626055115561645">"ফিরুন"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"সংরক্ষণাগারভুক্ত"</string>
+    <string name="action_delete" msgid="4076795795307486019">"মুছুন"</string>
+    <string name="action_archive" msgid="5437034800324083170">"সংরক্ষণ করুন"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"সংরক্ষণাগারমুক্ত করুন"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"বিজ্ঞপ্তিগুলি বন্ধ করুন"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"বিজ্ঞপ্তি চালু করুন"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"পরিচিতি যোগ করুন"</string>
+    <string name="action_download" msgid="7786338136368564146">"ডাউনলোড করুন"</string>
+    <string name="action_send" msgid="377635240181672039">"পাঠান"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"মুছুন"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"এই বার্তাটি মুছবেন?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"এই কাজটিকে পূর্বাবস্থায় ফেরানো যাবে না৷"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"মুছুন"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">এই কথোপকথনগুলি মুছবেন?</item>
+      <item quantity="other">এই কথোপকথনগুলি মুছবেন?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"মুছুন"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"বাতিল করুন"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"প্রাপক"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"একাধিক চিত্র নির্বাচন করুন"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"নির্বাচন নিশ্চিত করুন"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>টি"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"অডিও রেকর্ড করা যাবে না। আবার চেষ্টা করুন।"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"অডিও প্লে করা যাবে না। আবার চেষ্টা করুন।"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"অডিও সংরক্ষণ করা যায়নি। আবার চেষ্টা করুন"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"স্পর্শ করুন এবং ধরে রাখুন"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ছবি"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"অডিও ক্লিপ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ভিডিও"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"পরিচিতি কার্ড"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ডাউনলোড"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS এর মাধ্যমে উত্তর দিন"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS এর মাধ্যমে উত্তর দিন"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"উত্তর দিন"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> জন অংশগ্রহণকারী</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> জন অংশগ্রহণকারী</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"আমি"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"পরিচিতি অবরুদ্ধ ও সংরক্ষণাগারভুক্ত হয়েছে"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"পরিচিতি অবরোধ মুক্ত এবং সংরক্ষণাগারমুক্ত করা হয়েছে"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> টি সংরক্ষণাগারভুক্ত হয়েছে"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> সংরক্ষণাগারমুক্ত হয়েছে"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"বিজ্ঞপ্তিগুলি বন্ধ করা হয়েছে"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"বিজ্ঞপ্তিগুলি চালু করা হয়েছে"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"সবকিছু সেট। আবার পাঠাতে স্পর্শ করুন।"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"ডিফল্ট SMS অ্যাপ্লিকেশান হিসাবে বার্তাপ্রেরণ সফলভাবে সেট করা হয়েছে৷"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">সংযুক্তিগুলি বাতিল করুন</item>
+      <item quantity="other">সংযুক্তিগুলি বাতিল করুন</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"অডিও সংযুক্তি"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"অডিও সংযুক্তি চালান"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"বিরাম দিন"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> এর পাঠানো বার্তা: <xliff:g id="MESSAGE">%2$s</xliff:g>৷"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>:-র <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠাতে ব্যর্থ হয়েছে। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>: এর থেকে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>: -কে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠানো যায় নি। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>: -কে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠাচ্ছে। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>: -কে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠাতে ব্যর্থ হয়েছে। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>: -কে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠান। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠাতে ব্যর্থ হয়েছেন। সময়: <xliff:g id="TIME">%3$s</xliff:g>। <xliff:g id="GROUPINFO">%4$s</xliff:g>।"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>: এর থেকে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা। সময়: <xliff:g id="TIME">%3$s</xliff:g>। <xliff:g id="GROUPINFO">%4$s</xliff:g>।"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>: -কে <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠানো যায় নি। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>:-এ <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠানো হচ্ছে। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>: -এ <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠাতে ব্যর্থ হয়েছে। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>: -এ <xliff:g id="MESSAGE">%2$s</xliff:g> বার্তা পাঠান। সময়: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"বার্তা পাঠাতে ব্যর্থ হয়েছে। পুনরায় চেষ্টা করতে স্পর্শ করুন।"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> এর সাথে কথোপকথন"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"বিষয় মুছুন"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ভিডিও ক্যাপচার করুন"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"একটি স্থির চিত্র ক্যাপচার করুন"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ছবি তুলুন"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ভিডিও রেকর্ডিং শুরু করুন"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"সম্পূর্ণ স্ক্রীন ক্যামেরাতে স্যুইচ করুন"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"সামনে ও পিছনে ক্যামেরার মধ্যে স্যুইচ করুন"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"রেকর্ডিং করা বন্ধ করুন এবং ভিডিও সংযুক্ত করুন"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ভিডিও রেকর্ডিং বন্ধ করুন"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"বার্তাপ্রেরণ ফটোগুলি"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g>টি ফটো \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>টি ফটো \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g>টি ভিডিও \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>টি ভিডিও \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g>টি সংযুক্তি \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>টি সংযুক্তি \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" অ্যালবামে সংরক্ষিত হয়েছে</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি \"ডাউনলোডগুলি\" এ সংরক্ষিত হয়েছে</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি \"ডাউনলোডগুলি\" এ সংরক্ষিত হয়েছে</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি সংরক্ষণ করা হয়েছে</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি সংরক্ষণ করা হয়েছে</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি সংরক্ষণ করা যায়নি</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>টি সংযুক্তি সংরক্ষণ করা যায়নি</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS সংযুক্তি সংরক্ষণ করা হয়েছে"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"সেটিংস"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"সংরক্ষণাগারভুক্ত"</string>
+    <string name="action_close" msgid="1840519376200478419">"বন্ধ করুন"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"উন্নত"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ডিবাগ"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"আওয়াজ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"নীরব"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"কম্পন"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"অবরুদ্ধ"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS বিতরণের প্রতিবেদনগুলি"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"আপনি যে SMS পাঠাবেন তার প্রতিটির জন্য পৌঁছে দেওয়ার প্রতিবেদনের অনুরোধ করুন"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"স্বতঃ-উদ্ধার"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"স্বয়ংক্রিয়ভাবে MMS বার্তাগুলি পুনরুদ্ধার করুন"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"রোমিং থাকাকালীন স্বতঃ-উদ্ধার"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"রোমিং-এ থাকার সময় স্বয়ংক্রিয়ভাবে MMS পুনরুদ্ধার করুন"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"গোষ্ঠীর মধ্যে বার্তাপ্রেরণ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"যখন একাধিক প্রাপক রয়েছে তখন একটি বার্তা পাঠাতে MMS ব্যবহার করুন"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ডিফল্ট SMS অ্যাপ্লিকেশান"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ডিফল্ট SMS অ্যাপ্লিকেশান"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"আপনার ফোন নম্বর"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"অজানা"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"আউটগোয়িং বার্তার শব্দগুলি"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"ডাম্প SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"পাওয়া SMS এর অপীষ্কার ডেটাকে বহিরাগত সংগ্রহস্থলে জমা করুন"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"ডাম্প MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"গৃহিত MMS এর কাঁচা ডেটাকে বহিরাগত সংগ্রহস্থলে জমা করুন"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"বেতার সতর্কতাগুলি"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"বার্তা বিকল্পগুলি"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"পাঠ্য অনুলিপি করুন"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"বিশদ বিবরণ দেখুন"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"মুছুন"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ফরওয়ার্ড করুন"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"বার্তার বিশদ বিবরণ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"প্রকার: "</string>
+    <string name="text_message" msgid="7415419755252205721">"পাঠ্য বার্তা"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"মাল্টিমিডিয়া বার্তা"</string>
+    <string name="from_label" msgid="1947831848146564875">"প্রেরক: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"প্রাপক: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"পাঠানো হয়েছে: "</string>
+    <string name="received_label" msgid="4442494712757995203">"গ্রহণ করা হয়েছে: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"বিষয়: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"মাপ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"অগ্রাধিকার: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"উচ্চ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"স্বাভাবিক"</string>
+    <string name="priority_low" msgid="7398724779026801851">"নিম্ন"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"লুকানো প্রেরক ঠিকানা"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"সংযুক্তি লোড করার সময় বার্তা পাঠানো যাচ্ছে না।"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"সংযুক্তি লোড করা যাবে না। আবার চেষ্টা করুন।"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"নেটওয়ার্ক প্রস্তুত নয়৷ আবার চেষ্টা করুন৷"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"পাঠ্য মুছে দিন"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"পাঠ্য এবং সংখ্যা লেখার মধ্যে স্যুইচ করুন"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"আরো অংশগ্রহণকারী যোগ করুন"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"অংশগ্রহণকারীদের নিশ্চিত করুন"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"নতুন কথোপকথন শুরু করুন"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"এই আইটেমটি নির্বাচন করুন"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ভিডিও দেখুন"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ব্যক্তি ও বিকল্পগুলি"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ডিবাগ"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ব্যক্তি ও বিকল্পগুলি"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"সাধারণ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"এই কথোপকথনে থাকা ব্যক্তিগণ"</string>
+    <string name="action_call" msgid="6596167921517350362">"একটি কল করুন"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"বার্তা পাঠান"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; থেকে &lt;br/&gt;&lt;small&gt;from বার্তা পাঠান"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ফটোগুলি পাঠান</item>
+      <item quantity="other">ফটোগুলি পাঠান</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">অডিওগুলি পাঠান</item>
+      <item quantity="other">অডিওগুলি পাঠান</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">ভিডিওগুলি পাঠান</item>
+      <item quantity="other">ভিডিওগুলি পাঠান</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">পরিচিতি কার্ডগুলি পাঠান</item>
+      <item quantity="other">পরিচিতি কার্ডগুলি পাঠান</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">সংযুক্তিগুলি পাঠান</item>
+      <item quantity="other">সংযুক্তিগুলি পাঠান</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">পাঠানোর জন্য <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>টি সংযুক্তি প্রস্তুত</item>
+      <item quantity="other">পাঠানোর জন্য <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>টি সংযুক্তি প্রস্তুত</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"প্রতিক্রিয়া পাঠান"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play স্টোরে দেখুন"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"সংস্করণ তথ্য"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"সংস্করণ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"মুক্ত উৎস লাইসেন্সগুলি"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"সংযুক্তির সীমা অতিক্রান্ত হয়েছে"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"সংযুক্তি লোড করতে ব্যর্থ হয়েছে।"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"পরিচিতিতে জুড়ুন"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"পরিচিতি জুড়ুন"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"বিষয়"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"বিষয়: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"পরিচিতি কার্ড লোড হচ্ছে"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"পরিচিতি কার্ড লোড করা যায়নি"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"পরিচিতি কার্ড দেখুন"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>টি পরিচিতি</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>টি পরিচিতি</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"যোগাযোগ কার্ড"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"জন্মদিন"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"টীকাগুলি"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"বার্তা ফরোয়ার্ড করুন"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"উত্তর"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+১"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS অক্ষম করা হয়েছে"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"পাঠাতে, ডিফল্ট SMS অ্যাপ্লিকেশান হিসাবে বার্তাপ্রেরণ সেট করুন"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"ডিফল্ট SMS অ্যাপ্লিকেশান হিসাবে বার্তাপ্রেরণ সেট করুন"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"পরিবর্তন"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"বার্তাগুলি গ্রহণ করতে, আপনার ডিফল্ট SMS অ্যাপ্লিকেশান হিসাবে বার্তাপ্রেরণ সেট করুন"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS বার্তাগুলি পাঠানোর জন্য কোন পছন্দের SIM নির্বাচিত নেই৷"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"এই অ্যাপ্লিকেশানটি ডিভাইস মালিক দ্বারা অনুমোদিত নয়।"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ঠিক আছে"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"একটি কথোপকথনে খুব বেশি সংখ্যার অংশগ্রহণকারী"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">অবৈধ পরিচিতিগুলি</item>
+      <item quantity="other">অবৈধ পরিচিতিগুলি</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ক্যামেরা চিত্র লোড করা যায়নি"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"আপনি: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"খসড়া"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"আপনি নতুন কোনো কথোপকথন শুরু করলে, সেটিকে এই তালিকায় দেখতে পাবেন"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"সংরক্ষিত করা কথোপকথন এখানে প্রদর্শিত হয়"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"কথোপকথনগুলি লোড হচ্ছে…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ছবি"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"অডিও ক্লিপ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ভিডিও"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"পরিচিতি কার্ড"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"পূর্বাবস্থায় ফিরুন"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"পুনরায় চেষ্টা করুন"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"একটি নতুন বার্তা পাঠাতে একটি পরিচিতি নাম অথবা ফোন নম্বর লিখুন"</string>
+    <string name="action_block" msgid="9032076625645190136">"অবরুদ্ধ করুন"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>-কে অবরুদ্ধ করুন"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g>-কে অবরোধ মুক্ত করুন"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>-কে অবরুদ্ধ করবেন?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"আপনি এই নম্বর থেকে অবিরত বার্তা গ্রহণ করতে করবেন কিন্তু আপনাকে আর সূচিত করা হবে না। এই কথোপকথন সংরক্ষণ করা হবে।"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"অবরুদ্ধ পরিচিতিগুলি"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"অবরোধ মুক্ত করুন"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"অবরুদ্ধ পরিচিতিগুলি"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"দস্তাবেজ লাইব্রেরি থেকে চিত্র নির্বাচন করুন"</string>
+    <string name="sending_message" msgid="6363584950085384929">"বার্তা পাঠানো হচ্ছে"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"বার্তা পাঠানো হয়েছে"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"সেলুলার ডেটা বন্ধ আছে। আপনার সেটিংস চেক করুন।"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"বিমান মোডে বার্তা পাঠানো যাবে না"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"এই বার্তাটি পাঠানো যায়নি"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"বার্তা ডাউনলোড করা হয়েছে"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"সেলুলার ডেটা বন্ধ আছে। আপনার সেটিংস চেক করুন।"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"বিমান মোডে বার্তাগুলি ডাউনলোড করা যাবে না"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"বার্তা ডাউনলোড করা যায়নি"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"শূন্য"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"এক"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"দুই"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"তিন"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"চার"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"পাঁচ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ছয়"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"সাত"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"আট"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"নয়"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> এর মাধ্যমে বার্তা পাঠানো যাবে না, ত্র্রুটি <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"অজানা পরিষেবা প্রদানকারীর মাধ্যমে বার্তা পাঠানো যাবে না, ত্রুটি <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ফরওয়ার্ড: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"বার্তা পাঠানো হয়নি: নেটওয়ার্কে পরিষেবা সক্রিয় নেই"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"বার্তা পাঠানো যায়নি: অবৈধ গন্তব্য ঠিকানা"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"বার্তা পাঠানো যায়নি: অবৈধ বার্তা"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"বার্তা পাঠানো যায়নি: অসমর্থিত বিষয়বস্তু"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"বার্তা পাঠানো যায়নি: অসমর্থিত বার্তা"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"বার্তা পাঠানো হয়নি: খুব বড়"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"নতুন বার্তা"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"দেখুন"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"চিত্র"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"কোনো উপযুক্ত অ্যাপ্লিকেশান পাওয়া যায়নি"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"প্রাপককে সরান"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"নতুন বার্তা"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"বাতিল করুন"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"অ্যাক্সেস পয়েন্ট সম্পাদনা করুন"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"সেট করা নেই"</string>
+    <string name="apn_name" msgid="1572691851070894985">"নাম"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS প্রক্সি"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS পোর্ট"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN প্রকার"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN মুছে দিন"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"নতুন APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"সংরক্ষণ করুন"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"খারিজ করুন"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"নামের ক্ষেত্রটি খালি থাকতে পারে না।"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN খালি থাকতে পারে না।"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ক্ষেত্রটিকে ৩ ডিজিটের হতে হবে।"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ক্ষেত্রটিকে ২ অথবা ৩ ডিজিটের হতে হবে।"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ডিফল্ট APN সেটিংস পুনরুদ্ধার করা হচ্ছে।"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"পুনরায় ডিফল্ট হিসাবে সেট করুন"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"ডিফল্ট APN সেটিংস পুনরায় সেট করা সম্পন্ন হয়েছে।"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"শীর্ষকহীন"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"অ্যাক্সেস পয়েন্টের নামগুলি"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNগুলি"</string>
+    <string name="menu_new" msgid="8286285392706532511">"নতুন APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"এই ব্যবহারকারীর জন্য অ্যাক্সেস পয়েন্ট নাম সেটিংস উপলব্ধ নয়"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ক্লিপবোর্ডে অনুলিপি করবেন?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"অনুলিপি করুন"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> এ"</string>
+    <string name="general_settings" msgid="5409336577057897710">"সাধারণ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"আরো বিকল্প"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"সাধারণ সেটিংস"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"উন্নত সেটিংস"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"সকল প্রাপকের কাছে আলাদা আলাদা করে SMS পাঠান৷ শুধুমাত্র আপনিই উত্তরগুলি পাবেন"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"সকল প্রাপকের কাছে একটি নির্দিষ্ট MMS পাঠান"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"অজানা নম্বর"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"নতুন বার্তা"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"নতুন বার্তা৷"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM নির্বাচক"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> নির্বাচিত, SIM নির্বাচক"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"বিষয় সম্পাদনা করুন"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM নির্বাচন করুন বা বিষয় সম্পাদনা করুন"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"অডিও রেকর্ড করতে স্পর্শ করুন এবং ধরে রাখুন"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"নতুন কথোপকথন শুরু করুন"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"বার্তাপ্রেরণ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"বার্তাপ্রেরণ তালিকা"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"বার্তাপ্রেরণ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"নতুন বার্তা"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"কথোপকথনের তালিকা"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"কথোপকথনগুলি লোড হচ্ছে"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"বার্তাগুলি লোড করা হচ্ছে"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"আরো কথোপকথন দেখুন"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"আরো বার্তা দেখুন"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"কথোপকথন মুছে দেওয়া হয়েছে"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"কথোপকথন মুছে ফেলা হয়েছে৷ একটি ভিন্ন বার্তাপ্রেরণ কথোপকথন দেখানোর জন্য স্পর্শ করুন"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"অবরুদ্ধ"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"অবরোধ মুক্ত করা হয়েছে"</string>
+    <string name="db_full" msgid="8459265782521418031">"সঞ্চয়স্থান কম রয়েছে৷ কিছু ডেটা হারিয়ে যেতে পারে৷"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"সংযুক্তিগুলি নির্বাচন করুন"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"নির্বাচন নিশ্চিত করুন"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g>টি নির্বাচন করা হয়েছে"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"একটি অথবা আরও বেশি সংযুক্তি সরিয়ে আবার চেষ্টা করুন।"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"আপনি আপনার বার্তা পাঠানোর চেষ্টা করতে পারেন, কিন্তু আপনি এক বা একাধিক সংযুক্তি অপসারণ না করা পর্যন্ত তা বিতরণ নাও করা হতে পারে।"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"আপনি বার্তা প্রতি শুধুমাত্র একটি ভিডিও পাঠাতে পারেন৷ অতিরিক্ত ভিডিওগুলি সরিয়ে দিয়ে আবার চেষ্টা করুন৷"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"বার্তাপ্রেরণ সংযুক্তি লোড করতে ব্যর্থ হয়েছে৷"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"তবুও পাঠান"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"কথোপকথন শুরু করা যায়নি"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> নির্বাচিত হয়েছে"</string>
+</resources>
diff --git a/res/values-ca/arrays.xml b/res/values-ca/arrays.xml
new file mode 100644
index 0000000..69ce724
--- /dev/null
+++ b/res/values-ca/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sense assumpte"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sí"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"D\'acord"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Gràcies"</item>
+    <item msgid="4881335087096496747">"Accepto"</item>
+    <item msgid="2422296858597420738">"Molt bé"</item>
+    <item msgid="4805581752819452687">"Ja vinc."</item>
+    <item msgid="4746700499431366214">"D\'acord. Et diré alguna cosa més tard."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
new file mode 100644
index 0000000..9f09908
--- /dev/null
+++ b/res/values-ca/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Missatges"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Missatges"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Selecció de la conversa"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Configuració"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Envia el missatge"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Afegeix un fitxer adjunt"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ajuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Et donem la benvinguda"</string>
+    <string name="skip" msgid="7238879696319945853">"Omet"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Següent &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Següent"</string>
+    <string name="exit" msgid="1905187380359981199">"Surt"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Configuració &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Configuració"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Missatges necessita permís per accedir als SMS, al telèfon i als contactes."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Pots canviar els permisos a Configuració &gt; Aplicacions &gt; Missatges &gt; Permisos."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Pots canviar els permisos a Configuració, Aplicacions, Missatges, Permisos."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Freqüents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tots els contactes"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Envia al <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Captura fotos o vídeos"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Tria imatges d\'aquest dispositiu."</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Enregistra l\'àudio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Triar una foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"S\'ha seleccionat el fitxer multimèdia."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"No hi ha cap fitxer multimèdia seleccionat."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Seleccionats: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imatge: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imatge"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Enregistra l\'àudio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Comparteix"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Ara mateix"</string>
+    <string name="posted_now" msgid="867560789350406701">"Ara"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hores</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dies</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> setmanes</item>
+      <item quantity="one">una setmana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mesos</item>
+      <item quantity="one">un mes</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> anys</item>
+      <item quantity="one">un any</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Missatge de classe 0"</string>
+    <string name="save" msgid="5081141452059463572">"Desa"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Queda poc espai al dispositiu. Per alliberar-ne, Missatgeria suprimirà automàticament els missatges antics."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"L\'espai d\'emmagatzematge s\'està esgotant"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Pot ser que Missatges no enviï ni rebi missatges fins que no tinguis més espai disponible al dispositiu."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Poc emmagatzematge per a SMS. És possible que et calgui suprimir missatges."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirma el teu número de telèfon"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Aquest pas únic garanteix que els missatges de grup s\'enviïn correctament amb Missatges."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de telèfon"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Suprimeix tots els missatges amb fitxers multimèdia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Suprimeix els missatges de més de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Suprimeix automàticament els missatges de més de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignora"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Confirmes que vols suprimir tots els missatges amb fitxers multimèdia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Confirmes que vols suprimir els missatges de més de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Confirmes que vols suprimir els missatges de més de <xliff:g id="DURATION">%s</xliff:g> i activar la funció per suprimir-los automàticament?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ha dit:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Has dit:"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Missatge de: <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Has enviat un missatge."</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"S\'està enviant…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"No s\'ha enviat. Toca per tornar-ho a provar."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"No s\'ha enviat. S\'està tornant a provar…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Reenvia o suprimeix"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Truca als serveis d\'emergència. En aquest moment, el missatge de text no s\'ha pogut enviar."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"S\'ha produït un error."</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Missatge MMS nou per baixar"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Missatge MMS nou"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"No s\'ha pogut baixar."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Toca per tornar-ho a provar"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Toca per baixar"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Baixa o suprimeix"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"S\'està baixant..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"El missatge ha caducat o no està disponible."</string>
+    <string name="mms_info" msgid="3402311750134118165">"mida: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, caducitat: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"No es pot enviar. El destinatari no és vàlid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"El servei no està activat a la xarxa."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"No s\'ha pogut enviar a causa d\'un problema de xarxa."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"El missatge ha caducat o no està disponible."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sense assumpte)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Emissor desconegut"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregat"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"No s\'ha pogut baixar el missatge <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"No s\'ha pogut completar l\'operació de la base de dades perquè hi ha poca memòria."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"No s\'ha enviat el missatge."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Alguns missatges no s\'han enviat a Missatges"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> missatges en <xliff:g id="CONVERSATIONS">%d</xliff:g> converses</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> missatges en una conversa</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"No s\'ha baixat el missatge"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Alguns missatges a Missatges no s\'han baixat"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> missatges en <xliff:g id="CONVERSATIONS">%d</xliff:g> converses</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> missatges en una conversa</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"No s\'ha enviat el missatge al <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Truca als serveis d\'emergència. En aquest moment, el missatge de text al <xliff:g id="NUMBER">%1$s</xliff:g> no s\'ha pogut enviar."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> missatges nous</item>
+      <item quantity="one">Missatge nou</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Inicia"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"La càmera no està disponible."</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"La càmera no està disponible."</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"La captura de vídeo no està disponible."</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"No es pot desar el fitxer multimèdia."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"No es pot fer una foto."</string>
+    <string name="back" msgid="1477626055115561645">"Enrere"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arxivades"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Suprimeix"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arxiu"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Treu de l\'arxiu"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desactiva les notificacions"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activa les notificacions"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Afegeix un contacte"</string>
+    <string name="action_download" msgid="7786338136368564146">"Baixa"</string>
+    <string name="action_send" msgid="377635240181672039">"Envia"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Suprimeix"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vols suprimir aquest missatge?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Aquesta acció no es pot desfer."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Suprimeix"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Vols suprimir aquestes converses?</item>
+      <item quantity="one">Vols suprimir aquesta conversa?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Suprimeix"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancel·la"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Per a"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Selecciona diverses imatges"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirma la selecció"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"No es pot enregistrar l\'àudio. Torna-ho a provar."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"No es pot reproduir l\'àudio. Torna-ho a provar."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"No s\'ha pogut desar l\'àudio. Torna-ho a provar."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Toca i mantén premut"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imatge"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip d\'àudio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vídeo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Targeta de contacte"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Baixa"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Respon amb un SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Respon amb un MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Respon"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participant</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Jo"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contactes bloquejats i arxivats"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contacte desbloquejat i no arxivat"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Arxivades: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"No arxivades: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificacions desactivades"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificacions activades"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Ja està tot llest. Torna a tocar Envia."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Missatges s\'ha definit correctament com a aplicació predeterminada de SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Descarta els fitxers adjunts</item>
+      <item quantity="one">Descarta el fitxer adjunt</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Àudio adjunt"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reprodueix l\'àudio adjunt"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Atura"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Missatge de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Missatge no enviat de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Missatge de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Missatge no enviat a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"S\'està enviant un missatge a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Missatge no enviat a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Missatge a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Missatge no enviat de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Missatge de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Missatge no enviat a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"S\'està enviant un missatge a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Missatge no enviat a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Missatge a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Hi ha hagut un problema amb aquest missatge. Toca per tornar-ho a provar."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversa amb <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Suprimeix l\'assumpte"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Captura un vídeo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Captura una imatge fixa"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Fes una foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Comença a enregistrar vídeo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Canvia a la càmera de pantalla completa"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Canvia entre la càmera frontal i la posterior"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Deixa d\'enregistrar i adjunta un vídeo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Atura l\'enregistrament de vídeo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos de missatges"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">S\'han desat <xliff:g id="QUANTITY_2">%d</xliff:g> fotos a l\'àlbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one">S\'ha desat <xliff:g id="QUANTITY_0">%d</xliff:g> foto a l\'àlbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">S\'han desat <xliff:g id="QUANTITY_2">%d</xliff:g> vídeos a l\'àlbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one">S\'ha desat <xliff:g id="QUANTITY_0">%d</xliff:g> vídeo a l\'àlbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">S\'han desat <xliff:g id="QUANTITY_2">%d</xliff:g> fitxers adjunts a l\'àlbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one">S\'ha desat <xliff:g id="QUANTITY_0">%d</xliff:g> fitxer adjunt a l\'àlbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">S\'han desat <xliff:g id="QUANTITY_1">%d</xliff:g> fitxers adjunts a Baixades</item>
+      <item quantity="one">S\'ha desat <xliff:g id="QUANTITY_0">%d</xliff:g> fitxer adjunt a Baixades</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">S\'han desat <xliff:g id="QUANTITY_1">%d</xliff:g> fitxers adjunts</item>
+      <item quantity="one">S\'ha desat <xliff:g id="QUANTITY_0">%d</xliff:g> fitxer adjunt</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">No s\'han pogut desar <xliff:g id="QUANTITY_1">%d</xliff:g> fitxers adjunts</item>
+      <item quantity="one">No s\'ha pogut desar <xliff:g id="QUANTITY_0">%d</xliff:g> fitxer adjunt</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"S\'ha desat el fitxer adjunt MMS."</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Configuració"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arxivades"</string>
+    <string name="action_close" msgid="1840519376200478419">"Tanca"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avançada"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depuració"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificacions"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"So"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silenci"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibració"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"S\'ha bloquejat"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Informes d\'entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Sol·licita un informe d\'entrega per a cada SMS enviat"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperació automàtica"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recupera MMS automàticament"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recupera aut. els MMS en itinerància"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recupera MMS automàticament en itinerància"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Missatge de grup"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utilitza MMS per enviar un únic missatge a diversos destinataris"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicació de SMS predeterminada"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicació de SMS predeterminada"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Número de telèfon"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Desconegut"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons per a missatges de sortida"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Envia el contingut dels SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Envia les dades sense processar dels SMS rebuts al fitxer d\'emmagatzematge extern."</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Envia el contingut dels MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Buida les dades sense processar dels MMS rebuts en un fitxer d’emmagatzematge extern"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertes sense fil"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opcions del missatge"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copia el text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Mostra els detalls"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Suprimeix"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Reenvia"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalls del missatge"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipus: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Missatge de text"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Missatge multimèdia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Per a: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviat: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Rebut: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Assumpte: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Mida: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritat: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baixa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Amaga l\'adreça del remitent"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"No es pot enviar el missatge durant la càrrega dels fitxers adjunts."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"No s\'ha pogut carregar el fitxer adjunt. Torna-ho a provar."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"La xarxa no està a punt. Torna-ho a provar."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Suprimeix el text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alterna entre escriure lletres i números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Afegeix més participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirma els participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Inicia una conversa nova"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selecciona aquest element."</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reprodueix el vídeo."</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Persones i opcions"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depura"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Persones i opcions"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"General"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Persones en aquesta conversa"</string>
+    <string name="action_call" msgid="6596167921517350362">"Fes una trucada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Envia el missatge"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Envia un missatge&lt;br/&gt;&lt;small&gt;des de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;."</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Envia les fotos</item>
+      <item quantity="one">Envia la foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Envia els àudios</item>
+      <item quantity="one">Envia l\'àudio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Envia els vídeos</item>
+      <item quantity="one">Envia el vídeo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Envia les targetes de contacte</item>
+      <item quantity="one">Envia la targeta de contacte</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Envia els fitxers adjunts</item>
+      <item quantity="one">Envia el fitxer adjunt</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">Ja es poden enviar <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> fitxers adjunts</item>
+      <item quantity="one">Ja es pot enviar un fitxer adjunt</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Envia suggeriments"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Mostra a Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informació de la versió"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versió %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Llicències de codi obert"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificacions"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"S\'ha assolit el límit de fitxers adjunts"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"No s\'ha pogut carregar el fitxer adjunt."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Vols afegir-lo als contactes?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Afegeix el contacte"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Assumpte"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Assumpte: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"S\'està carregant la targeta de contacte"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"No s\'ha pogut carregar la targeta de contacte"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Mostra la targeta de contactes"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contactes</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contacte</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Targetes de contacte"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Natalici"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notes"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Reenvia el missatge"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Respon"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS desactivats"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Per enviar missatges, defineix Missatges com a aplicació predeterminada de SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Defineix Missatges com a aplicació predeterminada de SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Canvia"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Per rebre missatges, defineix Missatges com a aplicació predeterminada de SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No s\'ha seleccionat cap SIM preferida per enviar missatges SMS."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"El propietari del dispositiu no admet l\'aplicació."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"D\'acord"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Hi ha massa participants a la conversa."</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Els contactes no són vàlids</item>
+      <item quantity="one">El contacte no és vàlid</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"No s\'ha pogut carregar la imatge de la càmera."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Tu: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Esborrany"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Quan comencis una conversa nova, es mostrarà aquí."</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Les converses arxivades es mostren aquí."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"S\'estan carregant les converses..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imatge"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip d\'àudio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vídeo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Targeta de contacte"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Desfés"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Torna-ho a provar"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Introdueix el nom d\'un contacte o el número de telèfon per escriure un missatge nou."</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloqueja"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloqueja <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloqueja <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vols bloquejar <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Continuaràs rebent missatges d\'aquest número, però no se t\'enviarà cap notificació. Aquesta conversa s\'arxivarà."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contactes bloquejats"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEJA"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contactes bloquejats"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Tria una imatge de la biblioteca de documents."</string>
+    <string name="sending_message" msgid="6363584950085384929">"S\'està enviant el missatge"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Missatge enviat"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Les dades del telèfon estan desactivades. Comprova\'n la configuració."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"No es poden enviar missatges amb el mode d\'avió activat."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"No s\'ha pogut enviar el missatge"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Missatge baixat"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Les dades del telèfon estan desactivades. Comprova\'n la configuració."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"No es poden baixar missatges en mode d\'avió"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"El missatge no s\'ha pogut baixar"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Un"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dos"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tres"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quatre"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinc"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Set"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Vuit"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nou"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"No es pot enviar el missatge amb <xliff:g id="CARRIERNAME">%1$s</xliff:g>, error <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"No es pot enviar el missatge amb un operador de telefonia mòbil desconegut, error <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Rv: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"No s\'ha enviat el missatge; el servei no s\'ha activat a la xarxa."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Missatge no enviat: adreça de destinació no vàlida"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Missatge no enviat: missatge no vàlid"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Missatge no enviat: contingut no admès"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Missatge no enviat: missatge no admès"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"El missatge no s\'ha enviat: és massa gran"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Missatge nou"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Mostra"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imatge"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"No s\'ha pogut trobar una aplicació adequada."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Suprimeix el destinatari."</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Missatge nou"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancel·la"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edita el punt d\'accés"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"No definit"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nom"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Servidor intermediari MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port per a MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipus d\'APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Suprimeix l\'APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN nou"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Desa"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Descarta"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"El camp Nom no pot quedar buit."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"L\'APN no pot quedar buit."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"El camp MCC ha de tenir 3 dígits."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"El camp MNC ha de tenir 2 o 3 dígits."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"S\'està restaurant la configuració predeterminada d\'APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Restableix al valor predeterminat"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"S\'ha restablert la configuració predeterminada d\'APN."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sense títol"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Noms de punt d\'accés"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN nou"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"La configuració del nom del punt d\'accés no està disponible per a aquest usuari."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Ho vols copiar al porta-retalls?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copia"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"per a <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avançada"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Configuració general"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Configuració avançada"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Envia missatges SMS individuals a tots els destinataris. Només tu rebràs les respostes."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Envia un MMS individual a tots els destinataris"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número desconegut"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Missatge nou"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Missatge nou"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selector de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> seleccionada, selector de SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edita l\'assumpte"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Selecciona la SIM o edita l\'assumpte"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Mantén premut per enregistrar àudio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Inicia una conversa nova"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Missatges"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Llista de missatges"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Missatges"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Missatge nou"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Llista de converses"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"S\'estan carregant les converses"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"S\'estan carregant els missatges"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Mostra més converses"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Mostra més missatges"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"S\'ha suprimit la conversa."</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"S\'ha suprimit la conversa. Toca per mostrar una altra conversa de Missatges"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloquejat"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desbloquejat"</string>
+    <string name="db_full" msgid="8459265782521418031">"Hi ha poc espai d\'emmagatzematge. És possible que es perdin algunes dades."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Selecciona els fitxers adjunts"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirma la selecció"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Seleccionats: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Suprimeix un o més fitxers adjunts i torna-ho a provar."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Pots provar d\'enviar el missatge, però és possible que no s\'enviï si no suprimeixes un o més fitxers adjunts."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Només pots enviar un vídeo per missatge. Suprimeix els vídeos addicionals i torna-ho a provar."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Missatges no ha pogut carregar el fitxer adjunt."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Envia igualment"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"No s\'ha pogut iniciar la conversa"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> seleccionada"</string>
+</resources>
diff --git a/res/values-cs/arrays.xml b/res/values-cs/arrays.xml
new file mode 100644
index 0000000..95c2775
--- /dev/null
+++ b/res/values-cs/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"bez předmětu"</item>
+    <item msgid="272485471009191934">"bezpředmětu"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ano"</item>
+    <item msgid="6049132459802288033">"Ne"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Cha cha"</item>
+    <item msgid="2611328818571146775">"Díky"</item>
+    <item msgid="4881335087096496747">"Souhlasím"</item>
+    <item msgid="2422296858597420738">"Hezké"</item>
+    <item msgid="4805581752819452687">"Jsem na cestě."</item>
+    <item msgid="4746700499431366214">"OK, ozvu se později."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
new file mode 100644
index 0000000..7e58112
--- /dev/null
+++ b/res/values-cs/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS a MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS a MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Vybrat konverzaci"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Nastavení"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Odeslat zprávu"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Přidat přílohu"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Nápověda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Vítejte"</string>
+    <string name="skip" msgid="7238879696319945853">"Přeskočit"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Další &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Další"</string>
+    <string name="exit" msgid="1905187380359981199">"Ukončit"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Nastavení &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Nastavení"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Aplikace SMS a MMS vyžaduje oprávnění k přístupu k SMS, telefonu a kontaktům."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Oprávnění můžete změnit v Nastavení &gt; Aplikace &gt; SMS a MMS &gt; Oprávnění."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Oprávnění můžete změnit v Nastavení, Aplikace, SMS a MMS, Oprávnění."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Časté kontakty"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Všechny kontakty"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Odeslat na číslo <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Pořídit fotky nebo video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Vyberte obrázky z tohoto zařízení."</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Nahrát zvuk"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Vybrat fotku"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Médium je vybráno."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Výběr média je zrušen."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Vybráno: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"obrázek <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"obrázek"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Nahrávání zvuku"</string>
+    <string name="action_share" msgid="2143483844803153871">"Sdílet"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Právě teď"</string>
+    <string name="posted_now" msgid="867560789350406701">"Teď"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> hodiny</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hodiny</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hodin</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hodina</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dny</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> dne</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dnů</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> den</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> týdny</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> týdne</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> týdnů</item>
+      <item quantity="one">jeden týden</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> měsíce</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> měsíce</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> měsíců</item>
+      <item quantity="one">jeden měsíc</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> roky</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> roku</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> let</item>
+      <item quantity="one">jeden rok</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Zpráva třídy 0"</string>
+    <string name="save" msgid="5081141452059463572">"Uložit"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"V zařízení dochází místo. Aplikace SMS a MMS automaticky smaže starší zprávy, aby uvolnila místo."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"V úložišti je málo místa"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Aplikace SMS a MMS nebude moci posílat ani přijímat zprávy, dokud v zařízení nebude k dispozici více místa."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Dochází volné místo na zprávy SMS. Možná bude potřeba nějaké zprávy vymazat."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Ověřit telefonní číslo"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Tento jednorázový krok zajistí, že aplikace SMS a MMS správně doručí vaše skupinové zprávy."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonní číslo"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Smazat všechny zprávy s médii"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Smazat zprávy starší než <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automaticky smazat zprávy starší než <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorovat"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Vymazat všechny zprávy s médii?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Smazat zprávy starší než <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Chcete smazat zprávy starší než <xliff:g id="DURATION">%s</xliff:g> a zapnout automatické mazání?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> říká"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Řekli jste"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Zpráva od uživatele <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Odeslali jste zprávu"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Odesílání…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Zpráva nebyla odeslána. Klepnutím to zkusíte znovu."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Zpráva nebyla odeslána. Probíhá další pokus…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Znovu odeslat nebo smazat"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Uskutečněte prosím hlasové volání nouzových služeb. Vaši textovou zprávu v současné době nebylo možné doručit."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Nezdařilo se"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nová zpráva MMS ke stažení"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nová zpráva MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Stažení se nezdařilo."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Klepnutím to zkusíte znovu"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Stáhněte klepnutím."</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Stáhnout nebo smazat"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Stahování…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Platnost zprávy vypršela nebo zpráva není k dispozici."</string>
+    <string name="mms_info" msgid="3402311750134118165">"velikost: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, vypršení platnosti: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Zprávu nelze odeslat. Příjemce není platný."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Služba není v síti aktivována."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Zprávu se nepodařilo odeslat z důvodu chyby v síti."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Platnost zprávy vypršela nebo zpráva není k dispozici."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Bez předmětu)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Neznámý odesílatel"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Doručeno"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Stažení zprávy <xliff:g id="SUBJECT">%1$s</xliff:g> od odesílatele <xliff:g id="FROM">%2$s</xliff:g> se nezdařilo."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Databázovou operaci se nepodařilo dokončit z důvodu nedostatku paměti."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Zprávu se nepodařilo odeslat."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Několik zpráv v aplikaci SMS a MMS nebylo odesláno."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="few">Počet zpráv ve <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzacích: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="many">Počet zpráv v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzace: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="other">Počet zpráv v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzacích: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="one">Počet zpráv v jedné konverzaci: <xliff:g id="MESSAGES_0">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Zprávu se nepodařilo stáhnout"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Několik zpráv se do aplikace SMS a MMS nepodařilo stáhnout."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="few">Počet zpráv ve <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzacích: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="many">Počet zpráv v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzace: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="other">Počet zpráv v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzacích: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="one">Počet zpráv v jedné konverzaci: <xliff:g id="MESSAGES_0">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Zpráva na číslo <xliff:g id="NUMBER">%1$s</xliff:g> nebyla odeslána."</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Uskutečněte prosím hlasové volání nouzových služeb. Vaši textovou zprávu na číslo <xliff:g id="NUMBER">%1$s</xliff:g> v současné době nebylo možné doručit."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nové zprávy</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> nové zprávy</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nových zpráv</item>
+      <item quantity="one">Nová zpráva</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Spustit"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotoaparát není k dispozici"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotoaparát není k dispozici."</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Záznam videa není k dispozici."</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Média nelze uložit."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nelze pořídit fotku"</string>
+    <string name="back" msgid="1477626055115561645">"Zpět"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivováno"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Smazat"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivovat"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Vyjmout z archivu"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Vypnout oznámení"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Zapnout oznámení"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Přidat kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Stáhnout"</string>
+    <string name="action_send" msgid="377635240181672039">"Odeslat"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Smazat"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Smazat tuto zprávu?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tuto akci nelze vrátit zpět."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Smazat"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="few">Smazat tyto konverzace?</item>
+      <item quantity="many">Smazat tyto konverzace?</item>
+      <item quantity="other">Smazat tyto konverzace?</item>
+      <item quantity="one">Smazat tuto konverzaci?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Smazat"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Zrušit"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Komu"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Vybrat několik obrázků"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Potvrďte výběr"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Zvuk nelze zaznamenat. Zkuste to znovu."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Zvuk nelze přehrát. Zkuste to znovu."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Zvuk nelze uložit. Zkuste to znovu."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Dotyk s podržením"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Fotografie"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Zvukový klip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Karta kontaktu"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Stáhnout"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Odpovědět – SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Odpovědět v MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Odpovědět"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> účastníci</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> účastníka</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> účastníků</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> účastník</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Já"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt byl zablokován a archivován."</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt byl odblokován a jeho archivace byla zrušena"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Archivováno: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Vyjmuto z archivu: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Oznámení jsou vypnuta"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Oznámení jsou zapnuta"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Vše je připraveno. Znovu klepněte na Odeslat."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Aplikace SMS a MMS byla úspěšně nastavena jako výchozí aplikace pro SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="few">Zahodit přílohy</item>
+      <item quantity="many">Zahodit přílohy</item>
+      <item quantity="other">Zahodit přílohy</item>
+      <item quantity="one">Zahodit přílohu</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Zvuková příloha"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Přehrát zvukovou přílohu"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pozastavit"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Zpráva od uživatele <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Neúspěšná zpráva od uživatele <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Zpráva od uživatele <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Neodeslaná zpráva pro uživatele <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Odesílání zprávy uživateli <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Neúspěšná zpráva pro uživatele <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Zpráva pro uživatele <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Neúspěšná zpráva od uživatele <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Zpráva od uživatele <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Neodeslaná zpráva pro uživatele <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Odesílání zprávy uživateli <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Neúspěšná zpráva pro uživatele <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Zpráva pro uživatele <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Neúspěšná zpráva. Klepnutím pokus opakujte."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Konverzace s uživateli <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Smazat předmět"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Natočit video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Pořídit statický snímek"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Vyfotit"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Začít natáčet video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Přepnout na fotoaparát na celou obrazovku"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Přepnout mezi předním a zadním fotoaparátem"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Zastavit nahrávání a připojit video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Zastavit záznam videa"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotky z aplikace SMS a MMS"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> fotky byly uloženy do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> fotky bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotek bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotka byla uložena do alba <xliff:g id="ALBUMNAME_1">%s</xliff:g>.</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> videa byla uložena do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> videa bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videí bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video bylo uloženo do alba <xliff:g id="ALBUMNAME_1">%s</xliff:g>.</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> přílohy byly uloženy do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> přílohy bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> příloh bylo uloženo do alba <xliff:g id="ALBUMNAME_3">%s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> příloha byla uložena do alba <xliff:g id="ALBUMNAME_1">%s</xliff:g>.</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> přílohy byly uloženy do složky stažených položek.</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> přílohy bylo uloženo do složky stažených položek.</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> příloh bylo uloženo do složky stažených položek.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> příloha byla uložena do složky stažených položek.</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="few">Uloženy <xliff:g id="QUANTITY_1">%d</xliff:g> přílohy</item>
+      <item quantity="many">Uloženo <xliff:g id="QUANTITY_1">%d</xliff:g> přílohy</item>
+      <item quantity="other">Uloženo <xliff:g id="QUANTITY_1">%d</xliff:g> příloh</item>
+      <item quantity="one">Uložena <xliff:g id="QUANTITY_0">%d</xliff:g> příloha</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> přílohy se nepodařilo uložit</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> přílohy se nepodařilo uložit</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> příloh se nepodařilo uložit</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> přílohu se nepodařilo uložit</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Příloha MMS byla uložena"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Nastavení"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivováno"</string>
+    <string name="action_close" msgid="1840519376200478419">"Zavřít"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Rozšířená nastavení"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Ladit"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Oznámení"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Zvuk"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Tichý režim"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrace"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Zablokováno"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Zprávy o doručení SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"U každé odeslané SMS požadovat potvrzení o doručení"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatické načítání"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automaticky načítat zprávy MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Autom. načítání při roamingu"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Při roamingu automaticky načítat zprávy MMS"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Skupinové zprávy"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Použít MMS k odeslání jedné zprávy, pokud má několik příjemců"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Výchozí aplikace SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Výchozí aplikace SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Vaše telefonní číslo"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Neznámé"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Zvuky odchozích zpráv"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Vypsání zpráv SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Vypsat nezpracovaná data přijatých zpráv SMS do souboru externího úložiště"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Vypsání zpráv MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Vypsat nezpracovaná data přijatých zpráv MMS do souboru externího úložiště"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Bezdrátová upozornění"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Možnosti zprávy"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopírovat text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Zobrazit podrobnosti"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Smazat"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Přeposlat"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Podrobnosti zprávy"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Typ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Textová zpráva"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimediální zpráva"</string>
+    <string name="from_label" msgid="1947831848146564875">"Od: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Komu: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Odesláno: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Přijato: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Předmět: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Velikost: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorita: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM karta: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Vysoká"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normální"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Nízká"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM karta <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skrytá adresa odesílatele"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Při načítání příloh nelze odeslat zprávu."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Přílohu nelze načíst. Zkuste to znovu."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Síť není připravena. Zkuste to znovu."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Smazat text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Přepnutí mezi zadáváním textu a čísel"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Přidat další účastníky"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Potvrdit účastníky"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Zahájit novou konverzaci"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Vybrat tuto položku"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Přehrát video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Lidé a možnosti"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Ladit"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Lidé a možnosti"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Obecné"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Lidé v této konverzaci"</string>
+    <string name="action_call" msgid="6596167921517350362">"Uskutečnit hovor"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Poslat zprávu"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Odeslat zprávu&lt;br/&gt;&lt;small&gt;ze SIM karty <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="few">Odeslat fotky</item>
+      <item quantity="many">Odeslat fotky</item>
+      <item quantity="other">Odeslat fotky</item>
+      <item quantity="one">Odeslat fotku</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="few">Odeslat zvukové nahrávky</item>
+      <item quantity="many">Odeslat zvukové nahrávky</item>
+      <item quantity="other">Odeslat zvukové nahrávky</item>
+      <item quantity="one">Odeslat zvukovou nahrávku</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="few">Odeslat videa</item>
+      <item quantity="many">Odeslat videa</item>
+      <item quantity="other">Odeslat videa</item>
+      <item quantity="one">Odeslat video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="few">Odeslat vizitky</item>
+      <item quantity="many">Odeslat vizitky</item>
+      <item quantity="other">Odeslat vizitky</item>
+      <item quantity="one">Odeslat vizitku</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="few">Odeslat přílohy</item>
+      <item quantity="many">Odeslat přílohy</item>
+      <item quantity="other">Odeslat přílohy</item>
+      <item quantity="one">Odeslat přílohu</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> přílohy jsou připraveny k odeslání</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> přílohy je připraveno k odeslání</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> příloh je připraveno k odeslání</item>
+      <item quantity="one">Jedna příloha je připravena k odeslání</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Odeslat zpětnou vazbu"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Zobrazit v Obchodě Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informace o verzi"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Verze %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licence open source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Oznámení"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Byl dosažen maximální počet příloh"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Načtení přílohy se nezdařilo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Přidat do kontaktů?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Přidat kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Předmět"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Předmět: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Načítání kontaktní karty"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kartu kontaktu nelze načíst."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Zobrazit kontaktní kartu"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> kontakty</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> kontaktu</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktů</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Karty kontaktů"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Narozeniny"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Poznámky"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Přeposlat zprávu"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Odpovědět"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Zprávy SMS jsou zakázány"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Chcete-li odeslat zprávu, nastavte aplikaci SMS a MMS jako výchozí aplikaci pro SMS."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Nastavte aplikaci SMS a MMS jako výchozí aplikaci pro SMS."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Změnit"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Chcete-li dostávat zprávy, nastavte aplikaci SMS a MMS jako výchozí aplikaci pro SMS."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Není vybrána preferovaná SIM karta pro odesílání zpráv SMS."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Tuto aplikaci vlastník zařízení nepovolil."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Konverzace obsahuje příliš mnoho účastníků"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="few">Neplatné kontakty</item>
+      <item quantity="many">Neplatné kontakty</item>
+      <item quantity="other">Neplatné kontakty</item>
+      <item quantity="one">Neplatný kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Obraz z fotoaparátu nelze načíst."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vy: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Koncept"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Zde budou uvedeny nové konverzace"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Zde se zobrazují archivované konverzace."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Načítání konverzací…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Fotografie"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Zvukový klip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Karta kontaktu"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Vrátit zpět"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Opakovat"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Chcete-li začít psát novou zprávu, zadejte jméno kontaktu nebo telefonní číslo."</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokovat"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokovat <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Odblokovat kontakt <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokovat <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Zprávy z tohoto čísla budete i nadále dostávat, ale nebude se pro ně již zobrazovat oznámení. Tato konverzace bude archivována."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokované kontakty"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ODBLOKOVAT"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokované kontakty"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Vyberte obrázek z knihovny dokumentů."</string>
+    <string name="sending_message" msgid="6363584950085384929">"Odesílání zprávy"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Zpráva byla odeslána"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobilní datové přenosy jsou vypnuty. Zkontrolujte svá nastavení."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"V režimu Letadlo zprávy nelze odeslat."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Zprávu nelze odeslat"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Zpráva byla stažena"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobilní datové přenosy jsou vypnuty. Zkontrolujte svá nastavení."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"V režimu Letadlo zprávy nelze stahovat"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Zprávu nelze stáhnout"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nula"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Jedna"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dvě"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tři"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Čtyři"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pět"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Šest"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sedm"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Osm"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Devět"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Zprávu prostřednictvím operátora <xliff:g id="CARRIERNAME">%1$s</xliff:g> nelze odeslat. Chyba <xliff:g id="ERRORCODE">%2$d</xliff:g>."</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Zprávu prostřednictvím neznámého operátora nelze odeslat. Chyba <xliff:g id="ERRORCODE">%1$d</xliff:g>."</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Zpráva nebyla odeslána: služba není v síti aktivována"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Zpráva nebyla odeslána: neplatná cílová adresa"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Zpráva nebyla odeslána: neplatná zpráva"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Zpráva nebyla odeslána: nepodporovaný obsah"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Zpráva nebyla odeslána: nepodporovaná zpráva"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Zpráva nebyla odeslána, protože je příliš velká"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nová zpráva"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Zobrazit"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Obrázek"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Vhodná aplikace nebyla nalezena."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Odebrat příjemce"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nová zpráva"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Zrušit"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Upravit přístupový bod"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nenastaveno"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Název"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Název přístupového bodu (APN)"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy server pro MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port pro MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Typ APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Smazat APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nový název přístupového bodu (APN)"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Uložit"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Zahodit"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Pole Název nesmí být prázdné."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Název přístupového bodu (APN) nesmí být prázdný."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Pole MCC musí obsahovat alespoň 3 číslice."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Pole MNC musí obsahovat 2 nebo 3 číslice."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Obnovování výchozích nastavení (APN)"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Obnovit výchozí"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Obnovení výchozích nastavení APN bylo dokončeno."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Bez názvu"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Názvy přístupových bodů"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Názvy přístupových bodů (APN)"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nový název přístupového bodu (APN)"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Nastavení názvu přístupového budu pro tohoto uživatele není dostupné."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopírovat do schránky?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopírovat"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"na SIM kartu <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Obecné"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Rozšířená nastavení"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Obecná nastavení"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Rozšířená nastavení"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM karta <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Odesílat všem příjemcům jednotlivé zprávy SMS. Odpovědi dostanete pouze vy."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Odeslat všem příjemcům jednu zprávu MMS"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Neznámé číslo"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nová zpráva"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nová zpráva"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Výběr SIM karty"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Výběr SIM karty (vybrána SIM karta <xliff:g id="SIM_0">%1$s</xliff:g>)"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Upravit předmět"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Vybrat SIM kartu nebo upravit předmět"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Zvuk zaznamenáte klepnutím a podržením"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Zahájit novou konverzaci"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS a MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Seznam SMS a MMS"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS a MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nová zpráva"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Seznam konverzací"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Načítání konverzací"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Načítání zpráv"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Zobrazit další konverzace"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Zobrazit další zprávy"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Konverzace byla smazána"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Konverzace byla smazána. Klepnutím zobrazíte jinou konverzaci v aplikaci SMS a MMS."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Zablokováno"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Odblokováno"</string>
+    <string name="db_full" msgid="8459265782521418031">"V úložišti je málo místa. Některá data mohou být ztracena."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Vybrat přílohy"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Potvrďte výběr"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Vybráno: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Odstraňte prosím alespoň jednu přílohu a zkuste to znovu."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Zprávu můžete zkusit odeslat, avšak může se stát, že nebude doručena, dokud neodstraníte alespoň jednu přílohu."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Ve zprávě lze odeslat pouze jedno video. Odstraňte ostatní videa a zkuste to znovu."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Načtení přílohy v aplikaci SMS a MMS se nezdařilo."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Přesto odeslat"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Konverzaci nelze zahájit"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Vybráno: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-da/arrays.xml b/res/values-da/arrays.xml
new file mode 100644
index 0000000..d40336a
--- /dev/null
+++ b/res/values-da/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"intet emne"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nej"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Haha"</item>
+    <item msgid="2611328818571146775">"Tak"</item>
+    <item msgid="4881335087096496747">"Jeg er enig"</item>
+    <item msgid="2422296858597420738">"Sådan!"</item>
+    <item msgid="4805581752819452687">"Er på vej"</item>
+    <item msgid="4746700499431366214">"Jeg vender tilbage til dig lidt senere"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
new file mode 100644
index 0000000..6d441da
--- /dev/null
+++ b/res/values-da/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Beskeder"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Beskeder"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Vælg en samtale"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Indstillinger"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Send besked"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Tilføj en vedhæftet fil"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hjælp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Velkommen"</string>
+    <string name="skip" msgid="7238879696319945853">"Spring over"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Næste &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Næste"</string>
+    <string name="exit" msgid="1905187380359981199">"Afslut"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Indstillinger &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Indstillinger"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Beskeder skal have tilladelse for at kunne anvende Sms, Telefon og Kontaktpersoner."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Du kan ændre tilladelser i Indstillinger &gt; Apps &gt; Beskeder &gt; Tilladelser."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Du kan ændre tilladelser under Indstillinger, Apps, Beskeder, Tilladelser."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Mest brugte"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alle kontaktpersoner"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Send til <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Optag billeder eller video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Vælg billeder fra denne enhed"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Optag lyd"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Vælg billede"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Medierne er valgt."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Medierne er fravalgt."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Der er valgt <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"billede <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"billede"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Optag lyd"</string>
+    <string name="action_share" msgid="2143483844803153871">"Del"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Lige nu"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nu"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> timer</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> timer</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dage</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dage</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> uger</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> uger</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> måneder</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> måneder</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> år</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> år</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Klasse 0-besked"</string>
+    <string name="save" msgid="5081141452059463572">"Gem"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Enheden er ved at løbe tør for plads. Ældre beskeder bliver automatisk slettet for at frigøre plads."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Der er snart ikke mere lagerplads"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Beskeder sender eller modtager muligvis ikke beskeder, før der er mere ledig plads på din enhed."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Begrænset lagerplads til sms. Det kan være nødvendigt at slette beskeder."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Bekræft dit telefonnummer"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Dette engangstrin sikrer, at Beskeder leverer dine gruppebeskeder på korrekt vis."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonnummer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Slet alle beskeder med medier"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Slet beskeder, der er mere end <xliff:g id="DURATION">%s</xliff:g> gamle"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Slet automatisk beskeder, der er mere end <xliff:g id="DURATION">%s</xliff:g> gamle"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorer"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Slet alle beskeder, der indeholder medier?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Vil du slette beskeder, der er mere end <xliff:g id="DURATION">%s</xliff:g> gamle?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Vil du slette beskeder, der er ældre end <xliff:g id="DURATION">%s</xliff:g>, og aktiverr automatisk sletning?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sagde"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Du sagde"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Besked fra <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Du sendte en besked"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sender…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ikke sendt. Tryk for at prøve igen."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ikke sendt. Prøver igen…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Send igen eller slet"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Ring op til alarmcentralen. Din sms-besked kan ikke leveres på nuværende tidspunkt."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Mislykkedes"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Ny MMS-besked til download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Ny MMS-besked"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Download mislykkedes"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tryk for at prøve igen"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Tryk for at downloade"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Download eller slet"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Downloader…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Beskeden er udløbet eller ikke tilgængelig"</string>
+    <string name="mms_info" msgid="3402311750134118165">"størrelse: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, udløb: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Beskeden kan ikke sendes. Ugyldig modtager."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Tjenesten er ikke aktiveret på netværket"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Et netværksproblem er skyld i, at afsendelsen mislykkedes"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Beskeden er udløbet eller ikke tilgængelig"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Intet emne)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Ukendt afsender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Leveret"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Beskeden <xliff:g id="SUBJECT">%1$s</xliff:g> blev ikke downloadet fra <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Databasehandlingen blev ikke udført, fordi hukommelsen er for lille"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Beskeden blev ikke sendt"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Nogle beskeder blev ikke sendt i Beskeder"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> beskeder i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> beskeder i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Beskeden blev ikke downloadet"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Nogle beskeder blev ikke downloadet i Beskeder"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> beskeder i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> beskeder i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Beskeden til <xliff:g id="NUMBER">%1$s</xliff:g> blev ikke sendt"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Ring op til alarmcentralen. Din sms-besked til <xliff:g id="NUMBER">%1$s</xliff:g> kan ikke leveres på nuværende tidspunkt."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> nye beskeder</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nye beskeder</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Start"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kameraet er ikke tilgængeligt"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kameraet er ikke tilgængeligt"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Videooptagelse er ikke tilgængelig"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Medie kan ikke gemmes"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Der kan ikke tages billeder"</string>
+    <string name="back" msgid="1477626055115561645">"Tilbage"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arkiveret"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Slet"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkivér"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Fjern fra arkiv"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Deaktiver underretninger"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Aktivér underretninger"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Tilføj kontaktperson"</string>
+    <string name="action_download" msgid="7786338136368564146">"Download"</string>
+    <string name="action_send" msgid="377635240181672039">"Send"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Slet"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vil du slette denne besked?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Denne handling kan ikke fortrydes."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Slet"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Vil du slette disse samtaler?</item>
+      <item quantity="other">Vil du slette disse samtaler?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Slet"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Annuller"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Til"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Vælg flere billeder"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Bekræft valg"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Der kan ikke optages lyd. Prøv igen."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Lyden kan ikke afspilles. Prøv igen."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Lyden kunne ikke gemmes. Prøv igen."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Tryk og hold nede"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Billede"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Lydklip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Visitkort"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Svar via sms"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Svar via mms"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Besvar"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> deltagere</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> deltagere</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Mig"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakten er blokeret og arkiveret"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontaktpersonen er ikke længere blokeret og er fjernet fra arkivet"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> blev arkiveret"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> er blevet fjernet fra arkivet."</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Underretninger er slået fra"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Underretninger er slået til"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Alt er klart. Tryk på Send igen."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Beskeder blev angivet som standardappen til sms-beskeder."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Kassér vedhæftede filer</item>
+      <item quantity="other">Kassér vedhæftede filer</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Vedhæftet lydfil"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Afspil vedhæftet lydfil"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Sæt på pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Besked fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mislykket besked fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Besked fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ikke-afsendt besked til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sender besked til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mislykket besked til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Besked til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mislykket besked fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Besked fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ikke-afsendt besked til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sender besked til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mislykket besked til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Besked til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mislykket besked. Tryk for at prøve igen."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Samtale med <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Slet emne"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Optag video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Tag et stillbillede"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Tag et billede"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Start videooptagelse"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Skift til kamera i fuld skærm"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Skift mellem front- og bagudvendt kamera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stop optagelsen, og vedhæft video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stands optagelse af video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Billeder i Beskeder"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> billeder blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> billeder blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> videoer blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videoer blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> vedhæftede filer blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vedhæftede filer blev gemt i albummet \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer blev gemt under \"Downloads\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer blev gemt under \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer blev gemt</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer blev gemt</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer kunne ikke gemmes</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> vedhæftede filer kunne ikke gemmes</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Den vedhæftede MMS blev gemt"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Indstillinger"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arkiveret"</string>
+    <string name="action_close" msgid="1840519376200478419">"Luk"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Mms"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avanceret"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Fejlretning"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Underretninger"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Lyd"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Lydløs"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrer"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokeret"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-leveringsrapporter"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Anmod om leveringsrapporter for alle de sms-beskeder, du sender"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatisk hentning"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Hent automatisk mms-beskeder"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatisk hentning under roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Hent automatisk mms under roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Gruppebeskeder"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Brug mms til at sende en enkelt besked, når der er flere modtagere"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Standardapp til sms-beskeder"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Standardapp til sms-beskeder"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Dit telefonnummer"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Ukendt"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Lyde for udgående besked"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Gem sms"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Gem rådata fra modtagne sms-beskeder i en fil på et eksternt lager"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Gem mms"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Gem rådata fra modtagne mms-beskeder i en fil på et eksternt lager"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Trådløse alarmer"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Indstillinger for beskeder"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiér tekst"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Se info"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Slet"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Videresend"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Beskedinfo"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Sms"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mms"</string>
+    <string name="from_label" msgid="1947831848146564875">"Fra: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Til: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sendt: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Modtaget: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Emne: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Størrelse: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-kort: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Høj"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Lav"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-kort <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skjult afsenderadresse"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Beskeden kan ikke sendes, mens der indlæses vedhæftede filer."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Den vedhæftede fil kunne ikke indlæses. Prøv igen."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Netværket er ikke klar. Prøv igen."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Slet tekst"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Skift mellem indtastning af tekst og tal"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Tilføj flere deltagere"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Bekræft deltagere"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Start en ny samtale"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Vælg dette element"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Afspil video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Personer og valgmuligheder"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Fejlretning"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Personer og valgmuligheder"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Generelt"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Personer i denne samtale"</string>
+    <string name="action_call" msgid="6596167921517350362">"Foretag et opkald"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Send besked"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Send besked&lt;br/&gt;&lt;small&gt;fra <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Send billeder</item>
+      <item quantity="other">Send billeder</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Send lydoptagelser</item>
+      <item quantity="other">Send lydoptagelser</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Send videoer</item>
+      <item quantity="other">Send videoer</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Send visitkort</item>
+      <item quantity="other">Send visitkort</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Send vedhæftede filer</item>
+      <item quantity="other">Send vedhæftede filer</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> vedhæftede filer er klar til at blive sendt</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> vedhæftede filer er klar til at blive sendt</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Send feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Se i Google Play Butik"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Oplysninger om versionen"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open source-licenser"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Underretninger"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Grænsen for vedhæftede filer er nået"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Den vedhæftede fil kunne ikke indlæses."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Vil du føje dette nummer til Kontaktpersoner?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Tilføj kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Emne"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Emne: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontaktkortet indlæses"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kontaktkortet kunne ikke indlæses"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Se visitkortet"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> kontaktpersoner</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktpersoner</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktkort"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Fødselsdag"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Noter"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Videresend besked"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Svar"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Sms er slået fra"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Angiv Beskeder som standardappen til sms-beskeder for at sende beskeder"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Angiv Beskeder som standardappen til sms-beskeder"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Skift"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Angiv Beskeder som standardappen til sms-beskeder for at modtage beskeder"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Der er ikke valgt et foretrukket simkort til afsendelse af sms-beskeder"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Denne app er ikke tilladt af enhedens ejer."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Der er for mange deltagere i en samtale"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Ugyldige kontaktpersoner</item>
+      <item quantity="other">Ugyldige kontaktpersoner</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kamerabilledet kunne ikke indlæses"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Dig: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Kladde"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Når du starter en ny samtale, vises den her"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arkiverede samtaler vises her"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Indlæser samtaler ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Billede"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Lydklip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Visitkort"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Mms"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Fortryd"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Prøv igen"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Indtast navnet på en kontaktperson eller et telefonnummer for at starte på en ny besked"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloker"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloker <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Ophæv blokering af <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vil du blokere <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Du vil fortsat modtage beskeder fra dette nummer, men du bliver ikke længere underrettet. Denne samtale arkiveres."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokerede kontakter"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"OPHÆV BLOKERING"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokerede kontakter"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Vælg billede fra dokumentbiblioteket"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sender besked"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Beskeden er sendt"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobildata er slået fra. Kontrollér dine indstillinger."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Der kan ikke sendes beskeder i flytilstand"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Beskeden blev ikke sendt"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Beskeden blev downloadet"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobildata er slået fra. Kontrollér dine indstillinger."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Beskeder kan ikke downloades i flytilstand"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Beskeden kunne ikke downloades"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nul"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Et"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"To"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tre"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Fire"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Fem"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seks"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Syv"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Otte"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Ni"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Der kan ikke sendes en besked med <xliff:g id="CARRIERNAME">%1$s</xliff:g>, fejl <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Der kan ikke sendes en besked med ukendt mobilselskab, fejl <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Vs: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Beskeden blev ikke sendt: Tjenesten er ikke aktiveret på netværket"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Beskeden blev ikke sendt: Destinationsadressen er ugyldig"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Beskeden blev ikke sendt: Beskeden er ugyldig"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Beskeden blev ikke sendt: Indholdet understøttes ikke"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Beskeden blev ikke sendt: Beskeden understøttes ikke"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Beskeden blev ikke sendt, da den er for stor"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Ny besked"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Vis"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Billede"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Vi kunne ikke finde en passende applikation"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Fjern modtager"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Ny besked"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Annuller"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Rediger adgangspunkt"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ikke angivet"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Navn"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Adgangspunkt"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Adgangspunktstype"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Slet adgangspunkt"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nyt adgangspunkt"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Gem"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Kassér"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Feltet Navn skal udfyldes."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Du skal angive et adgangspunkt."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Feltet MCC skal indeholde tre cifre."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Feltet MNC skal indeholde to eller tre cifre."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Gendanner standardindstillingerne for adgangspunktet."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Nulstil til standard"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Standardindstillingerne for adgangspunktet er nulstillet."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Ikke-navngivet"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Adgangspunkter"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Adgangspunkter"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nyt adgangspunkt"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Indstillingerne for adgangspunkt (APN) er ikke tilgængelige for denne bruger"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Vil du kopiere til udklipsholder?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiér"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"til <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Generelt"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avanceret"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Generelle indstillinger"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Avancerede indstillinger"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Indstillinger for SIM-kortet \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Send individuelle sms-beskeder til alle modtagere. Der kan kun sendes svar til dig"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Send en enkelt mms-besked til alle modtagere"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Ukendt nummer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Ny besked"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Ny besked."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-vælger"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> er valgt. SIM-vælger"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Rediger emne"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Vælg SIM-kort, eller rediger emne"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Tryk og hold nede for at optage lyd"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Start en ny samtale"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Beskeder"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Liste i Beskeder"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Beskeder"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Ny besked"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Samtaleliste"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Indlæser samtaler"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Indlæser beskeder"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Se flere samtaler"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Se flere beskeder"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Samtalen er slettet"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Samtalen blev slettet. Tryk for at se en anden samtale i Beskeder."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokeret"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blokering fjernet"</string>
+    <string name="db_full" msgid="8459265782521418031">"Der er for lidt lagerplads. Nogle data gemmes muligvis ikke."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Vælg vedhæftede filer"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Bekræft valg"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Der er valgt <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Fjern en eller flere vedhæftede filer, og prøv igen."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Du kan prøve at sende din besked, men den leveres muligvis ikke, medmindre du fjerner en eller flere vedhæftede filer."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Du kan kun sende én video pr besked. Fjern flere videoer, og prøv igen."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Beskeder kunne ikke indlæse den vedhæftede fil."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Send alligevel"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Samtalen kunne ikke startes"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> er valgt"</string>
+</resources>
diff --git a/res/values-de/arrays.xml b/res/values-de/arrays.xml
new file mode 100644
index 0000000..c3e971f
--- /dev/null
+++ b/res/values-de/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"kein Betreff"</item>
+    <item msgid="272485471009191934">"Kein Betreff"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nein"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Vielen Dank!"</item>
+    <item msgid="4881335087096496747">"Ich stimme zu."</item>
+    <item msgid="2422296858597420738">"Wunderbar"</item>
+    <item msgid="4805581752819452687">"Bin auf dem Weg."</item>
+    <item msgid="4746700499431366214">"OK, ich melde mich später."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 0000000..4537b8b
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS/MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS/MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Konversation auswählen"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Einstellungen"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Nachricht senden"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Anhang hinzufügen"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hilfe"</string>
+    <string name="welcome" msgid="2857560951820802321">"Willkommen"</string>
+    <string name="skip" msgid="7238879696319945853">"Überspringen"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Weiter &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Weiter"</string>
+    <string name="exit" msgid="1905187380359981199">"Beenden"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Einstellungen &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Einstellungen"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Die SMS/MMS App benötigt Berechtigungen für SMS, Telefon und Kontakte."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Sie können die Berechtigungen unter \"Einstellungen\" &gt; \"Apps\" &gt; \"SMS/MMS\" &gt; \"Berechtigungen\" ändern."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Sie können die Berechtigungen unter \"Einstellungen\" &gt; \"Apps\" &gt; \"SMS/MMS\" &gt; \"Berechtigungen\" ändern."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Häufig genutzte Kontakte"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alle Kontakte"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"An <xliff:g id="DESTINATION">%s</xliff:g> senden"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Bilder oder Videos aufnehmen"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Bilder von diesem Gerät auswählen"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Audio aufzeichnen"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Foto auswählen"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Die Medien sind ausgewählt."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Die Auswahl der Medien ist aufgehoben."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ausgewählt"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"Bild: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"Bild"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Audio aufzeichnen"</string>
+    <string name="action_share" msgid="2143483844803153871">"Teilen"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Gerade eben"</string>
+    <string name="posted_now" msgid="867560789350406701">"Jetzt"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> Stunden</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> Stunde</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> Tage</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> Tag</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Wochen</item>
+      <item quantity="one">eine Woche</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Monate</item>
+      <item quantity="one">ein Monat</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Jahre</item>
+      <item quantity="one">ein Jahr</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Nachricht Klasse 0"</string>
+    <string name="save" msgid="5081141452059463572">"Speichern"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Das Gerät verfügt über wenig Speicherplatz. Die SMS/MMS App löscht ältere Nachrichten automatisch, um Speicherplatz freizugeben."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Der Speicherplatz wird knapp"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Die SMS/MMS App versendet oder empfängt möglicherweise keine Nachrichten, bis mehr Speicherplatz auf Ihrem Gerät zur Verfügung steht."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Geringer SMS-Speicherplatz. Sie müssen eventuell Nachrichten löschen."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Telefonnummer bestätigen"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Mit dieser einmaligen Eingabe stellen Sie sicher, dass die SMS/MMS App Ihre Gruppennachrichten korrekt sendet."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonnummer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Alle Nachrichten mit Medien löschen"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Nachrichten löschen, die älter als <xliff:g id="DURATION">%s</xliff:g> sind"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Nachrichten, die älter als <xliff:g id="DURATION">%s</xliff:g> sind, automatisch löschen"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorieren"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Alle Nachrichten mit Medien löschen?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Nachrichten löschen, die älter als <xliff:g id="DURATION">%s</xliff:g> sind?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Nachrichten löschen, die älter als <xliff:g id="DURATION">%s</xliff:g> sind, und automatisches Löschen aktivieren?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> hat Folgendes gesagt:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Sie haben Folgendes gesagt:"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Nachricht von <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Sie haben eine Nachricht gesendet."</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Nachricht wird gesendet…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nachricht wurde nicht gesendet. Zum erneuten Senden tippen."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nachricht wurde nicht gesendet. Neuer Versuch…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Erneut senden oder löschen"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Bitte kontaktieren Sie die Notfalldienste per Sprachanruf. Ihre SMS konnte dieses Mal nicht zugestellt werden."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Fehler"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Neue MMS zum Herunterladen"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Neue MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Fehler beim Download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Für neuen Versuch hier tippen"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Zum Herunterladen tippen"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Herunterladen oder löschen"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Nachricht wird heruntergeladen…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Nachricht abgelaufen oder nicht verfügbar"</string>
+    <string name="mms_info" msgid="3402311750134118165">"Größe: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, läuft ab: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nachricht kann nicht gesendet werden. Der Empfänger ist ungültig."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Dienst im Netzwerk nicht aktiviert"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Nachricht kann aufgrund eines Netzwerkproblems nicht gesendet werden."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Nachricht abgelaufen oder nicht verfügbar"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Kein Betreff)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Unbekannter Absender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Zugestellt"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nachricht \"<xliff:g id="SUBJECT">%1$s</xliff:g>\" von <xliff:g id="FROM">%2$s</xliff:g> konnte nicht heruntergeladen werden."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Datenbankoperation konnte aufgrund unzureichenden Speichers nicht abgeschlossen werden."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Nachricht wurde nicht gesendet."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Einige Nachrichten in der SMS/MMS App wurden nicht gesendet."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> Nachrichten in <xliff:g id="CONVERSATIONS">%d</xliff:g> Unterhaltungen</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> Nachricht in einer Unterhaltung</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Nachricht nicht heruntergeladen"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Einige Nachrichten in der SMS/MMS App wurden nicht heruntergeladen."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> Nachrichten in <xliff:g id="CONVERSATIONS">%d</xliff:g> Unterhaltungen</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> Nachricht in einer Unterhaltung</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"SMS an <xliff:g id="NUMBER">%1$s</xliff:g> nicht gesendet"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Bitte kontaktieren Sie die Notfalldienste per Sprachanruf. Ihre SMS an <xliff:g id="NUMBER">%1$s</xliff:g> konnte dieses Mal nicht zugestellt werden."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> neue Nachrichten</item>
+      <item quantity="one">Neue Nachricht</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Starten"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera nicht verfügbar"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera nicht verfügbar"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Videoaufnahme nicht verfügbar"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Medien können nicht gespeichert werden."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Keine Bildaufnahme möglich"</string>
+    <string name="back" msgid="1477626055115561645">"Zurück"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archiviert"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Löschen"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivieren"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Aus Archiv entfernen"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Benachrichtigungen deaktivieren"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Benachrichtigungen aktivieren"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Kontakt hinzufügen"</string>
+    <string name="action_download" msgid="7786338136368564146">"Herunterladen"</string>
+    <string name="action_send" msgid="377635240181672039">"Senden"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Löschen"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Diese Nachricht löschen?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Diese Aktion kann nicht rückgängig gemacht werden."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Löschen"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Diese Unterhaltungen löschen?</item>
+      <item quantity="one">Diese Unterhaltung löschen?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Löschen"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Abbrechen"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"An"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Mehrere Bilder auswählen"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Auswahl bestätigen"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Die Audioaufzeichnung ist nicht möglich. Bitte versuchen Sie es erneut."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Die Audiowiedergabe ist nicht möglich. Bitte versuchen Sie es erneut."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Die Audionachricht konnte nicht gespeichert werden. Bitte versuchen Sie es erneut."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Berühren und halten"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Bild"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audioclip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktkarte"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Herunterladen"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Per SMS antworten"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Antwort per MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Antworten"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> Teilnehmer</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> Teilnehmer</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ich"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt blockiert und archiviert"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Blockierung des Kontakts aufgehoben &amp; Kontakt aus dem Archiv entfernt"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archiviert"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> aus dem Archiv entfernt"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Benachrichtigungen deaktiviert"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Benachrichtigungen aktiviert"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Bereit. Zum erneuten Senden tippen."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Die SMS/MMS App wurde als Standard-SMS-App festgelegt."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Anhänge verwerfen</item>
+      <item quantity="one">Anhang verwerfen</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audioanhang"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Audioanhang wiedergeben"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausieren"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Nachricht von <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Fehler bei Nachricht von <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Nachricht von <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Nicht gesendete Nachricht an <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Nachricht wird gesendet an <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Fehler bei Nachricht an <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Nachricht an <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Fehler bei Nachricht von <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Nachricht von <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Nicht gesendete Nachricht an <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Nachricht wird gesendet an <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Fehler bei Nachricht an <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Nachricht an <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Uhrzeit: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Fehler bei Nachricht. Zum Wiederholen tippen."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Unterhaltung mit <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Betreff löschen"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video aufnehmen"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Standbild aufnehmen"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Bild aufnehmen"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Videoaufnahme starten"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Zur Vollbildkamera wechseln"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Zwischen Kamera auf Vorder- und Rückseite wechseln"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Aufnahme beenden und Video anhängen"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Videoaufzeichnung stoppen"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos in der SMS/MMS App"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> Fotos im Album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" gespeichert</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Foto im Album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" gespeichert</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> Videos im Album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" gespeichert</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Video im Album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" gespeichert</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> Anhänge im Album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" gespeichert</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Anhang im Album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" gespeichert</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> Anhänge in \"Downloads\" gespeichert</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Anhang in \"Downloads\" gespeichert</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> Anhänge wurden gespeichert.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Anhang wurde gespeichert.</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> Anhänge konnten nicht gespeichert werden.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> Anhang konnte nicht gespeichert werden.</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS-Anhang gespeichert"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Einstellungen"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archiviert"</string>
+    <string name="action_close" msgid="1840519376200478419">"Schließen"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Erweitert"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Fehlersuche"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Benachrichtigungen"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ton"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Lautlos"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrieren"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blockiert"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-Zustellberichte"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Zustellbestätigung für jede gesendete SMS anfordern"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatisch abrufen"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS-Nachrichten automatisch abrufen"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatischer Roaming-Abruf"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"MMS beim Roaming automatisch abrufen"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"SMS/MMS an Gruppe senden"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Verwenden Sie MMS, um eine einzelne Nachricht an mehrere Empfänger zu versenden."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Standard-SMS-App"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Standard-SMS-App"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Meine Telefonnummer"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Unbekannt"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Töne für ausgehende Nachrichten"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS sichern"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Erhaltene SMS-Rohdaten in externer Speicherdatei sichern"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS sichern"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Erhaltene MMS-Rohdaten in externer Speicherdatei sichern"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Cell Broadcast-Warnungen"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Nachrichtenoptionen"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Text kopieren"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Details ansehen"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Löschen"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Weiterleiten"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Nachrichtendetails"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Typ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"MMS"</string>
+    <string name="from_label" msgid="1947831848146564875">"Von: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"An: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Gesendet: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Empfangen: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Betreff: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Größe: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorität: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Hoch"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Niedrig"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Ausgeblendete Senderadresse"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Die Nachricht kann nicht gesendet werden, weil die Anhänge noch nicht geladen wurden."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Anhang kann nicht geladen werden. Bitte versuchen Sie es erneut."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Netzwerk ist nicht bereit. Bitte versuchen Sie es erneut."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Text löschen"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Zwischen Text- und Zifferneingabe wechseln"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Weitere Teilnehmer hinzufügen"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Teilnehmer bestätigen"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Neue Unterhaltung starten"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Dieses Element auswählen"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Video abspielen"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Personen &amp; Optionen"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debuggen"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Personen &amp; Optionen"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Allgemein"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Personen in dieser Konversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Anrufen"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Nachricht senden"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Nachricht senden&lt;br/&gt;&lt;small&gt;von <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Fotos senden</item>
+      <item quantity="one">Foto senden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Audioaufzeichnungen senden</item>
+      <item quantity="one">Audioaufzeichnung senden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Videos senden</item>
+      <item quantity="one">Video senden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Kontaktkarten senden</item>
+      <item quantity="one">Kontaktkarte senden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Anhänge senden</item>
+      <item quantity="one">Anhang senden</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> Anhänge zum Senden bereit</item>
+      <item quantity="one">Ein Anhang zum Senden bereit</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Feedback geben"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Im Google Play Store ansehen"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versionsinformationen"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version: %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open-Source-Lizenzen"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Benachrichtigungen"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Anhanglimit erreicht"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Anhang konnte nicht geladen werden"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Zu Kontakten hinzufügen?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Kontakt hinzufügen"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Betreff"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Betreff: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontaktkarte wird geladen."</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kontaktkarte kann nicht geladen werden."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Kontaktkarte ansehen"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> Kontakte</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> Kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktkarten"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Geburtstag"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notizen"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Nachricht weiterleiten"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Antworten"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS deaktiviert"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Um Nachrichten zu senden, legen Sie die SMS/MMS App als Standard-SMS-App fest."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Legen Sie die SMS/MMS App als Standard-SMS-App fest."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Ändern"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Um Nachrichten zu erhalten, legen Sie die SMS/MMS App als Standard-SMS-App fest."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Keine bevorzugte SIM für das Senden von SMS ausgewählt"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Diese App wird vom Geräteeigentümer nicht zugelassen."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Zu viele Teilnehmer in der Unterhaltung"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Ungültige Kontakte</item>
+      <item quantity="one">Ungültiger Kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kamerabild kann nicht geladen werden."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Sie: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Entwurf"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Wenn Sie eine neue Unterhaltung beginnen, wird diese hier angezeigt"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Archivierte Unterhaltungen erscheinen hier."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Unterhaltungen werden geladen…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Bild"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audioclip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktkarte"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Rückgängig"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Erneut versuchen"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Geben Sie einen Kontaktnamen oder eine Telefonnummer ein, um eine neue Nachricht zu beginnen."</string>
+    <string name="action_block" msgid="9032076625645190136">"Blockieren"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> blockieren"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Blockierung aufheben für <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> blockieren?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Sie erhalten weiterhin Nachrichten von dieser Nummer, werden jedoch nicht mehr benachrichtigt. Diese Unterhaltung wird archiviert."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blockierte Kontakte"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"Blockierung aufheben"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blockierte Kontakte"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Bild aus der Dokumentenbibliothek auswählen"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Nachricht wird gesendet"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Nachricht gesendet"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobilfunkdaten sind deaktiviert. Bitte überprüfen Sie Ihre Einstellungen."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Im Flugmodus können keine Nachrichten gesendet werden."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Die Nachricht konnte nicht gesendet werden."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Nachricht heruntergeladen"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobilfunkdaten sind deaktiviert. Bitte überprüfen Sie Ihre Einstellungen."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Im Flugmodus können keine Nachrichten heruntergeladen werden."</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Die Nachricht konnte nicht heruntergeladen werden."</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Null"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Eins"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Zwei"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Drei"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Vier"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Fünf"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sechs"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sieben"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Acht"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Neun"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nachricht kann nicht mit <xliff:g id="CARRIERNAME">%1$s</xliff:g> gesendet werden. Fehler <xliff:g id="ERRORCODE">%2$d</xliff:g>."</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nachricht kann nicht mit einem unbekannten Mobilfunkanbieter gesendet werden. Fehler <xliff:g id="ERRORCODE">%1$d</xliff:g>."</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Nachricht wurde nicht gesendet: Der Dienst ist im Netzwerk nicht aktiviert."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Nachricht nicht gesendet: ungültige Zieladresse"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Nachricht nicht gesendet: ungültige Nachricht"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Nachricht nicht gesendet: nicht unterstützter Inhalt"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Nachricht nicht gesendet: nicht unterstützte Nachricht"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Nachricht nicht gesendet: zu groß"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Neue Nachricht"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ansehen"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Bild"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Keine geeignete App gefunden"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Empfänger entfernen"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Neue Nachricht"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Abbrechen"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Zugangspunkt bearbeiten"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nicht definiert"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Name"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-Proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-Port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-Typ"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN löschen"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Neuer APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Speichern"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Verwerfen"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Das Namensfeld darf nicht leer sein."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN darf nicht leer sein."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Das MCC-Feld muss 3 Zeichen enthalten."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Das MNC-Feld muss 2 oder 3 Zeichen enthalten."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Standard-APN-Einstellungen werden wiederhergestellt"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Auf Standard zurücksetzen"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Zurücksetzen auf Standard-APN-Einstellungen abgeschlossen"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Unbenannt"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Zugriffspunktnamen"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Neuer APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Die Einstellungen für den Zugangspunkt sind für diesen Nutzer nicht verfügbar."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"In Zwischenablage kopieren?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopieren"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"an <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Allgemein"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Erweitert"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Allgemeine Einstellungen"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Erweiterte Einstellungen"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Einzelne SMS-Nachrichten an alle Empfänger senden. Die Antworten erhalten nur Sie."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Einzelne MMS an alle Empfänger senden"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Unbekannte Nummer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Neue Nachricht"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Neue Nachricht"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-Auswahl"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ausgewählt, SIM-Auswahl"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Betreff bearbeiten"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM auswählen oder Betreff bearbeiten"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Für Audioaufnahme berühren und halten"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Neue Unterhaltung starten"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS/MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Liste der Unterhaltungen"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Nachricht"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Neue Nachricht"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Konversationsliste"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Unterhaltungen werden geladen"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Nachrichten werden geladen"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Weitere Unterhaltungen anzeigen"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Weitere Nachrichten ansehen"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Konversation gelöscht"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Unterhaltung gelöscht. Tippen Sie hier, um eine andere Unterhaltung zu sehen."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blockiert"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blockierung aufgehoben"</string>
+    <string name="db_full" msgid="8459265782521418031">"Wenig freier Speicherplatz. Einige Daten gehen möglicherweise verloren."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Anhänge auswählen"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Auswahl bestätigen"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ausgewählt"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Bitte entfernen Sie mindestens einen Anhang und versuchen Sie es erneut."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Sie können versuchen, die Nachricht zu senden, sie wird jedoch möglicherweise nicht zugestellt, wenn Sie nicht mindestens einen Anhang entfernen."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Pro Nachricht kann nur ein Video gesendet werden. Bitte entfernen Sie überzählige Videos und versuchen Sie es erneut."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Die SMS/MMS App konnte den Anhang nicht laden."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Trotzdem senden"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Die Unterhaltung konnte nicht gestartet werden."</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ausgewählt"</string>
+</resources>
diff --git a/res/values-el/arrays.xml b/res/values-el/arrays.xml
new file mode 100644
index 0000000..280d8e9
--- /dev/null
+++ b/res/values-el/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"χωρίς θέμα"</item>
+    <item msgid="272485471009191934">"χωρίς θέμα"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ναι"</item>
+    <item msgid="6049132459802288033">"Όχι"</item>
+    <item msgid="3084376867445867895">"ΟΚ"</item>
+    <item msgid="3155097332660174689">"Χαχα"</item>
+    <item msgid="2611328818571146775">"Σας ευχαριστούμε"</item>
+    <item msgid="4881335087096496747">"Συμφωνώ"</item>
+    <item msgid="2422296858597420738">"Ωραία"</item>
+    <item msgid="4805581752819452687">"Έρχομαι"</item>
+    <item msgid="4746700499431366214">"Εντάξει, θα επικοινωνήσω μαζί σου αργότερα"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
new file mode 100644
index 0000000..d74a84b
--- /dev/null
+++ b/res/values-el/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Ανταλλαγή μηνυμάτων"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Ανταλλαγή μηνυμάτων"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Επιλογή συνομιλίας"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ρυθμίσεις"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Αποστολή μηνύματος"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Προσθήκη συνημμένου αρχείου"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Βοήθεια"</string>
+    <string name="welcome" msgid="2857560951820802321">"Καλώς ήρθατε"</string>
+    <string name="skip" msgid="7238879696319945853">"Παράλειψη"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Επόμενο &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Επόμενο"</string>
+    <string name="exit" msgid="1905187380359981199">"Έξοδος"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Ρυθμίσεις &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ρυθμίσεις"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Η Ανταλλαγή μηνυμάτων χρειάζεται άδεια για SMS, Τηλέφωνο και Επαφές."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Μπορείτε να αλλάξετε τα δικαιώματα στις Ρυθμίσεις &gt; Εφαρμογές &gt; Ανταλλαγή μηνυμάτων &gt; Δικαιώματα."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Μπορείτε να αλλάξετε τα δικαιώματα στις Ρυθμίσεις, Εφαρμογές, Μηνύματα, Δικαιώματα."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Συχνή επικοινωνία"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Όλες οι επαφές"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Αποστολή σε <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Λήψη εικόνων ή βίντεο"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Επιλέξτε εικόνες από αυτήν τη συσκευή"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Ηχογράφηση"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Επιλογή φωτογραφίας"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Το μέσο είναι επιλεγμένο."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Το μέσο δεν είναι επιλεγμένο."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> επιλεγμένα"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"εικόνα <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"εικόνα"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Ηχογράφηση"</string>
+    <string name="action_share" msgid="2143483844803153871">"Κοινή χρήση"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Μόλις τώρα"</string>
+    <string name="posted_now" msgid="867560789350406701">"Τώρα"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> λεπτά</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> λεπτό</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ώρες</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ώρα</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ημέρες</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ημέρα</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> εβδομάδες</item>
+      <item quantity="one">μία εβδομάδα</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> μήνες</item>
+      <item quantity="one">ένας μήνας</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> έτη</item>
+      <item quantity="one">ένα έτος</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Μήνυμα κλάσης 0"</string>
+    <string name="save" msgid="5081141452059463572">"Αποθήκευση"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Ο αποθηκευτικός χώρος της συσκευής είναι περιορισμένος. Η Ανταλλαγή μηνυμάτων θα διαγράψει αυτόματα τα παλαιότερα μηνύματα για να απελευθερώσει χώρο."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Ο χώρος αποθήκευσης εξαντλείται"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Η Ανταλλαγή μηνυμάτων μπορεί να μην κάνει αποστολή ή λήψη μηνυμάτων μέχρι να ελευθερώσετε περισσότερο χώρο στη συσκευή σας."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Περιορισμένος αποθηκευτικός χώρος SMS. Μπορεί να χρειαστεί να διαγράψετε μηνύματα."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Επιβεβαιώστε τον αριθμό τηλεφώνου σας"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Αυτό το μοναδικό βήμα θα εξασφαλίσει ότι η Ανταλλαγή μηνυμάτων θα παραδώσει σωστά τα ομαδικά μηνύματά σας."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Αριθμός τηλεφώνου"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Διαγραφή όλων των μηνυμάτων με πολυμέσα"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Διαγραφή μηνυμάτων πριν από τις <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Αυτόματη διαγραφή των μηνυμάτων πριν από <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Παράβλεψη"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Να γίνει διαγραφή όλων των μηνυμάτων που περιέχουν πολυμέσα;"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Να γίνει διαγραφή των μηνυμάτων πριν από τις <xliff:g id="DURATION">%s</xliff:g>;"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Να γίνει αυτόματη διαγραφή των μηνυμάτων πριν από <xliff:g id="DURATION">%s</xliff:g> και ενεργοποίηση της αυτόματης διαγραφής;"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"Ο χρήστης <xliff:g id="SENDER">%s</xliff:g> είπε"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Είπατε"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Μήνυμα από το χρήστη <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Στείλατε ένα μήνυμα"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Αποστολή…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Δεν εστάλη. Αγγίξτε για να δοκιμάσετε ξανά."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Δεν εστάλη. Επανάληψη…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Εκ νέου αποστολή ή διαγραφή"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Κάντε μια φωνητική κλήση στις υπηρεσίες έκτακτης ανάγκης. Δεν ήταν δυνατή η παράδοση του μηνύματος κειμένου σας αυτήν τη φορά."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Αποτυχία"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Νέο μήνυμα MMS για λήψη"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Νέο μήνυμα MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Δεν ήταν δυνατή η λήψη"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Αγγίξτε για να δοκιμάσετε ξανά"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Αγγίξτε για λήψη"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Λήψη ή διαγραφή"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Λήψη…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Το μήνυμα έληξε ή δεν είναι διαθέσιμο"</string>
+    <string name="mms_info" msgid="3402311750134118165">"μέγεθος: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, λήξη: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Δεν είναι δυνατή η αποστολή. Ο παραλήπτης δεν είναι έγκυρος."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Η υπηρεσία δεν έχει ενεργοποιηθεί στο δίκτυο"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Δεν ήταν δυνατή η αποστολή λόγω προβλήματος στο δίκτυο"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Το μήνυμα έληξε ή δεν είναι διαθέσιμο."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Χωρίς θέμα)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Άγνωστος αποστολέας"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Παραδόθηκε"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Δεν ήταν δυνατή η λήψη του μηνύματος <xliff:g id="SUBJECT">%1$s</xliff:g> από <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Δεν ήταν δυνατή η ολοκλήρωση της λειτουργίας της βάσης δεδομένων λόγω ανεπαρκούς μνήμης"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Το μήνυμα δεν εστάλη"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Ορισμένα μηνύματα δεν εστάλησαν στην Ανταλλαγή μηνυμάτων"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> μηνύματα σε <xliff:g id="CONVERSATIONS">%d</xliff:g> συνομιλίες</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> μηνύματα σε μία συνομιλία</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Δεν έγινε λήψη του μηνύματος"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Δεν έγινε λήψη ορισμένων μηνυμάτων στην Ανταλλαγή μηνυμάτων"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> μηνύματα σε <xliff:g id="CONVERSATIONS">%d</xliff:g> συνομιλίες</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> μηνύματα σε μία συνομιλία</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Το μήνυμα στον αριθμό <xliff:g id="NUMBER">%1$s</xliff:g> δεν εστάλη"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Κάντε μια φωνητική κλήση στις υπηρεσίες έκτακτης ανάγκης. Δεν ήταν δυνατή η παράδοση του μηνύματος κειμένου σας στον αριθμό <xliff:g id="NUMBER">%1$s</xliff:g> αυτήν τη φορά."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> νέα μηνύματα</item>
+      <item quantity="one">Νέο μήνυμα</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Έναρξη"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Η φωτογραφική μηχανή δεν είναι διαθέσιμη"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Η φωτογραφική μηχανή δεν είναι διαθέσιμη"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Η εγγραφή βίντεο δεν είναι διαθέσιμη"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Δεν είναι δυνατή η αποθήκευση πολυμέσων"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Δεν είναι δυνατή η λήψη φωτογραφίας"</string>
+    <string name="back" msgid="1477626055115561645">"Πίσω"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Αρχειοθετημένο"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Διαγραφή"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Αρχειοθέτηση"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Κατάργηση αρχειοθέτησης"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Απενεργοποίηση ειδοποιήσεων"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Ενεργοποίηση ειδοποιήσεων"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Προσθήκη επαφής"</string>
+    <string name="action_download" msgid="7786338136368564146">"Λήψη"</string>
+    <string name="action_send" msgid="377635240181672039">"Αποστολή"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Διαγραφή"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Να διαγραφεί αυτό το μήνυμα;"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Δεν είναι δυνατή η αναίρεση αυτής της ενέργειας."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Διαγραφή"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Διαγραφή αυτών των συνομιλιών;</item>
+      <item quantity="one">Διαγραφή αυτής της συνομιλίας;</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Διαγραφή"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Ακύρωση"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Προς"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Επιλογή πολλαπλών εικόνων"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Επιβεβαίωση επιλογής"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Δεν είναι δυνατή η αποθήκευση ήχου. Δοκιμάστε ξανά."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Δεν είναι δυνατή η αναπαραγωγή ήχου. Δοκιμάστε ξανά."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Δεν ήταν δυνατή η αποθήκευση ήχου. Δοκιμάστε ξανά."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Άγγιγμα &amp; κράτημα"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Εικόνα"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Κλιπ ήχου"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Βίντεο"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Κάρτα επικοινωνίας"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Λήψη"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Απάντηση μέσω SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Απάντηση μέσω MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Απάντηση"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> συμμετέχοντες</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> συμμετέχων</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Εγώ"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Η επαφή αποκλείστηκε και αρχειοθετήθηκε"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Έγινε κατάργηση αποκλεισμού και αρχειοθέτησης της επαφής"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Έχουν αρχειοθετηθεί <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> αφαιρέθηκαν από το αρχείο"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Οι ειδοποιήσεις απενεργοποιήθηκαν"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Οι ειδοποιήσεις ενεργοποιήθηκαν"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Έχουν ρυθμιστεί όλα. Αγγίξτε ξανά την επιλογή \"Αποστολή\"."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Η Ανταλλαγή μηνυμάτων ορίστηκε επιτυχώς ως η προεπιλεγμένη εφαρμογή SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Απόρριψη συνημμένων</item>
+      <item quantity="one">Απόρριψη συνημμένου</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Συνημμένο ήχου"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Αναπαραγωγή συνημμένου ήχου"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Παύση"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Μήνυμα από <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Αποτυχία μηνύματος από <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Μήνυμα από <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Μη απεσταλμένο μήνυμα προς <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Αποστολή μηνύματος προς <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Αποτυχία μηνύματος προς <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Μήνυμα προς <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Αποτυχία μηνύματος από <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Μήνυμα από <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Μη απεσταλμένο μήνυμα προς <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Αποστολή μηνύματος σε <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Αποτυχία μηνύματος προς <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Μήνυμα προς <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ώρα: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Αποτυχία μηνύματος. Αγγίξτε για επανάληψη."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Συνομιλία με <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Διαγραφή θέματος"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Λήψη βίντεο"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Τραβήξτε μια στατική εικόνα"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Τραβήξτε μια φωτογραφία"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Έναρξη εγγραφής βίντεο"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Εναλλαγή σε κάμερα πλήρους οθόνης"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Εναλλαγή μεταξύ μπροστινής και της πίσω φωτογραφικής μηχανής"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Διακοπή εγγραφής και επισύναψη βίντεο"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Διακοπή εγγραφής βίντεο"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Φωτογραφίες Ανταλλαγής μηνυμάτων"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> φωτογραφίες αποθηκεύτηκαν στο λεύκωμα \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> φωτογραφία αποθηκεύτηκε στο λεύκωμα \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> βίντεο αποθηκεύτηκαν στο λεύκωμα \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> βίντεο αποθηκεύτηκε στο λεύκωμα \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> συνημμένα αποθηκεύτηκαν στο λεύκωμα \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> συνημμένο αποθηκεύτηκε στο λεύκωμα \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> συνημμένα αποθηκεύτηκαν στις \"Λήψεις\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> συνημμένο αποθηκεύτηκε στις \"Λήψεις\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Αποθηκεύτηκε <xliff:g id="QUANTITY_1">%d</xliff:g> συνημμένων αρχείων</item>
+      <item quantity="one">Αποθηκεύτηκε <xliff:g id="QUANTITY_0">%d</xliff:g> συνημμένο αρχείο</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Δεν ήταν δυνατή η αποθήκευση <xliff:g id="QUANTITY_1">%d</xliff:g> συνημμένων αρχείων</item>
+      <item quantity="one">Δεν ήταν δυνατή η αποθήκευση <xliff:g id="QUANTITY_0">%d</xliff:g> συνημμένου αρχείου</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Αποθηκευμένο συνημμένο MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ρυθμίσεις"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Αρχειοθετημένο"</string>
+    <string name="action_close" msgid="1840519376200478419">"Κλείσιμο"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Σύνθετες ρυθμίσεις"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Εντοπισμός σφαλμάτων"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Ειδοποιήσεις"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ήχος"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Σίγαση"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Δόνηση"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Αποκλεισμένο"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Αναφορές παράδοσης SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Αίτηση αναφοράς παράδοσης για κάθε SMS που στέλνετε"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Αυτόματη ανάκτηση"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Αυτόματη ανάκτηση μηνυμάτων MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Αυ/τη ανάκτηση περιαγ."</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Αυτόματη ανάκτηση MMS κατά την περιαγωγή"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Ομαδική ανταλλαγή μηνυμάτων"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Χρησιμοποιήστε το MMS για να στείλετε ένα μήνυμα σε πολλούς παραλήπτες"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Προεπιλεγμένη εφαρμογή SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Προεπιλεγμένη εφαρμογή SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Ο αριθμός τηλεφώνου σας"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Άγνωστo"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Ήχοε εξερχόμενου μηνύματος"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Απόρριψη SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Απόρριψη μη επεξεργασμένων δεδομένων ληφθέντων SMS σε αρχείο εξωτερικού αποθηκευτικού χώρου"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Απόρριψη MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Απόρριψη μη επεξεργασμένων δεδομένων ληφθέντων MMS σε αρχείο εξωτερικού αποθηκευτικού χώρου"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Ασύρματες ειδοποιήσεις"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Επιλογές μηνύματος"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Αντιγραφή κειμένου"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Προβολή λεπτομερειών"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Διαγραφή"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Προώθηση"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Λεπτομέρειες μηνύματος"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Τύπος: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Μήνυμα κειμένου"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Μήνυμα πολυμέσων"</string>
+    <string name="from_label" msgid="1947831848146564875">"Από: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Προς: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Εστάλη: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Ελήφθη: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Θέμα: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Μέγεθος: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Προτεραιότητα: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Υψηλή"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Κανονική"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Χαμηλή"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Διεύθυνση κρυφού αποστολέα"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Δεν είναι δυνατή η αποστολή του μηνύματος ενώ φορτώνουν τα συνημμένα."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Δεν είναι δυνατή η φόρτωση της επισύναψης. Δοκιμάστε ξανά."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Το δίκτυο δεν είναι έτοιμο. Δοκιμάστε ξανά."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Διαγραφή κειμένου"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Εναλλαγή μεταξύ εισαγωγής κειμένου και αριθμών"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Προσθήκη περισσότερων συμμετεχόντων"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Επιβεβαίωση συμμετεχόντων"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Έναρξη νέας συνομιλίας"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Επιλέξτε αυτό το στοιχείο"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Αναπαραγωγή βίντεο"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Άτομα και επιλογές"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Εντοπισμός σφαλμάτων"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Άτομα και επιλογές"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Γενικά"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Άτομα σε αυτήν τη συνομιλία"</string>
+    <string name="action_call" msgid="6596167921517350362">"Πραγματοποίηση κλήσης"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Αποστολή μηνύματος"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Αποστολή μηνύματος&lt;br/&gt;&lt;small&gt;από <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Αποστολή φωτογραφιών</item>
+      <item quantity="one">Αποστολή φωτογραφίας</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Αποστολή αρχείων ήχου</item>
+      <item quantity="one">Αποστολή αρχείου ήχου</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Αποστολή αρχείων βίντεο</item>
+      <item quantity="one">Αποστολή αρχείου βίντεο</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Αποστολή καρτών επαφών</item>
+      <item quantity="one">Αποστολή κάρτας επαφής</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Αποστολή συνημμένων</item>
+      <item quantity="one">Αποστολή συνημμένου</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> συνημμένα έτοιμα για αποστολή</item>
+      <item quantity="one">Ένα συνημμένο έτοιμο για αποστολή</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Αποστολή σχολίων"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Προβολή στο Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Πληροφορίες έκδοσης"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Έκδοση %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Άδειες λογισμικού ανοικτού κώδικα"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Ειδοποιήσεις"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Συμπλήρωση ορίου συνημμένων"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Αποτυχία φόρτωσης συνημμένου."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Προσθήκη στις επαφές;"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Προσθήκη επαφής"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Θέμα"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Θέμα: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Φόρτωση κάρτας επαφής"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Δεν ήταν δυνατή η φόρτωση της κάρτας επαφής"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Προβολή κάρτας επαφής"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> επαφές</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> επαφή</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Κάρτες επαφών"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Γενέθλια"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Σημειώσεις"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Προώθηση μηνύματος"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Απάντηση"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Τα SMS απενεργοποιήθηκαν"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Για αποστολή, ορίστε την Ανταλλαγή μηνυμάτων ως προεπιλεγμένη εφαρμογή SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Ορισμός Ανταλλαγής μηνυμάτων ως προεπιλεγμένης εφαρμογής SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Αλλαγή"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Για να λαμβάνετε μηνύματα, ορίστε την Ανταλλαγή μηνυμάτων ως προεπιλεγμένη εφαρμογή SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Δεν έχει επιλεγεί προτιμώμενη SIM για την αποστολή μηνυμάτων SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Αυτή η εφαρμογή δεν επιτρέπεται από τον κάτοχο της συσκευής."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ΟΚ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Πάρα πολλοί συμμετέχοντες σε μια συνομιλία"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Μη έγκυρες επαφές</item>
+      <item quantity="one">Μη έγκυρη επαφή</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Δεν ήταν δυνατή η φόρτωση της εικόνας φωτογραφικής μηχανής"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Εσείς: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Πρόχειρο"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Αφού ξεκινήσετε μια νέα συνομιλία, θα εμφανίζεται εδώ"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Οι αρχειοθετημένες συνομιλίες εμφανίζονται εδώ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Φόρτωση συνομιλιών…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Εικόνα"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Κλιπ ήχου"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Βίντεο"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Κάρτα επαφής"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Αναίρεση"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Επανάληψη"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Εισαγάγετε ένα όνομα επαφής ή έναν αριθμό τηλεφώνου για να ξεκινήσετε ένα νέο μήνυμα"</string>
+    <string name="action_block" msgid="9032076625645190136">"Αποκλεισμός"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Αποκλεισμός επαφής <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Κατάργηση αποκλεισμού της επαφής <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Αποκλεισμός <xliff:g id="DESTINATION">%s</xliff:g>;"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Θα εξακολουθήσετε να λαμβάνετε μηνύματα από αυτόν τον αριθμό, αλλά δεν θα ειδοποιείστε πια. Αυτή η συνομιλία θα αρχειοθετηθεί."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Αποκλεισμένες επαφές"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ΚΑΤΑΡΓΗΣΗ ΑΠΟΚΛΕΙΣΜΟΥ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Αποκλεισμένες επαφές"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Επιλέξτε μια εικόνα από τη βιβλιοθήκη εγγράφων"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Αποστολή μηνύματος"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Το μήνυμα εστάλη"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Τα δεδομένα κινητής τηλεφωνίας έχουν απενεργοποιηθεί. Ελέγξτε τις ρυθμίσεις σας."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Δεν είναι δυνατή η αποστολή μηνυμάτων σε Λειτουργία πτήσης"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Αδυναμία αποστολής μηνύματος"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Έγινε λήψη του μηνύματος"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν. Ελέγξτε τις ρυθμίσεις σας."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Δεν είναι δυνατή η λήψη μηνυμάτων σε λειτουργία πτήσης"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Δεν ήταν δυνατή η λήψη του μηνύματος"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Μηδέν"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Ένα"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Δύο"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Τρία"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Τέσσερα"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Πέντε"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Έξι"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Επτά"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Οκτώ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Εννέα"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Δεν είναι δυνατή η αποστολή του μηνύματος με <xliff:g id="CARRIERNAME">%1$s</xliff:g>, σφάλμα <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Δεν είναι δυνατή η αποστολή του μηνύματος με άγνωστη εταιρεία κινητής τηλεφωνίας, σφάλμα <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Προώθ.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Το μήνυμα δεν εστάλη: Η υπηρεσία δεν ενεργοποιήθηκε στο δίκτυο"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Το μήνυμα δεν εστάλη: μη έγκυρη διεύθυνση προορισμού"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Το μήνυμα δεν εστάλη: μη έγκυρο μήνυμα"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Το μήνυμα δεν εστάλη: μη υποστηριζόμενο περιεχόμενο"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Το μήνυμα δεν εστάλη: μη υποστηριζόμενο μήνυμα"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Το μήνυμα δεν εστάλη: πάρα πολύ μεγάλο"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Νέο μήνυμα"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Προβολή"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Εικόνα"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Δεν ήταν δυνατή η εύρεση της κατάλληλης εφαρμογής"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Κατάργηση παραλήπτη"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Νέο μήνυμα"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Ακύρωση"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Επεξ/σία σημ. πρόσβ."</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Δεν έχει ρυθμιστεί"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Όνομα"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Διακομιστής μεσολάβησης MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Θύρα MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Τύπος APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Διαγραφή APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Νέο APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Αποθήκευση"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Απόρριψη"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Το πεδίο Όνομα δεν μπορεί να είναι κενό."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Το APN δεν μπορεί να είναι κενό."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Το πεδίο MCC πρέπει να αποτελείται από 3 ψηφία."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Το πεδίο MNC πρέπει να αποτελείται από 2 ή 3 ψηφία."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Επαναφορά προεπιλεγμένων ρυθμίσεων APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Επαναφορά προεπιλογών"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Η επαναφορά των εργοστασιακών ρυθμίσεων APN ολοκληρώθηκε."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Χωρίς τίτλο"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Ονόματα σημείου πρόσβασης"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Νέο APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Οι ρυθμίσεις ονόματος σημείου πρόσβασης δεν είναι διαθέσιμες γι\' αυτόν το χρήστη"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Αντιγραφή στο πρόχειρο;"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Αντιγραφή"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"σε <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Γενικά"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Σύνθετες ρυθμίσεις"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Γενικές ρυθμίσεις"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Σύνθετες ρυθμίσεις"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Αποστολή μεμονωμένων μηνυμάτων SMS σε όλους τους παραλήπτες. Μόνο εσείς θα λαμβάνετε τις απαντήσεις"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Αποστολή μεμονωμένου MMS σε όλους τους παραλήπτες"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Άγνωστος αριθμός"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Νέο μήνυμα"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Νέο μήνυμα."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Επιλογέας SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Επιλέχτηκε <xliff:g id="SIM_0">%1$s</xliff:g>, επιλογέας SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Επεξεργασία θέματος"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Επιλέξτε SIM ή επεξεργαστείτε το θέμα"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Πατήστε παρατεταμένα για εγγραφή ήχου"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Έναρξη νέας συνομιλίας"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Ανταλλαγή μηνυμάτων"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Λίστα Ανταλλαγής μηνυμάτων"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Ανταλλαγή μηνυμάτων"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Νέο μήνυμα"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Λίστα συνομιλιών"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Φόρτωση συνομιλιών"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Φόρτωση μηνυμάτων"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Προβολή περισσότερων συνομιλιών"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Εμφάνιση περισσότερων μηνυμάτων"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Η συνομιλία διαγράφηκε"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Διαγραφή συνομιλίας. Αγγίξτε για να εμφανίσετε μια διαφορετική συνομιλία στην Ανταλλαγή μηνυμάτων"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Αποκλείστηκε"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Ο αποκλεισμός καταργήθηκε"</string>
+    <string name="db_full" msgid="8459265782521418031">"Ο αποθηκευτικός χώρος είναι περιορισμένος. Ορισμένα στοιχεία ενδέχεται να χαθούν."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Επιλέξτε συνημμένα"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Επιβεβαίωση επιλογής"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> επιλ/μένα"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Καταργήστε ένα ή περισσότερα συνημμένα και δοκιμάστε ξανά."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Μπορείτε να δοκιμάσετε να στείλετε το μήνυμά σας, αλλά ενδέχεται να μην παραδοθεί αν δεν καταργήσετε ένα ή περισσότερα συνημμένα."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Μπορείτε να στείλετε μόνο ένα βίντεο ανά μήνυμα. Καταργήστε τα επιπλέον βίντεο και δοκιμάστε ξανά."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Αποτυχία φόρτωσης συνημμένου από την Ανταλλαγή μηνυμάτων."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Αποστολή ούτως ή άλλως"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Δεν ήταν δυνατή η έναρξη της συνομιλίας"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Επιλέχτηκε <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-en-rAU/arrays.xml b/res/values-en-rAU/arrays.xml
new file mode 100644
index 0000000..94d5aff
--- /dev/null
+++ b/res/values-en-rAU/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"no subject"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Yes"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Thanks"</item>
+    <item msgid="4881335087096496747">"I agree"</item>
+    <item msgid="2422296858597420738">"Nice"</item>
+    <item msgid="4805581752819452687">"On my way"</item>
+    <item msgid="4746700499431366214">"OK, let me get back to you later"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..3a642fb
--- /dev/null
+++ b/res/values-en-rAU/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messaging"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messaging"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Select conversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Settings"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Send Message"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Add an attachment"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Help"</string>
+    <string name="welcome" msgid="2857560951820802321">"Welcome"</string>
+    <string name="skip" msgid="7238879696319945853">"Skip"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Next &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Next"</string>
+    <string name="exit" msgid="1905187380359981199">"Exit"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Settings &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Settings"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging needs permission to SMS, Phone and Contacts."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"You can change permissions in Settings &gt; Apps &gt; Messaging &gt; Permissions."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"You can change permissions in Settings, Apps, Messaging, Permissions."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"All contacts"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Send to <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capture pictures or video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Choose images from this device"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Record audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Choose photo"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"The media is selected."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"The media is unselected."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"image <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"image"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Record audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Share"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Just now"</string>
+    <string name="posted_now" msgid="867560789350406701">"Now"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> mins</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hours</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hour</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> days</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> day</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> weeks</item>
+      <item quantity="one">a week</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> months</item>
+      <item quantity="one">a month</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> years</item>
+      <item quantity="one">a year</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 message"</string>
+    <string name="save" msgid="5081141452059463572">"Save"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Device is low on space. Messaging will automatically delete older messages to free up space."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Storage space running out"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaging might not send or receive messages until more space is available on your device."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Low SMS storage. You may need to delete messages."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirm your phone number"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"This one-off step will ensure Messaging will deliver your group messages properly."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Phone number"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Delete all messages with media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Auto-delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignore"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Delete all messages with media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g> and turn on auto-delete?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> said"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"You said"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Message from <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"You sent a message"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sending…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Not sent. Touch to try again."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Not sent. Trying again…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Resend or delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Please make a voice call to emergency services. Your text message could not be delivered at this time."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Failed"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"New MMS message to download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"New MMS message"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Couldn\'t download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Touch to try again"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Touch to download"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Download or delete"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Downloading…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Message expired or not available"</string>
+    <string name="mms_info" msgid="3402311750134118165">"size: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Can\'t send. Recipient not valid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Service not activated on network"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Couldn\'t send due to network problem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Message expired or not available"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(No subject)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Unknown sender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Delivered"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Couldn\'t download message <xliff:g id="SUBJECT">%1$s</xliff:g> from <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Couldn\'t complete database operation due to low memory"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Message not sent"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Some messages not sent in Messaging"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Message not downloaded"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Some messages not downloaded in Messaging"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Message to <xliff:g id="NUMBER">%1$s</xliff:g> not sent"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Please make a voice call to emergency services. Your text message to <xliff:g id="NUMBER">%1$s</xliff:g> could not be delivered at this time."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> new messages</item>
+      <item quantity="one">New message</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Start"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Camera not available"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Camera not available"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video capture not available"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Can\'t save media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Can\'t take picture"</string>
+    <string name="back" msgid="1477626055115561645">"Back"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archived"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Delete"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archive"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Unarchive"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Turn off notifications"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Turn on notifications"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Add contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"Download"</string>
+    <string name="action_send" msgid="377635240181672039">"Send"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Delete"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Delete this message"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"This action cannot be undone."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Delete"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Delete these conversations?</item>
+      <item quantity="one">Delete this conversation?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Delete"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancel"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"To"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Select multiple images"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirm selection"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Can\'t record audio. Try again."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Can\'t play audio. Try again."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Couldn\'t save audio. Try again."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Touch &amp; hold"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Picture"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio clip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Contact card"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Reply via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Reply via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Reply"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participant</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Me"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact blocked &amp; archived"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contact unblocked &amp; unarchived"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archived"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> unarchived"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifications turned off"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifications turned on"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"All set. Touch Send again."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaging successfully set as the default SMS app."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Discard attachments</item>
+      <item quantity="one">Discard attachment</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio attachment"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Play audio attachment"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Unsent message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sending message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Failed message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Unsent message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sending message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Failed message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Failed message. Touch to retry."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversation with <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Delete subject"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capture video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capture a still image"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Take picture"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Start recording video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Switch to full screen camera"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Switch between front and back camera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stop recording and attach video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stop recording video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging photos"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> photos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> photo saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> attachments saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved to \"Downloads\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Couldn\'t save <xliff:g id="QUANTITY_1">%d</xliff:g> attachments</item>
+      <item quantity="one">Couldn\'t save <xliff:g id="QUANTITY_0">%d</xliff:g> attachment</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Saved MMS attachment"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Settings"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archived"</string>
+    <string name="action_close" msgid="1840519376200478419">"Close"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Advanced"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifications"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sound"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silent"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrate"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blocked"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS delivery reports"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Request a delivery report for each SMS that you send"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Auto-retrieve"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatically retrieve MMS messages"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Roaming auto-retrieve"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatically retrieve MMS when roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Group messaging"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Use MMS to send a single message when there are multiple recipients"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Default SMS app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Default SMS app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Your phone number"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Unknown"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Outgoing message sounds"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Dump SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Dump received SMS raw data into external storage file"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Dump MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dump received MMS raw data into external storage file"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Wireless alerts"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Message options"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copy text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"View details"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Delete"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Forward"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Message details"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Text message"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia message"</string>
+    <string name="from_label" msgid="1947831848146564875">"From: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"To: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sent: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Received: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subject: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Size: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priority: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"High"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Low"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Hidden sender address"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Can\'t send message while loading attachments."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Can\'t load attachment. Try again."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Network is not ready. Try again."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Delete text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Switch between entering text and numbers"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Add more participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirm participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Start new conversation"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Select this item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Play video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"People &amp; Options"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"People &amp; Options"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"General"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"People in this conversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Make a call"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Send message"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Send message&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Send photos</item>
+      <item quantity="one">Send photo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Send audios</item>
+      <item quantity="one">Send audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Send videos</item>
+      <item quantity="one">Send video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Send contact cards</item>
+      <item quantity="one">Send contact card</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Send attachments</item>
+      <item quantity="one">Send attachment</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> attachments ready to send</item>
+      <item quantity="one">One attachment ready to send</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Send feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"View in Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Version info"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open-source licences"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifications"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Attachment limit reached"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Failed to load attachment."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Add to Contacts?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Add Contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subject"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subject: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Loading contact card"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Couldn\'t load contact card"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"View contact card"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacts</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Contact cards"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Birthday"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notes"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Forward message"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Reply"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS disabled"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"To send, set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Change"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"To receive messages, set Messaging as the default SMS app"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No preferred SIM selected for sending SMS messages"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"This app isn\'t allowed by the device owner."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Too many participants in a conversation"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Invalid contacts</item>
+      <item quantity="one">Invalid contact</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Couldn\'t load camera image"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"You: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draft"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Once you start a new conversation, you’ll see it listed here"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Archived conversations appear here"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Loading conversations…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Picture"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio clip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"In-stream video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Contact card"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Undo"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Retry"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Enter a contact name or phone number to start a new message"</string>
+    <string name="action_block" msgid="9032076625645190136">"Block"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Block <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Unblock <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Block <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"You\'ll continue to receive messages from this number but won\'t be notified anymore. This conversation will be archived."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blocked contacts"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"UNBLOCK"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blocked contacts"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Choose image from document library"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sending message"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Message sent"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobile data is turned off. Check your settings."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Can\'t send messages in Aeroplane mode"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Message could not be sent"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Message downloaded"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobile data is turned off. Check your settings."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Can\'t download messages in Aeroplane mode"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Message could not be downloaded"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"One"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Two"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Three"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Four"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Five"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Six"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Seven"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Eight"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nine"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Can\'t send message with <xliff:g id="CARRIERNAME">%1$s</xliff:g>, error <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Can\'t send message with unknown operator, error <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Message not sent: service not activated on network"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Message not sent: invalid destination address"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Message not sent: invalid message"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Message not sent: unsupported content"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Message not sent: unsupported message"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Message not sent: too large"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"New message"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"View"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Image"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Could not find an appropriate application"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Remove recipient"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"New message"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancel"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit access point"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Not set"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Named"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN type"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Delete APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"New APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Save"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Discard"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"The Name field can\'t be empty."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"The APN cannot be empty."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC field must be 3 digits."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC field must be 2 or 3 digits."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restoring default APN settings."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Reset to default"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Reset default APN settings completed"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Untitled"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Access point names"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"New APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Access Point Name settings are not available for this user"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copy to clipboard?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copy"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"to <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Advanced"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"General settings"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Advanced settings"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Send individual SMS messages to all recipients. Only you will get any replies"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Send a single MMS to all recipients"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Unknown number"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"New message"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"New message"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM selector"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> selected, SIM selector"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edit subject"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Select SIM or edit subject"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Touch and hold to record audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Start new conversation"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging List"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"New message"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Conversation list"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Loading conversations"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Loading messages"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"View more conversations"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"View more messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversation deleted"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversation deleted. Touch to show a different Messaging conversation"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blocked"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Unblocked"</string>
+    <string name="db_full" msgid="8459265782521418031">"Storage space is low. Some data may be lost."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Select attachments"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirm selection"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Please remove one or more attachments and try again."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"You can try sending your message, but it might not be delivered unless you remove one or more attachments."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"You can only send one video per message. Please remove additional videos and try again."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging failed to load attachment."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Send anyway"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Could not start conversation"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selected"</string>
+</resources>
diff --git a/res/values-en-rGB/arrays.xml b/res/values-en-rGB/arrays.xml
new file mode 100644
index 0000000..94d5aff
--- /dev/null
+++ b/res/values-en-rGB/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"no subject"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Yes"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Thanks"</item>
+    <item msgid="4881335087096496747">"I agree"</item>
+    <item msgid="2422296858597420738">"Nice"</item>
+    <item msgid="4805581752819452687">"On my way"</item>
+    <item msgid="4746700499431366214">"OK, let me get back to you later"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..3a642fb
--- /dev/null
+++ b/res/values-en-rGB/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messaging"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messaging"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Select conversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Settings"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Send Message"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Add an attachment"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Help"</string>
+    <string name="welcome" msgid="2857560951820802321">"Welcome"</string>
+    <string name="skip" msgid="7238879696319945853">"Skip"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Next &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Next"</string>
+    <string name="exit" msgid="1905187380359981199">"Exit"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Settings &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Settings"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging needs permission to SMS, Phone and Contacts."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"You can change permissions in Settings &gt; Apps &gt; Messaging &gt; Permissions."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"You can change permissions in Settings, Apps, Messaging, Permissions."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"All contacts"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Send to <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capture pictures or video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Choose images from this device"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Record audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Choose photo"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"The media is selected."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"The media is unselected."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"image <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"image"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Record audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Share"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Just now"</string>
+    <string name="posted_now" msgid="867560789350406701">"Now"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> mins</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hours</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hour</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> days</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> day</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> weeks</item>
+      <item quantity="one">a week</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> months</item>
+      <item quantity="one">a month</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> years</item>
+      <item quantity="one">a year</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 message"</string>
+    <string name="save" msgid="5081141452059463572">"Save"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Device is low on space. Messaging will automatically delete older messages to free up space."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Storage space running out"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaging might not send or receive messages until more space is available on your device."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Low SMS storage. You may need to delete messages."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirm your phone number"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"This one-off step will ensure Messaging will deliver your group messages properly."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Phone number"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Delete all messages with media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Auto-delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignore"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Delete all messages with media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g> and turn on auto-delete?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> said"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"You said"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Message from <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"You sent a message"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sending…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Not sent. Touch to try again."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Not sent. Trying again…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Resend or delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Please make a voice call to emergency services. Your text message could not be delivered at this time."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Failed"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"New MMS message to download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"New MMS message"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Couldn\'t download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Touch to try again"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Touch to download"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Download or delete"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Downloading…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Message expired or not available"</string>
+    <string name="mms_info" msgid="3402311750134118165">"size: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Can\'t send. Recipient not valid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Service not activated on network"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Couldn\'t send due to network problem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Message expired or not available"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(No subject)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Unknown sender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Delivered"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Couldn\'t download message <xliff:g id="SUBJECT">%1$s</xliff:g> from <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Couldn\'t complete database operation due to low memory"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Message not sent"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Some messages not sent in Messaging"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Message not downloaded"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Some messages not downloaded in Messaging"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Message to <xliff:g id="NUMBER">%1$s</xliff:g> not sent"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Please make a voice call to emergency services. Your text message to <xliff:g id="NUMBER">%1$s</xliff:g> could not be delivered at this time."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> new messages</item>
+      <item quantity="one">New message</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Start"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Camera not available"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Camera not available"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video capture not available"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Can\'t save media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Can\'t take picture"</string>
+    <string name="back" msgid="1477626055115561645">"Back"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archived"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Delete"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archive"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Unarchive"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Turn off notifications"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Turn on notifications"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Add contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"Download"</string>
+    <string name="action_send" msgid="377635240181672039">"Send"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Delete"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Delete this message"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"This action cannot be undone."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Delete"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Delete these conversations?</item>
+      <item quantity="one">Delete this conversation?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Delete"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancel"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"To"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Select multiple images"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirm selection"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Can\'t record audio. Try again."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Can\'t play audio. Try again."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Couldn\'t save audio. Try again."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Touch &amp; hold"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Picture"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio clip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Contact card"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Reply via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Reply via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Reply"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participant</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Me"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact blocked &amp; archived"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contact unblocked &amp; unarchived"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archived"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> unarchived"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifications turned off"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifications turned on"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"All set. Touch Send again."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaging successfully set as the default SMS app."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Discard attachments</item>
+      <item quantity="one">Discard attachment</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio attachment"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Play audio attachment"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Unsent message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sending message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Failed message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Unsent message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sending message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Failed message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Failed message. Touch to retry."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversation with <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Delete subject"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capture video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capture a still image"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Take picture"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Start recording video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Switch to full screen camera"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Switch between front and back camera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stop recording and attach video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stop recording video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging photos"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> photos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> photo saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> attachments saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved to \"Downloads\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Couldn\'t save <xliff:g id="QUANTITY_1">%d</xliff:g> attachments</item>
+      <item quantity="one">Couldn\'t save <xliff:g id="QUANTITY_0">%d</xliff:g> attachment</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Saved MMS attachment"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Settings"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archived"</string>
+    <string name="action_close" msgid="1840519376200478419">"Close"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Advanced"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifications"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sound"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silent"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrate"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blocked"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS delivery reports"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Request a delivery report for each SMS that you send"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Auto-retrieve"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatically retrieve MMS messages"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Roaming auto-retrieve"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatically retrieve MMS when roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Group messaging"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Use MMS to send a single message when there are multiple recipients"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Default SMS app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Default SMS app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Your phone number"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Unknown"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Outgoing message sounds"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Dump SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Dump received SMS raw data into external storage file"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Dump MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dump received MMS raw data into external storage file"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Wireless alerts"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Message options"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copy text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"View details"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Delete"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Forward"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Message details"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Text message"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia message"</string>
+    <string name="from_label" msgid="1947831848146564875">"From: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"To: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sent: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Received: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subject: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Size: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priority: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"High"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Low"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Hidden sender address"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Can\'t send message while loading attachments."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Can\'t load attachment. Try again."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Network is not ready. Try again."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Delete text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Switch between entering text and numbers"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Add more participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirm participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Start new conversation"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Select this item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Play video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"People &amp; Options"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"People &amp; Options"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"General"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"People in this conversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Make a call"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Send message"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Send message&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Send photos</item>
+      <item quantity="one">Send photo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Send audios</item>
+      <item quantity="one">Send audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Send videos</item>
+      <item quantity="one">Send video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Send contact cards</item>
+      <item quantity="one">Send contact card</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Send attachments</item>
+      <item quantity="one">Send attachment</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> attachments ready to send</item>
+      <item quantity="one">One attachment ready to send</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Send feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"View in Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Version info"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open-source licences"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifications"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Attachment limit reached"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Failed to load attachment."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Add to Contacts?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Add Contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subject"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subject: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Loading contact card"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Couldn\'t load contact card"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"View contact card"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacts</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Contact cards"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Birthday"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notes"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Forward message"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Reply"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS disabled"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"To send, set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Change"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"To receive messages, set Messaging as the default SMS app"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No preferred SIM selected for sending SMS messages"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"This app isn\'t allowed by the device owner."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Too many participants in a conversation"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Invalid contacts</item>
+      <item quantity="one">Invalid contact</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Couldn\'t load camera image"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"You: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draft"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Once you start a new conversation, you’ll see it listed here"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Archived conversations appear here"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Loading conversations…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Picture"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio clip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"In-stream video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Contact card"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Undo"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Retry"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Enter a contact name or phone number to start a new message"</string>
+    <string name="action_block" msgid="9032076625645190136">"Block"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Block <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Unblock <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Block <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"You\'ll continue to receive messages from this number but won\'t be notified anymore. This conversation will be archived."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blocked contacts"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"UNBLOCK"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blocked contacts"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Choose image from document library"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sending message"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Message sent"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobile data is turned off. Check your settings."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Can\'t send messages in Aeroplane mode"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Message could not be sent"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Message downloaded"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobile data is turned off. Check your settings."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Can\'t download messages in Aeroplane mode"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Message could not be downloaded"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"One"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Two"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Three"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Four"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Five"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Six"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Seven"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Eight"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nine"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Can\'t send message with <xliff:g id="CARRIERNAME">%1$s</xliff:g>, error <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Can\'t send message with unknown operator, error <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Message not sent: service not activated on network"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Message not sent: invalid destination address"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Message not sent: invalid message"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Message not sent: unsupported content"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Message not sent: unsupported message"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Message not sent: too large"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"New message"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"View"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Image"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Could not find an appropriate application"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Remove recipient"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"New message"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancel"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit access point"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Not set"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Named"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN type"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Delete APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"New APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Save"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Discard"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"The Name field can\'t be empty."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"The APN cannot be empty."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC field must be 3 digits."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC field must be 2 or 3 digits."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restoring default APN settings."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Reset to default"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Reset default APN settings completed"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Untitled"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Access point names"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"New APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Access Point Name settings are not available for this user"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copy to clipboard?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copy"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"to <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Advanced"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"General settings"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Advanced settings"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Send individual SMS messages to all recipients. Only you will get any replies"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Send a single MMS to all recipients"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Unknown number"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"New message"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"New message"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM selector"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> selected, SIM selector"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edit subject"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Select SIM or edit subject"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Touch and hold to record audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Start new conversation"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging List"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"New message"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Conversation list"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Loading conversations"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Loading messages"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"View more conversations"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"View more messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversation deleted"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversation deleted. Touch to show a different Messaging conversation"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blocked"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Unblocked"</string>
+    <string name="db_full" msgid="8459265782521418031">"Storage space is low. Some data may be lost."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Select attachments"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirm selection"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Please remove one or more attachments and try again."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"You can try sending your message, but it might not be delivered unless you remove one or more attachments."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"You can only send one video per message. Please remove additional videos and try again."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging failed to load attachment."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Send anyway"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Could not start conversation"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selected"</string>
+</resources>
diff --git a/res/values-en-rIN/arrays.xml b/res/values-en-rIN/arrays.xml
new file mode 100644
index 0000000..94d5aff
--- /dev/null
+++ b/res/values-en-rIN/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"no subject"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Yes"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Thanks"</item>
+    <item msgid="4881335087096496747">"I agree"</item>
+    <item msgid="2422296858597420738">"Nice"</item>
+    <item msgid="4805581752819452687">"On my way"</item>
+    <item msgid="4746700499431366214">"OK, let me get back to you later"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..3a642fb
--- /dev/null
+++ b/res/values-en-rIN/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messaging"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messaging"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Select conversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Settings"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Send Message"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Add an attachment"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Help"</string>
+    <string name="welcome" msgid="2857560951820802321">"Welcome"</string>
+    <string name="skip" msgid="7238879696319945853">"Skip"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Next &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Next"</string>
+    <string name="exit" msgid="1905187380359981199">"Exit"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Settings &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Settings"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging needs permission to SMS, Phone and Contacts."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"You can change permissions in Settings &gt; Apps &gt; Messaging &gt; Permissions."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"You can change permissions in Settings, Apps, Messaging, Permissions."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"All contacts"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Send to <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capture pictures or video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Choose images from this device"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Record audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Choose photo"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"The media is selected."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"The media is unselected."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"image <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"image"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Record audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Share"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Just now"</string>
+    <string name="posted_now" msgid="867560789350406701">"Now"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> mins</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hours</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hour</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> days</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> day</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> weeks</item>
+      <item quantity="one">a week</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> months</item>
+      <item quantity="one">a month</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> years</item>
+      <item quantity="one">a year</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 message"</string>
+    <string name="save" msgid="5081141452059463572">"Save"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Device is low on space. Messaging will automatically delete older messages to free up space."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Storage space running out"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaging might not send or receive messages until more space is available on your device."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Low SMS storage. You may need to delete messages."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirm your phone number"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"This one-off step will ensure Messaging will deliver your group messages properly."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Phone number"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Delete all messages with media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Auto-delete messages older than <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignore"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Delete all messages with media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Delete messages older than <xliff:g id="DURATION">%s</xliff:g> and turn on auto-delete?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> said"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"You said"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Message from <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"You sent a message"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sending…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Not sent. Touch to try again."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Not sent. Trying again…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Resend or delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Please make a voice call to emergency services. Your text message could not be delivered at this time."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Failed"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"New MMS message to download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"New MMS message"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Couldn\'t download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Touch to try again"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Touch to download"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Download or delete"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Downloading…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Message expired or not available"</string>
+    <string name="mms_info" msgid="3402311750134118165">"size: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Can\'t send. Recipient not valid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Service not activated on network"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Couldn\'t send due to network problem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Message expired or not available"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(No subject)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Unknown sender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Delivered"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Couldn\'t download message <xliff:g id="SUBJECT">%1$s</xliff:g> from <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Couldn\'t complete database operation due to low memory"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Message not sent"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Some messages not sent in Messaging"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Message not downloaded"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Some messages not downloaded in Messaging"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messages in one conversation</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Message to <xliff:g id="NUMBER">%1$s</xliff:g> not sent"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Please make a voice call to emergency services. Your text message to <xliff:g id="NUMBER">%1$s</xliff:g> could not be delivered at this time."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> new messages</item>
+      <item quantity="one">New message</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Start"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Camera not available"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Camera not available"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video capture not available"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Can\'t save media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Can\'t take picture"</string>
+    <string name="back" msgid="1477626055115561645">"Back"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archived"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Delete"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archive"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Unarchive"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Turn off notifications"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Turn on notifications"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Add contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"Download"</string>
+    <string name="action_send" msgid="377635240181672039">"Send"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Delete"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Delete this message"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"This action cannot be undone."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Delete"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Delete these conversations?</item>
+      <item quantity="one">Delete this conversation?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Delete"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancel"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"To"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Select multiple images"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirm selection"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Can\'t record audio. Try again."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Can\'t play audio. Try again."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Couldn\'t save audio. Try again."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Touch &amp; hold"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Picture"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio clip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Contact card"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Reply via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Reply via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Reply"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participant</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Me"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact blocked &amp; archived"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contact unblocked &amp; unarchived"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archived"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> unarchived"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifications turned off"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifications turned on"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"All set. Touch Send again."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaging successfully set as the default SMS app."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Discard attachments</item>
+      <item quantity="one">Discard attachment</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio attachment"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Play audio attachment"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Unsent message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sending message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Failed message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Message to <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Failed message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Message from <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Unsent message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sending message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Failed message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Message to <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Failed message. Touch to retry."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversation with <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Delete subject"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capture video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capture a still image"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Take picture"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Start recording video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Switch to full screen camera"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Switch between front and back camera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stop recording and attach video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stop recording video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging photos"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> photos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> photo saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videos saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> attachments saved to \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" album</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved to \"Downloads\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved to \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> attachments saved</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> attachment saved</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Couldn\'t save <xliff:g id="QUANTITY_1">%d</xliff:g> attachments</item>
+      <item quantity="one">Couldn\'t save <xliff:g id="QUANTITY_0">%d</xliff:g> attachment</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Saved MMS attachment"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Settings"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archived"</string>
+    <string name="action_close" msgid="1840519376200478419">"Close"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Advanced"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifications"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sound"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silent"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrate"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blocked"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS delivery reports"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Request a delivery report for each SMS that you send"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Auto-retrieve"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatically retrieve MMS messages"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Roaming auto-retrieve"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatically retrieve MMS when roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Group messaging"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Use MMS to send a single message when there are multiple recipients"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Default SMS app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Default SMS app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Your phone number"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Unknown"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Outgoing message sounds"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Dump SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Dump received SMS raw data into external storage file"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Dump MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dump received MMS raw data into external storage file"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Wireless alerts"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Message options"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copy text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"View details"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Delete"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Forward"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Message details"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Text message"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia message"</string>
+    <string name="from_label" msgid="1947831848146564875">"From: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"To: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sent: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Received: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subject: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Size: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priority: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"High"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Low"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Hidden sender address"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Can\'t send message while loading attachments."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Can\'t load attachment. Try again."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Network is not ready. Try again."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Delete text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Switch between entering text and numbers"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Add more participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirm participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Start new conversation"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Select this item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Play video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"People &amp; Options"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"People &amp; Options"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"General"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"People in this conversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Make a call"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Send message"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Send message&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Send photos</item>
+      <item quantity="one">Send photo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Send audios</item>
+      <item quantity="one">Send audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Send videos</item>
+      <item quantity="one">Send video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Send contact cards</item>
+      <item quantity="one">Send contact card</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Send attachments</item>
+      <item quantity="one">Send attachment</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> attachments ready to send</item>
+      <item quantity="one">One attachment ready to send</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Send feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"View in Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Version info"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open-source licences"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifications"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Attachment limit reached"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Failed to load attachment."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Add to Contacts?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Add Contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subject"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subject: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Loading contact card"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Couldn\'t load contact card"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"View contact card"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacts</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Contact cards"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Birthday"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notes"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Forward message"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Reply"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS disabled"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"To send, set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Set Messaging as the default SMS app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Change"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"To receive messages, set Messaging as the default SMS app"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No preferred SIM selected for sending SMS messages"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"This app isn\'t allowed by the device owner."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Too many participants in a conversation"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Invalid contacts</item>
+      <item quantity="one">Invalid contact</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Couldn\'t load camera image"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"You: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draft"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Once you start a new conversation, you’ll see it listed here"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Archived conversations appear here"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Loading conversations…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Picture"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio clip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"In-stream video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Contact card"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Undo"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Retry"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Enter a contact name or phone number to start a new message"</string>
+    <string name="action_block" msgid="9032076625645190136">"Block"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Block <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Unblock <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Block <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"You\'ll continue to receive messages from this number but won\'t be notified anymore. This conversation will be archived."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blocked contacts"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"UNBLOCK"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blocked contacts"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Choose image from document library"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sending message"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Message sent"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobile data is turned off. Check your settings."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Can\'t send messages in Aeroplane mode"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Message could not be sent"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Message downloaded"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobile data is turned off. Check your settings."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Can\'t download messages in Aeroplane mode"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Message could not be downloaded"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"One"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Two"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Three"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Four"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Five"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Six"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Seven"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Eight"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nine"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Can\'t send message with <xliff:g id="CARRIERNAME">%1$s</xliff:g>, error <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Can\'t send message with unknown operator, error <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Message not sent: service not activated on network"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Message not sent: invalid destination address"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Message not sent: invalid message"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Message not sent: unsupported content"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Message not sent: unsupported message"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Message not sent: too large"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"New message"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"View"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Image"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Could not find an appropriate application"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Remove recipient"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"New message"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancel"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit access point"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Not set"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Named"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN type"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Delete APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"New APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Save"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Discard"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"The Name field can\'t be empty."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"The APN cannot be empty."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC field must be 3 digits."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC field must be 2 or 3 digits."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restoring default APN settings."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Reset to default"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Reset default APN settings completed"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Untitled"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Access point names"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"New APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Access Point Name settings are not available for this user"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copy to clipboard?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copy"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"to <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Advanced"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"General settings"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Advanced settings"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Send individual SMS messages to all recipients. Only you will get any replies"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Send a single MMS to all recipients"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Unknown number"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"New message"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"New message"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM selector"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> selected, SIM selector"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edit subject"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Select SIM or edit subject"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Touch and hold to record audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Start new conversation"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging List"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"New message"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Conversation list"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Loading conversations"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Loading messages"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"View more conversations"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"View more messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversation deleted"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversation deleted. Touch to show a different Messaging conversation"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blocked"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Unblocked"</string>
+    <string name="db_full" msgid="8459265782521418031">"Storage space is low. Some data may be lost."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Select attachments"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirm selection"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selected"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Please remove one or more attachments and try again."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"You can try sending your message, but it might not be delivered unless you remove one or more attachments."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"You can only send one video per message. Please remove additional videos and try again."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging failed to load attachment."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Send anyway"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Could not start conversation"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selected"</string>
+</resources>
diff --git a/res/values-es-rUS/arrays.xml b/res/values-es-rUS/arrays.xml
new file mode 100644
index 0000000..4a3fbb7
--- /dev/null
+++ b/res/values-es-rUS/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sin asunto"</item>
+    <item msgid="272485471009191934">"sinasunto"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sí"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"Aceptar"</item>
+    <item msgid="3155097332660174689">"Je, je"</item>
+    <item msgid="2611328818571146775">"Gracias"</item>
+    <item msgid="4881335087096496747">"Acepto"</item>
+    <item msgid="2422296858597420738">"Genial"</item>
+    <item msgid="4805581752819452687">"Estoy en camino."</item>
+    <item msgid="4746700499431366214">"De acuerdo, te llamo más tarde."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..f474514
--- /dev/null
+++ b/res/values-es-rUS/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Centro de mensajes"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Centro de mensajes"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Seleccionar conversación"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Configuración"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Enviar mensaje"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Agregar un archivo adjunto"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ayuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Te damos la bienvenida"</string>
+    <string name="skip" msgid="7238879696319945853">"Omitir"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Siguiente &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Siguiente"</string>
+    <string name="exit" msgid="1905187380359981199">"Salir"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Configuración &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Configuración"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Centro de Mensajes necesita permiso para acceder a SMS, Teléfono y Contactos."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Puedes cambiar los permisos en Configuración &gt; Aplicaciones &gt; Centro de Mensajes &gt; Permisos."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Puedes cambiar los permisos en Configuración, Aplicaciones, Centro de Mensajes, Permisos."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frecuentes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Todos los contactos"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Enviar a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capturar imágenes o video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Seleccionar imágenes de este dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Grabar audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Elegir foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"El medio está seleccionado."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Los medios no están seleccionados."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Seleccionado: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imagen <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imagen"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Grabar audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Compartir"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Recién"</string>
+    <string name="posted_now" msgid="867560789350406701">"Recién"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> días</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> día</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+      <item quantity="one">una semana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+      <item quantity="one">un mes</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> años</item>
+      <item quantity="one">un año</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mensaje clase 0"</string>
+    <string name="save" msgid="5081141452059463572">"Guardar"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"El dispositivo tiene poco espacio de almacenamiento. El Centro de Mensajes borrará automáticamente los mensajes antiguos para liberar espacio."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Queda poco espacio de almacenamiento"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Es posible que Centro de Mensajes no envíe ni reciba mensajes hasta que se libere más espacio en el dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Como queda poco espacio para SMS, tal vez debas eliminar mensajes."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirmar tu número de teléfono"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Este paso, que se realiza por única vez, asegurará que Centro de Mensajes envíe los mensajes grupales de forma correcta."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de teléfono"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Eliminar todos los mensajes con contenido multimedia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Eliminar mensajes de más de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Eliminar automáticamente mensajes de más de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorar"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"¿Eliminar todos los mensajes con contenido multimedia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"¿Eliminar mensajes de más de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"¿Eliminar mensajes de más de <xliff:g id="DURATION">%s</xliff:g> y activar la eliminación automática?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> dijo"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Tú dijiste"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensaje de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Enviaste un mensaje"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Enviando…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"El mensaje no se envió. Toca para volver a intentarlo."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"El mensaje no se envió. Reintentando…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Volver a enviar o eliminar"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Realiza una llamada de voz a los servicios de emergencia. No se pudo enviar el mensaje de texto esta vez."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Error"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nuevo mensaje MMS para descargar"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nuevo mensaje MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"El mensaje no se pudo descargar."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Toca para volver a intentarlo."</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Toca para descargar."</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Descargar o eliminar"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Descargando…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"El mensaje venció o no está disponible."</string>
+    <string name="mms_info" msgid="3402311750134118165">"tamaño: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>; vencimiento: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"No se puede enviar porque el destinatario no es válido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"No se activó el servicio en la red."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"No se pudo enviar debido a un problema de la red."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"El mensaje venció o no está disponible."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sin asunto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Remitente desconocido"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregado"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"No se pudo descargar el mensaje <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"No se pudo completar la operación de la base de datos por falta de memoria."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mensaje no enviado"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"No se pudieron enviar algunos mensajes en Centro de Mensajes"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensajes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversaciones</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensajes en una conversación</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mensaje no descargado"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"No se pudieron descargar algunos mensajes en Centro de Mensajes"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensajes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversaciones</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensaje en una conversación</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mensaje al <xliff:g id="NUMBER">%1$s</xliff:g> no enviado"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Realiza una llamada de voz a los servicios de emergencia. No se pudo enviar el mensaje de texto a <xliff:g id="NUMBER">%1$s</xliff:g> esta vez."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mensajes nuevos</item>
+      <item quantity="one">Un mensaje nuevo</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Iniciar"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Cámara no disponible"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Cámara no disponible"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Captura de video no disponible"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"No se puede guardar el contenido multimedia."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"No se puede tomar la foto."</string>
+    <string name="back" msgid="1477626055115561645">"Atrás"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivadas"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Eliminar"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivo"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Eliminar del archivo"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desactivar notificaciones"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activar notificaciones"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Agregar contacto"</string>
+    <string name="action_download" msgid="7786338136368564146">"Descargar"</string>
+    <string name="action_send" msgid="377635240181672039">"Enviar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Eliminar"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"¿Deseas eliminar este mensaje?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Esta acción no se puede deshacer."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Eliminar"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">¿Deseas borrar estas conversaciones?</item>
+      <item quantity="one">¿Deseas borrar esta conversación?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Eliminar"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancelar"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Seleccionar varias imágenes"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmar selección"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"<xliff:g id="COUNT">%d</xliff:g> más"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"No se puede grabar el audio. Vuelve a intentarlo."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"No se puede reproducir el audio. Vuelve a intentarlo."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"No se pudo guardar el audio. Vuelve a intentarlo."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Mantener presionado"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imagen"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip de audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Tarjeta de contacto"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Descargar"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Responder con SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Responder (MMS)"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Responder"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participante</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Yo"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contacto bloqueado y archivado"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contacto desbloqueado y sin archivar"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archivada(s)"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> no archivada(s)"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificaciones desactivadas"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificaciones activadas"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Todo listo. Vuelve a tocar Enviar."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Se estableció de forma correcta Centro de Mensajes como tu aplicación de SMS predeterminada."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Descartar archivos adjuntos</item>
+      <item quantity="one">Descartar archivo adjunto</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Archivo adjunto de audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproducir archivo adjunto de audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausa"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Error del mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mensaje no enviado a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Enviando mensaje a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Error de mensaje a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensaje a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Error del mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g> <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g> <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mensaje no enviado a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Enviando mensaje a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Error del mensaje a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensaje a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Se produjo un error en el mensaje. Toca para volver a intentarlo."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversación con <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Eliminar asunto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capturar video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturar una imagen fija"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Tomar fotografía"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Iniciar grabación de video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Cambiar a cámara en pantalla completa"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Alternar entre cámara frontal y trasera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Detener la grabación y adjuntar video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Detener la grabación de video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos de Centro de Mensajes"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">Se guardaron <xliff:g id="QUANTITY_2">%d</xliff:g> fotos en el álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Se guardó <xliff:g id="QUANTITY_0">%d</xliff:g> foto en el álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">Se guardaron <xliff:g id="QUANTITY_2">%d</xliff:g> videos en el álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Se guardó <xliff:g id="QUANTITY_0">%d</xliff:g> video en el álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">Se guardaron <xliff:g id="QUANTITY_2">%d</xliff:g> archivos adjuntos en el álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Se guardó <xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto en el álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">Se guardaron <xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos en \"Descargas\"</item>
+      <item quantity="one">Se guardó <xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto en \"Descargas\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Se guardaron <xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos</item>
+      <item quantity="one">Se guardó <xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">No se pudieron guardar <xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos</item>
+      <item quantity="one">No se pudo guardar <xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Archivo adjunto de MMS guardado"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Configuración"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivadas"</string>
+    <string name="action_close" msgid="1840519376200478419">"Cerrar"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avanzada"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depurar"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificaciones"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sonido"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silencio"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqueado"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Informes de entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicitar un informe de entrega al enviar un SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperación automática"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recuperar mensajes MMS automáticamente"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recuperación automática en roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recuperar MMS automáticamente en roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mensajes grupales"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utiliza MMS para enviar un mismo mensaje a varios destinatarios."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicación de SMS predeterminada"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicación de SMS predeterminada"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Tu número de teléfono"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Desconocido"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sonidos de mensaje saliente"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Volcar SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Volcar datos sin procesar de SMS en el archivo de almacenamiento externo"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Volcar MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Volcar datos sin procesar de MMS recibidos en un archivo de almacenamiento externo"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertas inalámbricas"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opciones de mensaje"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiar el texto"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ver detalles"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Eliminar"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Reenviar"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalles del mensaje"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mensaje de texto"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mensaje multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Para: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviado: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Fecha de recepción: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Asunto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamaño: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioridad: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baja"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Dirección de remitente oculta"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"No se pueden enviar mensajes mientras se cargan adjuntos."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"No se puede cargar el archivo adjunto. Vuelve a intentarlo."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"La red no está lista. Vuelve a intentarlo."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Suprimir texto"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Cambiar entre ingresar texto y números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Agregar más participantes"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmar participantes"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Comenzar una nueva conversación"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Seleccionar este elemento"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproducir video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Contactos y opciones"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depurar"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Contactos y opciones"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"General"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Contactos en esta conversación"</string>
+    <string name="action_call" msgid="6596167921517350362">"Hacer una llamada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Enviar mensaje"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Enviar mensaje&lt;br/&gt;&lt;small&gt;de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Enviar fotos</item>
+      <item quantity="one">Enviar foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Enviar audios</item>
+      <item quantity="one">Enviar audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Enviar videos</item>
+      <item quantity="one">Enviar video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Enviar tarjetas de contacto</item>
+      <item quantity="one">Enviar tarjeta de contacto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Enviar archivos adjuntos</item>
+      <item quantity="one">Enviar archivo adjunto</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> archivos adjuntos listos para enviar</item>
+      <item quantity="one">Un archivo adjunto listo para enviar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Enviar comentarios"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ver en Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Información de la versión"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versión %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licencias de código abierto"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificaciones"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Se alcanzó el límite de archivos adjuntos."</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Se produjo un error al cargar el archivo adjunto."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"¿Agregar a contactos?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Agregar contacto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Asunto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Asunto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Cargando tarjeta de contacto"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"No se pudo cargar la tarjeta de contacto."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ver tarjeta de contacto"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contactos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contacto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Tarjetas de contactos"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Fecha de nacimiento"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Reenviar mensaje"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Responder"</string>
+    <string name="plus_one" msgid="9010288417554932581">"Hacer +1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS inhabilitados"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Establecer Centro de mensajes como la aplicación de SMS predeterminada para enviar mensajes"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Establecer Centro de Mensajes como la aplicación de SMS predeterminada"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Cambiar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Establecer Centro de mensajes como la aplicación de SMS predeterminada para recibir mensajes"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No se seleccionó ninguna SIM preferida para el envío de mensajes SMS."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"El propietario del dispositivo no permite esta aplicación."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Aceptar"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Demasiados participantes en una conversación"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Contactos no válidos</item>
+      <item quantity="one">Contacto no válido</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"No se pudo cargar la imagen de la cámara."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Tú: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Borrador"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Cuando inicies una conversación nueva, aparecerá aquí."</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Las conversaciones archivadas aparecen aquí."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Cargando conversaciones…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imagen"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip de audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Tarjeta de contacto"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Deshacer"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Volver a intentar"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Ingresa un nombre de contacto o número de teléfono para crear un nuevo mensaje."</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquear"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquear a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloquear a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"¿Bloquear a <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Seguirás recibiendo mensajes de este número, pero no verás notificaciones. Esta conversación se archivará."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contactos bloqueados"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEAR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contactos bloqueados"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Seleccionar imagen de la galería de documentos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Enviando el mensaje"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Se envió el mensaje."</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Los datos móviles están desactivados. Comprueba la configuración."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"No se pueden enviar mensajes en modo de avión."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"No se pudo enviar el mensaje."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Se descargó el mensaje."</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Los datos móviles están desactivados. Comprueba la configuración."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"No se pueden descargar mensajes en modo de avión."</string>
+    <string name="download_message_failure" msgid="635370887537738004">"No se pudo descargar el mensaje."</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Cero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Uno"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dos"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tres"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Cuatro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinco"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Siete"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Ocho"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nueve"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Error <xliff:g id="ERRORCODE">%2$d</xliff:g>. No se puede enviar el mensaje con <xliff:g id="CARRIERNAME">%1$s</xliff:g>."</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Error <xliff:g id="ERRORCODE">%1$d</xliff:g>. No se puede enviar el mensaje con un proveedor desconocido."</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Rv: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"No se envió el mensaje porque el servicio no está activado en la red."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mensaje no enviado: dirección de destino no válida"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mensaje no enviado: mensaje no válido"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mensaje no enviado: contenido no admitido"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mensaje no enviado: mensaje no admitido"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mensaje no enviado: demasiado largo"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mensaje nuevo"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ver"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imagen"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"No se pudo encontrar una aplicación adecuada."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Eliminar destinatario"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mensaje nuevo"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancelar"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editar el punto de acceso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Sin establecer"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nombre"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy de MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Puerto MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo de APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Eliminar APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN nuevo"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Guardar"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Descartar"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"El campo Nombre no puede estar vacío."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"El APN no puede estar vacío."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"El campo de MCC debe contener tres dígitos."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"El campo MNC debe contener dos o tres dígitos."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restaurando la configuración APN predeterminada"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Restablecer parámetros predeterminados"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Se restableció la configuración predeterminada de APN."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sin título"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nombres de puntos de acceso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN nuevo"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"La configuración del nombre de punto de acceso no está disponible para este usuario."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"¿Copiar en el portapapeles?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiar"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"a <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avanzada"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Configuración general"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Configuración avanzada"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Enviar mensajes de SMS individuales a todos los destinatarios (solo tú recibirás las respuestas)."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Enviar un único MMS a todos los destinatarios"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número desconocido"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mensaje nuevo"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mensaje nuevo"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selector de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Se seleccionó <xliff:g id="SIM_0">%1$s</xliff:g>, selector de SIM."</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editar asunto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Seleccionar SIM o editar asunto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Mantén presionado para grabar audio."</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Comenzar una nueva conversación"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Centro de mensajes"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista de Centro de Mensajes"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Centro de mensajes"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mensaje nuevo"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversaciones"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Cargando conversaciones"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Cargando mensajes…"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ver más conversaciones"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ver más mensajes"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Se eliminó la conversación."</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Se borró la conversación. Toca para mostrar otra conversación de Centro de Mensajes"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqueado"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desbloqueado"</string>
+    <string name="db_full" msgid="8459265782521418031">"Hay poco espacio de almacenamiento. Podrían perderse algunos datos."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Seleccionar archivos adjuntos"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmar selección"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Seleccionado: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Elimina uno o más archivos adjuntos y vuelve a intentarlo."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Puedes intentar enviar el mensaje, pero podría no enviarse a menos que elimines uno más archivos adjuntos."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Solo puedes enviar un video por mensaje. Quita los videos adicionales y vuelve a intentarlo."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Centro de Mensajes no pudo cargar el archivo adjunto."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Enviar de todas formas"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"No se pudo iniciar la conversación."</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Se seleccionó <xliff:g id="SELECTED_SIM">%s</xliff:g>."</string>
+</resources>
diff --git a/res/values-es/arrays.xml b/res/values-es/arrays.xml
new file mode 100644
index 0000000..ca8e06b
--- /dev/null
+++ b/res/values-es/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sin asunto"</item>
+    <item msgid="272485471009191934">"sinasunto"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sí"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"Ok"</item>
+    <item msgid="3155097332660174689">"Je, je"</item>
+    <item msgid="2611328818571146775">"Gracias"</item>
+    <item msgid="4881335087096496747">"Acepto"</item>
+    <item msgid="2422296858597420738">"Genial"</item>
+    <item msgid="4805581752819452687">"Voy de camino"</item>
+    <item msgid="4746700499431366214">"Vale, te llamo más tarde"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
new file mode 100644
index 0000000..98e0a1d
--- /dev/null
+++ b/res/values-es/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mensajes"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mensajes"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Seleccionar conversación"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ajustes"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Enviar mensaje"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Adjuntar un archivo"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ayuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Te damos la bienvenida"</string>
+    <string name="skip" msgid="7238879696319945853">"Saltar"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Siguiente &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Siguiente"</string>
+    <string name="exit" msgid="1905187380359981199">"Salir"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Ajustes &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ajustes"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mensajes necesita permiso para acceder a los SMS, al teléfono y a los contactos."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Puedes cambiar los permisos en Ajustes &gt; Aplicaciones &gt; Mensajes &gt; Permisos."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Puedes cambiar los permisos en Ajustes, Aplicaciones, Mensajes, Permisos."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frecuentes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Todos los contactos"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Enviar a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capturar imágenes o vídeo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Seleccionar imágenes de este dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Grabar audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Elegir foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Contenido multimedia seleccionado."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Contenido multimedia no seleccionado."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Seleccionado: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imagen del <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imagen"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Grabar audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Compartir"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Ahora mismo"</string>
+    <string name="posted_now" msgid="867560789350406701">"Ahora"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> días</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> día</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+      <item quantity="one">una semana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+      <item quantity="one">un mes</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> años</item>
+      <item quantity="one">un año</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mensaje de clase 0"</string>
+    <string name="save" msgid="5081141452059463572">"Guardar"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Casi no queda espacio en el dispositivo. La aplicación Mensajes eliminará automáticamente los mensajes más antiguos para liberar espacio."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Queda poco espacio"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Es posible que Mensajes no envíe ni reciba mensajes hasta que haya más espacio disponible en el dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Queda poco espacio para recibir SMS. Es posible que tengas que eliminar mensajes."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirma tu número de teléfono"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Este paso único garantiza que Mensajes enviará tus mensajes de grupo correctamente."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de teléfono"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Eliminar todos los mensajes con archivos multimedia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Eliminar mensajes anteriores a <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Eliminar automáticamente mensajes anteriores a <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorar"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"¿Eliminar todos los mensajes con archivos multimedia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"¿Eliminar mensajes anteriores a <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"¿Eliminar mensajes anteriores a <xliff:g id="DURATION">%s</xliff:g> y activar eliminación automática?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ha dicho"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Has dicho"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensaje de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Has enviado un mensaje"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Enviando..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"No enviado. Toca para volver a intentarlo."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"No enviado. Volviendo a intentar…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Volver a enviar o eliminar"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Llama a los servicios de emergencias. Tu mensaje de texto no se puede entregar en estos momentos."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Error"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nuevo mensaje MMS que descargar"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nuevo mensaje MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Error al descargar"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Toca para volver a intentarlo"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Toca para descargar"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Descargar o eliminar"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Descargando..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"El mensaje ha caducado o no está disponible"</string>
+    <string name="mms_info" msgid="3402311750134118165">"tamaño: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, vencimiento: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"No se puede enviar porque el destinatario no es válido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"No se ha activado el servicio en la red"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"No se ha podido enviar por un problema de red"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"El mensaje ha caducado o no está disponible"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sin asunto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Destinatario desconocido"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregado"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"No se ha podido descargar el mensaje <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"No se ha podido completar la operación de la base de datos por falta de memoria"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mensaje no enviado"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Hay algunos mensajes no enviados en Mensajes"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensajes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversaciones</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensajes en una conversación</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mensaje no descargado"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Algunos mensajes no se han descargado en Mensajes"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensajes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversaciones</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensajes en una conversación</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mensaje para <xliff:g id="NUMBER">%1$s</xliff:g> no enviado"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Llama a los servicios de emergencias. Tu mensaje de texto enviado al número <xliff:g id="NUMBER">%1$s</xliff:g> no se puede entregar en estos momentos."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mensajes nuevos</item>
+      <item quantity="one">Mensaje nuevo</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Iniciar"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Cámara no disponible"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Cámara no disponible"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Captura de vídeo no disponible"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"No se puede guardar el archivo multimedia"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"No se pueden hacer fotos"</string>
+    <string name="back" msgid="1477626055115561645">"Atrás"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivado"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Eliminar"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivar"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"No archivar"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desactivar notificaciones"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activar notificaciones"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Añadir contacto"</string>
+    <string name="action_download" msgid="7786338136368564146">"Descargar"</string>
+    <string name="action_send" msgid="377635240181672039">"Enviar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Eliminar"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"¿Eliminar este mensaje?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Esta acción no se puede deshacer."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Eliminar"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">¿Eliminar estas conversaciones?</item>
+      <item quantity="one">¿Eliminar esta conversación?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Eliminar"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancelar"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Seleccionar varias imágenes"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmar selección"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"No se puede grabar el audio. Vuelve a intentarlo."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"No se puede reproducir el audio. Vuelve a intentarlo."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"No se ha podido guardar el audio. Vuelve a intentarlo."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Mantener pulsado"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imagen"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Fragmento de audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vídeo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Tarjeta de contacto"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Descargar"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Responder con SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Responder por MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Responder"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participante</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Yo"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contacto bloqueado y archivado"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contacto desbloqueado y no archivado"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archivadas"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> no archivadas"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificaciones desactivadas"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificaciones activadas"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Listo. Toca Enviar de nuevo."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mensajes establecida como aplicación de SMS predeterminada."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Descartar archivos adjuntos</item>
+      <item quantity="one">Descartar archivo adjunto</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Archivo de audio adjunto"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproducir archivo de audio adjunto"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausar"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Error del mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mensaje no enviado a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Enviando mensaje a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Error del mensaje para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensaje para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Error del mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensaje de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mensaje no enviado a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Enviando mensaje a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Error del mensaje para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensaje para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Error del mensaje. Toca para volver a intentarlo."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversación con <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Eliminar asunto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capturar vídeo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturar una imagen fija"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Hacer foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Iniciar grabación de vídeo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Cambiar a cámara en pantalla completa"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Cambiar de la cámara frontal a la trasera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Dejar de grabar y adjuntar vídeo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Detener grabación de vídeo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos de Mensajes"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotos guardadas en el álbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto guardada en el álbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vídeos guardados en el álbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> vídeo guardado en el álbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> archivos adjuntos guardados en el álbum <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto guardado en el álbum <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos guardados en Descargas</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto guardado en Descargas</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos guardados</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto guardado</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">No se han podido guardar <xliff:g id="QUANTITY_1">%d</xliff:g> archivos adjuntos</item>
+      <item quantity="one">No se ha podido guardar <xliff:g id="QUANTITY_0">%d</xliff:g> archivo adjunto</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Adjunto de MMS guardado"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ajustes"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivado"</string>
+    <string name="action_close" msgid="1840519376200478419">"Cerrar"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Opciones avanzadas"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depurar"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificaciones"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sonido"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silencio"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqueado"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Informes de entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicitar un informe de entrega al enviar un SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperar automáticamente"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recuperar automáticamente mensajes MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Autorrecuperar en itinerancia"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recuperar MMS automáticamente en itinerancia"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mensaje de grupo"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Usar MMS para enviar un único mensaje a varios destinatarios"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicación de SMS predeterminada"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicación de SMS predeterminada"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Tu número de teléfono"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Desconocido"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sonidos de mensajes enviados"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Volcar SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Volcar datos sin procesar de SMS recibidos en un archivo del almacenamiento externo"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Volcar MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Volcar datos sin procesar de MMS recibidos en un archivo del almacenamiento externo"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertas inalámbricas"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opciones de mensaje"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiar texto"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ver detalles"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Eliminar"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Reenviar"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalles de mensaje"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mensaje de texto"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mensaje multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"A: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviado: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Recibido: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Asunto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamaño: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioridad: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baja"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Dirección de remitente oculta"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"No se pueden enviar mensajes mientras se cargan adjuntos."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"No se ha podido cargar el archivo adjunto. Vuelve a intentarlo."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"La red no está lista. Inténtalo de nuevo."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Eliminar texto"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alternar entre introducir texto y números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Añadir más participantes"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmar participantes"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Iniciar nueva conversación"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Seleccionar este elemento"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproducir vídeo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Contactos y opciones"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depurar"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Contactos y opciones"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Generales"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Contactos en esta conversación"</string>
+    <string name="action_call" msgid="6596167921517350362">"Hacer una llamada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Enviar mensaje"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Enviar mensaje&lt;br/&gt;&lt;small&gt;de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Enviar fotos</item>
+      <item quantity="one">Enviar foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Enviar archivos de audio</item>
+      <item quantity="one">Enviar archivo de audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Enviar vídeos</item>
+      <item quantity="one">Enviar vídeo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Enviar tarjetas de contacto</item>
+      <item quantity="one">Enviar tarjeta de contacto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Enviar archivos adjuntos</item>
+      <item quantity="one">Enviar archivo adjunto</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> archivos adjuntos listos para enviar</item>
+      <item quantity="one">Un archivo adjunto listo para enviar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Danos tu opinión"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ver en Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Información de la versión"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versión %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licencias código abierto"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificaciones"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Límite de archivos adjuntos alcanzado"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Error al cargar archivo adjunto."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"¿Añadir a contactos?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Añadir contacto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Asunto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Asunto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Cargando tarjeta de contacto"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"No se ha podido cargar la tarjeta de contacto"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ver tarjeta de contacto"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contactos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contacto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Tarjetas de contacto"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Cumpleaños"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Reenviar mensaje"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Responder"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS inhabilitados"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Para enviar mensajes, establece Mensajes como aplicación de SMS predeterminada"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Establecer Mensajes como aplicación de SMS predeterminada"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Cambiar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Para recibir mensajes, establece Mensajes como aplicación de SMS predeterminada"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"No se ha seleccionado la SIM preferida para enviar mensajes SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"El propietario del dispositivo no permite esta aplicación."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Aceptar"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Demasiados participantes en una conversación"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Contactos no válidos</item>
+      <item quantity="one">Contacto no válido</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"No se ha podido cargar la imagen de la cámara"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Tú: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Borrador"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Cuando inicies una conversación nueva, aparecerá aquí"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Aquí aparecen las conversaciones archivadas"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Cargando conversaciones..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imagen"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Fragmento de audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vídeo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Tarjeta de contacto"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Deshacer"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Volver a intentar"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Escribe el nombre de un contacto o un número de teléfono para iniciar un mensaje nuevo"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquear"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquear a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloquear a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"¿Bloquear a <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Seguirás recibiendo mensajes de este número pero no volverás a recibir notificaciones. Esta conversación se archivará."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contactos bloqueados"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEAR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contactos bloqueados"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Selecciona imagen de la biblioteca de documentos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Enviando mensaje"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mensaje enviado"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Los datos móviles están desactivados. Comprueba los ajustes."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"No se puede enviar mensajes en modo avión"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Error al enviar mensaje"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mensaje descargado"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Los datos móviles están desactivados. Comprueba los ajustes."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"No se pueden descargar mensajes en modo avión"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"No se ha podido descargar el mensaje"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Cero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Uno"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dos"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tres"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Cuatro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinco"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Siete"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Ocho"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nueve"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"No se puede enviar el mensaje con <xliff:g id="CARRIERNAME">%1$s</xliff:g> (error <xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"No se puede enviar el mensaje con un operador desconocido (error <xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Rv: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mensaje no enviado porque el servicio no se ha activado en la red"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mensaje no enviado: dirección de destino no válida"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mensaje no enviado: mensaje no válido"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mensaje no enviado: contenido no admitido"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mensaje no enviado: mensaje no admitido"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mensaje no enviado: demasiado largo"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mensaje nuevo"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ver"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imagen"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"No se ha podido encontrar una aplicación adecuada"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Eliminar destinatario"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mensaje nuevo"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancelar"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editar punto de acceso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"No definida"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nombre"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy para MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Puerto para MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo de APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Eliminar APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nuevo APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Guardar"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Descartar"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"El campo Nombre no puede estar vacío."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"El campo APN no puede estar vacío."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"El campo MCC debe contener 3 dígitos."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"El campo MNC debe contener 2 o 3 dígitos."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restaurando la configuración de APN predeterminada"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Restablecer ajustes"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Se ha restablecido la configuración de APN predeterminada."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sin título"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nombre de puntos de acceso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nuevo APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Los ajustes del nombre de punto de acceso no están disponibles para este usuario"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"¿Copiar al portapapeles?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiar"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"para <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"General"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Opciones avanzadas"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ajustes generales"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Ajustes avanzados"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Enviar mensajes SMS individuales. Solo tú recibirás las respuestas"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Enviar un único MMS a todos los destinatarios"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número desconocido"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mensaje nuevo"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mensaje nuevo."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selector de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> seleccionada, selector de SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editar asunto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Seleccionar SIM o editar asunto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Mantener pulsado para grabar audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Iniciar nueva conversación"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mensajes"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista de mensajes"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mensajes"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mensaje nuevo"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversaciones"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Cargando conversaciones"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Cargando mensajes"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ver más conversaciones"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ver más mensajes"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversación eliminada"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversación eliminada. Toca para ver otra conversación de Mensajes"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqueado"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desbloqueado"</string>
+    <string name="db_full" msgid="8459265782521418031">"Queda poco espacio de almacenamiento. Es posible que se pierdan algunos datos."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Seleccionar adjuntos"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmar selección"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Seleccionado: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Elimina uno o varios archivos adjuntos y vuelve a intentarlo."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Puedes probar a enviar el mensaje, pero quizás no se envíe hasta que elimines uno o varios archivos adjuntos."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Solo puedes enviar un vídeo por mensaje. Elimina más vídeos y vuelve a intentarlo."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"El mensaje no ha podido cargar el archivo adjunto."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Enviar de todos modos"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"No se ha podido iniciar la conversación"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> seleccionada"</string>
+</resources>
diff --git a/res/values-et/arrays.xml b/res/values-et/arrays.xml
new file mode 100644
index 0000000..16e1744
--- /dev/null
+++ b/res/values-et/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"teema puudub"</item>
+    <item msgid="272485471009191934">"teema puudub"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Jah"</item>
+    <item msgid="6049132459802288033">"Ei"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Aitäh"</item>
+    <item msgid="4881335087096496747">"Nõustun"</item>
+    <item msgid="2422296858597420738">"Tore"</item>
+    <item msgid="4805581752819452687">"Olen teel"</item>
+    <item msgid="4746700499431366214">"OK, vastan sulle hiljem"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
new file mode 100644
index 0000000..e222a3e
--- /dev/null
+++ b/res/values-et/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Sõnumside"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Sõnumside"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Vestluse valimine"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Seaded"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Saada sõnum"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Manuse lisamine"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Abi"</string>
+    <string name="welcome" msgid="2857560951820802321">"Tere tulemast"</string>
+    <string name="skip" msgid="7238879696319945853">"Vahelejätmine"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Järgmine &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Järgmine"</string>
+    <string name="exit" msgid="1905187380359981199">"Väljumine"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Seaded &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Seaded"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Sõnumside vajab luba SMS-idele, telefonile ja kontaktidele juurdepääsemiseks."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Saate muuta lube jaotises Seaded &gt; Rakendused &gt; Sõnumside &gt; Load."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Lubade muutmiseks tehke valikud Seaded, Rakendused, Sõnumside, Load."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Sagedased"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Kõik kontaktid"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Saada numbrile <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Jäädvustage pilte või videoid"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Kujutiste valimine sellest seadmest"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Heli salvestamine"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Foto valimine"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Meedia on valitud."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Meediat pole valitud."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> on valitud"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"pilt kuupäevaga <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"pilt"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Heli salvestamine"</string>
+    <string name="action_share" msgid="2143483844803153871">"Jagamine"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Hetk tagasi"</string>
+    <string name="posted_now" msgid="867560789350406701">"Praegu"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> tundi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> tund</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> päeva</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> päev</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> nädalat</item>
+      <item quantity="one">nädal</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> kuud</item>
+      <item quantity="one">kuu</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> aastat</item>
+      <item quantity="one">aasta</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0-klassi sõnum"</string>
+    <string name="save" msgid="5081141452059463572">"Salvesta"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Seadmes on vähe ruumi. Sõnumside kustutab ruumi vabastamiseks automaatselt vanemad sõnumid."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Talletusruum hakkab täis saama"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Sõnumside ei pruugi sõnumeid saata ega vastu võtta seni, kuni seadmes on rohkem vaba ruumi."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS-ide jaoks on vähe salvestusruumi. Peate võib-olla mõned sõnumid kustutama."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Kinnitage oma telefoninumber"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"See ühekordne toiming tagab, et rakendus Sõnumside edastab teie grupisõnumid õigesti."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefoninumber"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Kustuta kõik meediumifaile sisaldavad sõnumid"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Kustuta sõnumid, mis on vanemad kui <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Kustuta automaatselt sõnumid, mis on vanemad kui <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Eira"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Kas kustutada kõik meediaga sõnumid?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Kas kustutada sõnumid, mis on vanemad kui <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Kas kustutada automaatselt sõnumid, mis on vanemad kui <xliff:g id="DURATION">%s</xliff:g>, ja lülitada sisse automaatne kustutamine?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ütles:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ütlesite:"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Sõnum saatjalt <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Saatsite sõnumi"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Saatmine ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ei saadetud. Puudutage uuesti proovimiseks."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ei saadetud. Proovitakse uuesti ..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Saada uuesti või kustuta"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Helistage hädaabiteenusele. Teie tekstsõnumit ei õnnestunud praegu edastada."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Ebaõnnestus"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Uus MMS-sõnum allalaadimiseks"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Uus MMS-sõnum"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Ei saanud alla laadida"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Puudutage uuesti proovimiseks"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Puudutage allalaadimiseks"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Laadi alla või kustuta"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Allalaadimine ..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Sõnum on aegunud või pole saadaval"</string>
+    <string name="mms_info" msgid="3402311750134118165">"suurus: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, aegumine: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Ei õnnestu saata. Saaja ei ole õige."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Teenus pole võrgus aktiveeritud"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Võrguprobleemi tõttu ei õnnestunud saata"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Sõnum on aegunud või pole saadaval"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Teema puudub.)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Tundmatu saatja"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Kohale toimetatud"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Ei saa laadida alla sõnumit <xliff:g id="SUBJECT">%1$s</xliff:g>, mille saatis <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Vähese mälu tõttu ei õnnestunud andmebaasi toimingut lõpule viia"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Sõnumit ei saadetud"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Mõnda sõnumit ei saadetud rakenduses Sõnumside"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> sõnumit <xliff:g id="CONVERSATIONS">%d</xliff:g> vestluses</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> sõnumit ühes vestluses</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Sõnumit ei laaditud alla"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Mõnda sõnumit ei laaditud alla rakenduses Sõnumside"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> sõnumit <xliff:g id="CONVERSATIONS">%d</xliff:g> vestluses</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> sõnumit ühes vestluses</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Sõnumit numbrile <xliff:g id="NUMBER">%1$s</xliff:g> ei saadetud"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Helistage hädaabiteenusele. Teie tekstsõnumit numbrile <xliff:g id="NUMBER">%1$s</xliff:g> ei õnnestunud praegu edastada."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> uut sõnumit</item>
+      <item quantity="one">Uus sõnum</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Käivita"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kaamera pole saadaval"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kaamera pole saadaval"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video jäädvustamine pole saadaval"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Meediat ei saa salvestada"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Pilti ei saa jäädvustada"</string>
+    <string name="back" msgid="1477626055115561645">"Tagasi"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arhiivitud"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Kustutamine"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arhiivimine"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Arhiivimise tühistamine"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Märguannete väljalülitamine"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Märguannete sisselülitamine"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Kontakti lisamine"</string>
+    <string name="action_download" msgid="7786338136368564146">"Laadi alla"</string>
+    <string name="action_send" msgid="377635240181672039">"Saada"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Kustuta"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Kas kustutada see sõnum?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Seda toimingut ei saa tagasi võtta."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Kustuta"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Kas kustutada need vestlused?</item>
+      <item quantity="one">Kas kustutada see vestlus?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Kustuta"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Tühista"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Sihtkohta"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Mitme kujutise valimine"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Valiku kinnitamine"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"ja veel <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Heli ei õnnestu salvestada. Proovige uuesti."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Heli ei saa esitada. Proovige uuesti."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Heli ei õnnestunud salvestada. Proovige uuesti."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Puudutage pikalt"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Pilt"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Heliklipp"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktikaart"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Allalaadimine"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Vasta SMS-iga"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Vastam. MMS-iga"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Vasta"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> osalejat</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> osaleja</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Mina"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt on blokeeritud ja arhiivitud"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt deblokeeriti ja eemaldati arhiivist"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> on arhiivitud"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> üksuse arhiivimine on tühistatud"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Märguanded on välja lülitatud"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Märguanded on sisse lülitatud"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Kõik on valmis. Puudutage uuesti käsku Saada."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Sõnumside määramine SMS-i vaikerakenduseks õnnestus."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Manustest loobumine</item>
+      <item quantity="one">Manusest loobumine</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Helimanus"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Helimanuste esitamine"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Peata"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Sõnum saatjalt <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Sõnumi saamine kontaktilt <xliff:g id="SENDER">%1$s</xliff:g> ebaõnnestus: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Sõnum kontaktilt <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Saatmata sõnum kontaktile <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sõnumi saatmine kontaktile <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Sõnumi saatmine kontaktile <xliff:g id="CONTACT">%1$s</xliff:g> ebaõnnestus: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Sõnum kontaktile <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Sõnumi saamine kontaktilt <xliff:g id="SENDER">%1$s</xliff:g> ebaõnnestus: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Sõnum kontaktilt <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Saatmata sõnum kontaktile <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sõnumi saatmine kontaktile <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Sõnumi saatmine kontaktile <xliff:g id="GROUP">%1$s</xliff:g> ebaõnnestus: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Sõnum kontaktile <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aeg: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Sõnumi saatmine ebaõnnestus. Puudutage uuesti proovimiseks."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Vestlus osalejatega <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Teema kustutamine"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video jäädvustamine"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Foto jäädvustamine"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Pildistamine"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Video salvestamise alustamine"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Lülitamine täisekraaniga kaamerale"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Esi- ja tagakaamera vahetamine"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Salvestamise peatamine ja video lisamine"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Lõpeta video salvestamine"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Sõnumside fotod"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotot salvestati albumisse „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto salvestati albumisse „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videot salvestati albumisse „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video salvestati albumisse „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> manust salvestati albumisse „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> manus salvestati albumisse „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> manust salvestati kausta „Allalaadimised”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> manus salvestati kausta „Allalaadimised”</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> manust salvestati</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> manus salvestati</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> manust ei saanud salvestada</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> manust ei saanud salvestada</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Salvestati MMS-manus"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Seaded"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arhiivitud"</string>
+    <string name="action_close" msgid="1840519376200478419">"Sule"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Täpsem"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Silumine"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Märguanded"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Heli"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Hääletu"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibratsioon"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokeeritud"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-i edastamisaruanded"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Edastamisaruande taotlus iga saadetud SMS-i kohta"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automaatne toomine"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS-sõnumite automaatne vastuvõtmine"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automaatne vastuvõtmine rändlusel"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"MMS-ide automaatne toomine rändluse ajal"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Rühma sõnumside"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"MMS-i kasutamine, kui mitmele kontaktile tuleb saata üks sõnum"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"SMS-i vaikerakendus"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"SMS-i vaikerakendus"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Teie telefoninumber"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Teadmata"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Väljuva sõnumi helid"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS-i tõmmistamine"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Saadud SMS-ide lähteandmete tõmmistamine välisesse talletusfaili"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS-i tõmmistamine"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Saadud MMS-ide lähteandmete tõmmistamine välisesse talletusfaili"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Raadiosidehoiatused"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Sõnumi valikud"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopeeri tekst"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Kuva üksikasjad"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Kustuta"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Edastamine"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Sõnumi üksikasjad"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tüüp: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Tekstisõnum"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimeediumsõnum"</string>
+    <string name="from_label" msgid="1947831848146564875">"Saatja: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Saaja: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Saadetud: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Vastu võetud: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Teema: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Suurus: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioriteet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Suur"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Tavaline"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Madal"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Varjatud saatja aadress"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Sõnumit ei saa manuste laadimise ajal saata."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Manust ei õnnestu laadida. Proovige uuesti."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Võrk pole valmis. Proovige uuesti."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Kustuta tekst"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Teksti ja numbrite vaheldumisi sisestamine"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Lisa rohkem osalejaid"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Osalejate kinnitamine"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Uue vestluse alustamine"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selle üksuse valimine"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Video esitamine"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Inimesed ja valikud"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Silu"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Inimesed ja valikud"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Üldine"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Selles vestluses osalevad inimesed"</string>
+    <string name="action_call" msgid="6596167921517350362">"Helista"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Saatke sõnum"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Sõnumi saatmine&lt;br/&gt;&lt;small&gt;SIM-kaardilt <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Saada fotod</item>
+      <item quantity="one">Saada foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Saada helifailid</item>
+      <item quantity="one">Saada helifail</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Saada videod</item>
+      <item quantity="one">Saada video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Saada kontaktikaardid</item>
+      <item quantity="one">Saada kontaktikaart</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Saada manused</item>
+      <item quantity="one">Saada manus</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> manust on saatmiseks valmis</item>
+      <item quantity="one">Üks manus on saatmiseks valmis</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Tagasiside saatmine"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Kuvamine Google Play poes"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versiooni teave"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versioon %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Avatud lähtekoodi litsentsid"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Märguanded"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Manuselimiit on täis"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Manuse laadimine ebaõnnestus."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Kas lisada kontaktidesse?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Kontaktisiku lisamine"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Teema"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Teema: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontakti kaardi laadimine"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kontaktkaarti ei õnnestunud laadida"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Kontakti kaardi kuvamine"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakti</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktkaardid"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Sünnipäev"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Märkmed"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Sõnumi edastamine"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Vastamine"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS on keelatud"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Saatmiseks määrake rakendus Sõnumside SMS-i vaikerakenduseks"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Määrake rakendus Sõnumside SMS-i vaikerakenduseks"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Muuda"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Sõnumite vastuvõtmiseks määrake rakendus Sõnumside SMS-i vaikerakenduseks"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS-sõnumite saatmiseks pole eelistatud SIM-kaarti valitud"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Seadme omanik pole seda rakendust lubanud."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Vestluses on liiga palju osalejaid"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Sobimatud kontaktid</item>
+      <item quantity="one">Sobimatu kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kaamera kujutist ei õnnestunud laadida"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Teie: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Mustand"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Kui alustate uut vestlust, loetletakse see siin"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arhiivitud vestlused kuvatakse siin"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Vestluste laadimine …"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Pilt"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Heliklipp"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktikaart"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Tagasivõtmine"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Proovi uuesti"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Uue sõnumi alustamiseks sisestage kontakti nimi või telefoninumber"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokeerimine"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokeeri <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Deblokeeri <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Kas blokeerida <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Saate sellelt numbrilt ikka sõnumeid, kuid te ei saa enam märguandeid. Vestlus arhiivitakse."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokeeritud kontaktid"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DEBLOKEERIMINE"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokeeritud kontaktid"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Dokumendikogust kujutise valimine"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sõnumi saatmine"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Sõnum on saadetud"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobiilne andmeside on välja lülitatud. Kontrollige seadeid."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Lennukirežiimis ei saa sõnumeid saata"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Sõnumit ei saanud saata"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Sõnum on alla laaditud"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobiilne andmeside on välja lülitatud. Kontrollige seadeid."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Lennukireżiimis ei saa sõnumeid alla laadida"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Sõnumit ei saanud alla laadida"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Null"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Üks"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Kaks"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Kolm"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Neli"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Viis"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Kuus"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Seitse"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Kaheksa"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Üheksa"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Operaatori <xliff:g id="CARRIERNAME">%1$s</xliff:g> kaudu ei õnnestu sõnumit saata, viga <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Tundmatu operaatori kaudu ei õnnestu sõnumit saata, viga <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Edastamine: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Sõnumit ei saadetud: teenus pole võrgus aktiveeritud"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Sõnumit ei saadetud: kehtetu sihtaadress"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Sõnumit ei saadetud: vigane sõnum"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Sõnumit ei saadetud: toetuseta sisu"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Sõnumit ei saadetud: toetuseta sõnum"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Sõnumit ei saadetud: liiga suur"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Uus sõnum"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Kuvamine"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Kujutis"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Sobivat rakendust ei õnnestunud leida"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Saaja eemaldamine"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Uus sõnum"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Tühista"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Pääsupunkti muutmine"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Määramata"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nimi"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-i puhverserver"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-i port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-i tüüp"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Kustuta APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Uus APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Salvesta"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Tühista"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Nimeväli ei saa olla tühi."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ei saa olla tühi."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-väli peab olema kolme numbriga."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-väli peab olema kahe või kolme numbriga."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"APN-i vaikeseadete taastamine."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Lähtesta vaikeseadetele"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"APN-i vaikeseadete lähtestamine on lõpule viidud."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Pealkirjata"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Pääsupunktide nimed"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-id"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Uus APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Pääsupunkti nime seaded pole selle kasutaja jaoks saadaval"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kas kopeerida lõikelauale?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopeeri"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"SIM-kaardile <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Üldised"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Täpsemad"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Üldseaded"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Täpsemad seaded"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM-kaart „<xliff:g id="SIM_NAME">%s</xliff:g>”"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Individuaalsed SMS-id saadetakse kõikidele adressaatidele. Ainult teie saate vastuseid"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Üks MMS saadetakse kõikidele adressaatidele"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Tundmatu number"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Uus sõnum"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Uus sõnum."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-kaardi valija"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> on valitud, SIM-kaardi valija"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Teema muutmine"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM-kaardi valimine või objekti valimine"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Puudutage pikalt heli salvestamiseks"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Uue vestluse alustamine"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Sõnumside"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Sõnumside loend"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Sõnumside"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Uus sõnum"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Vestlusloend"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Vestluste laadimine …"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Sõnumite laadimine ..."</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Kuva rohkem vestlusi"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Kuva rohkem sõnumeid"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Vestlus on kustutatud"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Vestlus kustutati. Rakenduse Sõnumside eri vestluste kuvamiseks puudutage"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokeeritud"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Deblokeeritud"</string>
+    <string name="db_full" msgid="8459265782521418031">"Talletusruumi on vähe. Osa andmetest võib kaduma minna."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Manuste valimine"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Valiku kinnitamine"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> on valitud"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Eemaldage üks või mitu manust ja proovige uuesti."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Võite proovida sõnumit saata, aga selle edastamine võib ebaõnnestuda, kui te ei eemalda üht või mitut manust."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Saate sõnumis saata vaid ühe video. Eemaldage täiendavad videod ja proovige uuesti."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Rakendusel Sõnumside ei õnnestunud manust laadida."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Saada ikkagi"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Vestlust ei õnnestunud alustada"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> on valitud"</string>
+</resources>
diff --git a/res/values-eu/arrays.xml b/res/values-eu/arrays.xml
new file mode 100644
index 0000000..5ea97f0
--- /dev/null
+++ b/res/values-eu/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"gairik ez"</item>
+    <item msgid="272485471009191934">"gairik ez"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Bai"</item>
+    <item msgid="6049132459802288033">"Ez"</item>
+    <item msgid="3084376867445867895">"Ados"</item>
+    <item msgid="3155097332660174689">"Kar-kar"</item>
+    <item msgid="2611328818571146775">"Eskerrik asko"</item>
+    <item msgid="4881335087096496747">"Ados"</item>
+    <item msgid="2422296858597420738">"Ederki"</item>
+    <item msgid="4805581752819452687">"Banoa"</item>
+    <item msgid="4746700499431366214">"Ados, geroago erantzungo dizut"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
new file mode 100644
index 0000000..1703681
--- /dev/null
+++ b/res/values-eu/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mezuak"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mezuak"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Hautatu elkarrizketa"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ezarpenak"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Bidali mezua"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Gehitu eranskina"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Laguntza"</string>
+    <string name="welcome" msgid="2857560951820802321">"Ongi etorri"</string>
+    <string name="skip" msgid="7238879696319945853">"Saltatu"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Hurrengoa &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Hurrengoa"</string>
+    <string name="exit" msgid="1905187380359981199">"Irten"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Ezarpenak &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ezarpenak"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mezuak aplikazioak baimena behar du SMS mezuak bidaltzeko eta jasotzeko, deiak egiteko eta kontaktuak atzitzeko."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Baimenak aldatzeko, zoaz Ezarpenak &gt; Aplikazioak &gt; Mezuak &gt; Baimenak atalera."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Baimenak aldatzeko, zoaz Ezarpenak, Aplikazioak, Mezuak, Baimenak atalera."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Maiz erabilitakoak"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Kontaktu guztiak"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Bidali hona: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Atera irudiak edo grabatu bideoa"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Aukeratu gailu honetako irudiak"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Grabatu audioa"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Aukeratu argazkia"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Euskarria hautatu da."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Euskarria desautatu da."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> hautatuta"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"Irudiaren data: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"irudia"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Grabatu audioa"</string>
+    <string name="action_share" msgid="2143483844803153871">"Partekatu"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Oraintxe"</string>
+    <string name="posted_now" msgid="867560789350406701">"Orain"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ordu</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ordu</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> egun</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> egun</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> aste</item>
+      <item quantity="one">Astebete</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hilabete</item>
+      <item quantity="one">Hilabete</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> urte</item>
+      <item quantity="one">Urtebete</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0 klaseko mezua"</string>
+    <string name="save" msgid="5081141452059463572">"Gorde"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Toki gutxi dago gailuan. Tokia egiteko, Mezuak aplikazioak automatikoki ezabatuko ditu mezu zaharragoak."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Memoria betetzen ari da"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Gailuan toki gehiago izan arte, baliteke Mezuak aplikazioak mezurik ez bidaltzea edo jasotzea."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS mezuetarako memoria gutxi dago. Baliteke mezuak ezabatu behar izatea."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Berretsi telefono-zenbakia"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Behin bakarrik egin beharreko urrats honi esker, Mezuak aplikazioak taldeko mezuak behar bezala bidaliko dituela ziurtatuko duzu."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefono-zenbakia"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Ezabatu multimedia-elementuak dituzten mezu guztiak"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Ezabatu <xliff:g id="DURATION">%s</xliff:g> baino zaharragoak diren mezuak"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Ezabatu automatikoki <xliff:g id="DURATION">%s</xliff:g> baino zaharragoak diren mezuak"</string>
+    <string name="ignore" msgid="7063392681130898793">"Egin ez ikusi"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Multimedia-elementuak dauzkaten mezu guztiak ezabatu nahi dituzu?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> baino zaharragoak diren mezuak ezabatu nahi dituzu?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> baino zaharragoak diren mezuak ezabatu eta ezabaketa automatikoa aktibatu nahi duzu?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> erabiltzaileak esan du"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Zuk esan duzu"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> erabiltzailearen mezua:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Mezu bat bidali duzu"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Bidaltzen…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ez da bidali. Berriro saiatzeko, ukitu hau."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ez da bidali. Berriro saiatzen…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Birbidali edo ezabatu"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Deitu larrialdi-zerbitzuetara. Ezin izan dugu entregatu testu-mezua."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Huts egin du"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"MMS mezu berria deskargatzeko prest"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"MMS mezu berria"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Ezin izan da deskargatu"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Berriro saiatzeko, ukitu hau"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Deskargatzeko, ukitu hau"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Deskargatu edo ezabatu"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Deskargatzen…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mezua iraungi da edo ez dago erabilgarri"</string>
+    <string name="mms_info" msgid="3402311750134118165">"Tamaina: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>. Iraungitze-data: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>."</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Ezin da bidali. Hartzaileak ez du balio."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Zerbitzua ez dago sare honetan aktibatuta"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Ezin izan da bidali sareko arazo baten ondorioz"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mezua iraungi da edo ez dago erabilgarri"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Gairik ez)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Igorle ezezaguna"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Bidalita"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Ezin izan da <xliff:g id="FROM">%2$s</xliff:g> erabiltzailearen <xliff:g id="SUBJECT">%1$s</xliff:g> mezua deskargatu."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Ezin izan da datu-basearen eragiketa osatu memoria gutxi dagoelako"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Ez da bidali mezua"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Ez dira bidali Mezuak aplikazioko mezu batzuk"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mezu daude <xliff:g id="CONVERSATIONS">%d</xliff:g> elkarrizketatan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mezu daude elkarrizketa batean</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Ez da deskargatu mezua"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Ez dira deskargatu Mezuak aplikazioko mezu batzuk"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mezu daude <xliff:g id="CONVERSATIONS">%d</xliff:g> elkarrizketatan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mezu daude elkarrizketa batean</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mezua ez da bidali <xliff:g id="NUMBER">%1$s</xliff:g> zenbakira"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Deitu larrialdi-zerbitzuetara. Ezin izan dugu entregatu <xliff:g id="NUMBER">%1$s</xliff:g> zenbakira bidalitako testu-mezua."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mezu berri</item>
+      <item quantity="one">Mezu berria</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Hasi"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera ez dago erabilgarri"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera ez dago erabilgarri"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Bideo-grabaketa ez dago erabilgarri"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Ezin da gorde multimedia-elementua"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Ezin da atera argazkia"</string>
+    <string name="back" msgid="1477626055115561645">"Atzera"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Artxibatutakoak"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Ezabatu"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Artxibatu"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Kendu artxibotik"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desaktibatu jakinarazpenak"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Aktibatu jakinarazpenak"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Gehitu kontaktua"</string>
+    <string name="action_download" msgid="7786338136368564146">"Deskargatu"</string>
+    <string name="action_send" msgid="377635240181672039">"Bidali"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Ezabatu"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Mezua ezabatu nahi duzu?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ezin da ekintza hori desegin."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Ezabatu"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Elkarrizketa hauek ezabatu nahi dituzu?</item>
+      <item quantity="one">Elkarrizketa ezabatu nahi duzu?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Ezabatu"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Utzi"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Hartzailea"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Hautatu hainbat irudi"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Berretsi hautapena"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Ezin da grabatu audioa. Saiatu berriro."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Ezin da erreproduzitu audioa. Saiatu berriro."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Ezin izan da gorde audioa. Saiatu berriro."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Eduki ukituta"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Argazkia"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio-klipa"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Bideoa"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktu-txartela"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Deskargatu"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Erantzun SMS bidez"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Erantzun MMS bidez"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Erantzun"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> parte-hartzaile</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> parte-hartzaile</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ni"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontaktua blokeatu eta artxibatu egin da"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontaktua desblokeatu da eta artxibotik kendu da"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> artxibatuta"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> artxibotik kenduta"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Jakinarazpenak desaktibatuta daude"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Jakinarazpenak aktibatuta daude"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Dena ezarri da. Ukitu berriro Bidali."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mezuak aplikazioa behar bezala ezarri da SMS mezuetarako aplikazio lehenetsi gisa."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Baztertu eranskinak</item>
+      <item quantity="one">Baztertu eranskina</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio-eranskina"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Erreproduzitu audio-eranskina"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausatu"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> erabiltzailearen mezua: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> igorlearen mezuak huts egin du: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> igorlearen mezua: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ez zaio bidali mezua <xliff:g id="CONTACT">%1$s</xliff:g> erabiltzaileari: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> erabiltzaileari mezua bidaltzen: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Ezin izan zaio bidali mezua <xliff:g id="CONTACT">%1$s</xliff:g> erabiltzaileari: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> erabiltzailearentzako mezua: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> igorlearen mezuak huts egin du: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> igorlearen mezua: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ez da bidali mezua <xliff:g id="GROUP">%1$s</xliff:g> taldera: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> taldera mezua bidaltzen: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Ezin izan da bidali mezua <xliff:g id="GROUP">%1$s</xliff:g> taldera: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> taldearentzako mezua: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ordua: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mezuak huts egin du. Ukitu berriro saiatzeko."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Elkarrizketa erabiltzaile hauekin (<xliff:g id="PARTICIPANTS">%s</xliff:g>)"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Ezabatu gaia"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Grabatu bideoa"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Atera irudi finkoa"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Atera argazkia"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Hasi bideoa grabatzen"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Aldatu pantaila osoko kamerara"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Aldatu aurreko eta atzeko kameren artean"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Utzi grabatzeari eta erantsi bideoa"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Utzi bideoa grabatzeari"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Mezuak aplikazioko argazkiak"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> argazki gorde dira \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albumean</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> argazki gorde da \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albumean</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> bideo gorde dira \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albumean</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bideo gorde da \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albumean</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> eranskin gorde dira \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albumean</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> eranskin gorde da \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albumean</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> eranskin gorde dira \"Deskargak\" atalean</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> eranskin gorde da \"Deskargak\" atalean</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Gorde dira <xliff:g id="QUANTITY_1">%d</xliff:g> eranskin</item>
+      <item quantity="one">Gorde da <xliff:g id="QUANTITY_0">%d</xliff:g> eranskin</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Ezin izan dira gorde <xliff:g id="QUANTITY_1">%d</xliff:g> eranskin</item>
+      <item quantity="one">Ezin izan da gorde <xliff:g id="QUANTITY_0">%d</xliff:g> eranskin</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMSko eranskina gordeta dago"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ezarpenak"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Artxibatuta"</string>
+    <string name="action_close" msgid="1840519376200478419">"Itxi"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Ezarpen aurreratuak"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Araztu"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Jakinarazpenak"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Soinua"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Isilik"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Egin dar-dar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokeatuta"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMSak entregatzearen txostenak"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Eskatu bidaltzen duzun SMS bakoitzaren entrega-txostena"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Eskuratu automatikoki"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Eskuratu MMS mezuak automatikoki"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Eskuratu automatikoki ibiltaritzan"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Eskuratu MMS mezuak automatikoki ibiltaritzan"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Talde-mezularitza"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Erabili MMSak mezu bakarra bidaltzeko hartzaile ugari daudenean"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"SMS mezuetarako aplikazio lehenetsia"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"SMS mezuetarako aplikazio lehenetsia"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Zure telefono-zenbakia"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Ezezaguna"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Irteerako mezuen soinuak"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Irauli SMSak"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Irauli jasotako SMS mezuen prozesatu gabeko datuak kanpoko memoriako fitxategira"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Irauli MMSak"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Irauli jasotako MMS mezuen prozesatu gabeko datuak kanpoko memoriako fitxategira"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Hari gabeko alertak"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Mezuaren aukerak"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiatu testua"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ikusi xehetasunak"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Ezabatu"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Birbidali"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Mezuaren xehetasunak"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Mota: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Testu-mezua"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia-mezua"</string>
+    <string name="from_label" msgid="1947831848146564875">"Igorlea: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Hartzailea: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Bidaltze-data: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Jasotze-data: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Gaia: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamaina: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Lehentasuna: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM txartela: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Handia"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normala"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Txikia"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"<xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>. SIM txartela"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Igorlearen helbidea ezkutatuta badago"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Ezin da mezua bidali eranskinak kargatzen ari diren bitartean."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Ezin da kargatu eranskina. Saiatu berriro."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Sarea ez dago prest. Saiatu berriro."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Ezabatu testua"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Aldatu testu eta zenbaki moduen artean"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Gehitu parte-hartzaile gehiago"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Berretsi parte-hartzaileak"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Hasi elkarrizketa bat"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Hautatu elementu hau"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Erreproduzitu bideoa"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Jendea eta aukerak"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Araztu"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Jendea eta aukerak"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Orokorra"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Elkarrizketa honetako jendea"</string>
+    <string name="action_call" msgid="6596167921517350362">"Deitu"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Bidali mezua"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Bidali mezua &lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> txarteletik&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Bidali argazkiak</item>
+      <item quantity="one">Bidali argazkia</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Bidali audioak</item>
+      <item quantity="one">Bidali audioa</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Bidali bideoak</item>
+      <item quantity="one">Bidali bideoa</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Bidali kontaktu-txartelak</item>
+      <item quantity="one">Bidali kontaktu-txartela</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Bidali eranskinak</item>
+      <item quantity="one">Bidali eranskina</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> eranskin bidaltzeko prest daude</item>
+      <item quantity="one">Eranskin bat bidaltzeko prest dago</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Bidali iritzia"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ikusi Google Play Store dendan"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Bertsioari buruzko informazioa"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"%1$s bertsioa"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Kode irekiko lizentziak"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Jakinarazpenak"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Eranskinen mugara iritsi zara"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Ezin izan da kargatu eranskina."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Kontaktuetan gehitu nahi duzu?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Gehitu kontaktua"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Gaia"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Gaia: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontaktu-txartela kargatzen"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Ezin izan da kargatu kontaktu-txartela"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ikusi kontaktu-txartela"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktu</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontaktu</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktu-txartelak"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Urtebetetzea"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Oharrak"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Birbidali mezua"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Erantzun"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMSak desgaituta"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Mezuak bidaltzeko, ezarri Mezuak aplikazioa SMS mezuetarako aplikazio lehenetsi gisa"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Ezarri Mezuak aplikazioa SMS mezuetarako aplikazio lehenetsi gisa"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Aldatu"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Mezuak jasotzeko, ezarri Mezuak aplikazioa SMS mezuetarako aplikazio lehenetsi gisa"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ez da hautatu SIM txartel hobetsirik SMS mezuak bidaltzeko"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Gailuaren jabeak ez du aplikazio hau erabiltzea baimendu."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Ados"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Parte-hartzaile gehiegi daude elkarrizketan"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Kontaktuek ez dute balio</item>
+      <item quantity="one">Kontaktuak ez du balio</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Ezin izan da kargatu kamerako irudia"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Zu: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Zirriborroa"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Elkarrizketak hasten dituzunean, hemen agertuko dira"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Artxibatutako elkarrizketak hemen ageri dira"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Elkarrizketak kargatzen…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Argazkia"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio-klipa"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Bideoa"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktu-txartela"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Desegin"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Saiatu berriro"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Mezu berria hasteko, idatzi kontaktu baten izena edo telefono-zenbakia."</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokeatu"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokeatu <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desblokeatu <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> blokeatu nahi duzu?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Zenbaki horren mezuak jasotzen jarraituko duzu, baina ez duzu horren jakinarazpenik jasoko aurrerantzean. Elkarrizketa artxibatu egingo da."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokeatutako kontaktuak"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOKEATU"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokeatutako kontaktuak"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Aukeratu irudia dokumentuen liburutegitik"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Mezua bidaltzen"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mezua bidali da"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mugikorreko datuak desaktibatuta daude. Egiaztatu ezarpenak."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Ezin dira bidali mezuak hegaldi moduan"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Ezin izan da bidali mezua"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mezua deskargatu da"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mugikorreko datuak desaktibatuta daude. Egiaztatu ezarpenak."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Ezin da deskargatu mezua hegaldi moduan"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Ezin izan da deskargatu mezua"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Bat"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Bi"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Hiru"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Lau"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Bost"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sei"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Zazpi"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Zortzi"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Bederatzi"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Ezin da bidali mezua <xliff:g id="CARRIERNAME">%1$s</xliff:g> operadorearekin. Errorea: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Ezin da bidali mezua operadore ezezagunarekin. Errorea: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Ez da bidali mezua: zerbitzua ez dago aktibatuta sarean"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mezua ez da bidali. Helmugaren helbideak ez du balio."</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mezua ez da bidali. Ez du balio."</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mezua ez da bidali. Edukia ez da onartzen."</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mezua ez da bidali. Ez da onartzen."</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Ez da bidali mezua: handiegia da"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mezu berria"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ikusi"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Irudia"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Ezin izan da aurkitu aplikazio egokia"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Kendu hartzailea"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mezu berria"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Utzi"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editatu sarbide-puntua"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ezarri gabe"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Izena"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxya"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS ataka"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN mota"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Ezabatu APNa"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN berria"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Gorde"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Baztertu"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"\"Izena\" eremua ezin da hutsik utzi."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"\"APN\" eremua ezin da hutsik utzi."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"\"MCC\" eremuak 3 digitu izan behar ditu."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"\"MNC\" eremuak 2 edo 3 digitu izan behar ditu."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"APN ezarpen lehenetsiak leheneratzen."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Berrezarri ezarpen lehenetsiak"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"APN ezarpen lehenetsiak berrezarri dira."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Izengabea"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Sarbide-puntuen izenak"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNak"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN berria"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Erabiltzaile honek ezin ditu APN ezarpenak atzitu"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Arbelean kopiatu nahi duzu?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiatu"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> txartelean"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Orokorra"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Ezarpen aurreratuak"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ezarpen orokorrak"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Ezarpen aurreratuak"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM txartela"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Bidali SMS mezu bana hartzaile guztiei. Zuk bakarrik jasoko dituzu erantzunak"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Bidali MMS mezu bakarra hartzaile guztiei"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Zenbaki ezezaguna"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mezu berria"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mezu berria."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM hautatzailea"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> hautatuta, SIM hautatzailea"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editatu gaia"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Hautatu SIM txartela edo editatu gaia"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Eduki sakatuta audioa grabatzeko"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Hasi elkarrizketa bat"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mezuak"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Mezuak aplikazioko zerrenda"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mezuak"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mezu berria"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Elkarrizketa-zerrenda"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Elkarrizketak kargatzen"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Mezuak kargatzen"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ikusi elkarrizketa gehiago"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ikusi mezu gehiago"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Elkarrizketa ezabatu egin da"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Ezabatu egin da elkarrizketa. Ukitu hau Mezuak aplikazioko beste elkarrizketa bat erakusteko."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokeatu da"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desblokeatu da"</string>
+    <string name="db_full" msgid="8459265782521418031">"Toki gutxi geratzen da. Agian ez dira gordeko datu batzuk."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Hautatu eranskinak"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Berretsi hautapena"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> hautatuta"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Kendu eranskin bat edo gehiago, eta saiatu berriro."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Hala eta guztiz ere, mezua bidaltzen saia zaitezke, baina agian ez da entregatuko, eranskinetako batzuk kendu ezean."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Bideo bakarra bidal dezakezu mezu bakoitzeko. Kendu gainerako bideoak eta saiatu berriro."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mezuak aplikazioak ezin izan du eranskina kargatu."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Bidali halere"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Ezin izan da hasi elkarrizketa"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> hautatu da"</string>
+</resources>
diff --git a/res/values-fa/arrays.xml b/res/values-fa/arrays.xml
new file mode 100644
index 0000000..01b6f3e
--- /dev/null
+++ b/res/values-fa/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"بدون موضوع"</item>
+    <item msgid="272485471009191934">"بدون موضوع"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"بله"</item>
+    <item msgid="6049132459802288033">"خیر"</item>
+    <item msgid="3084376867445867895">"تأیید"</item>
+    <item msgid="3155097332660174689">"هه‌هه"</item>
+    <item msgid="2611328818571146775">"سپاسگزارم"</item>
+    <item msgid="4881335087096496747">"موافقم"</item>
+    <item msgid="2422296858597420738">"خوب"</item>
+    <item msgid="4805581752819452687">"در راهم"</item>
+    <item msgid="4746700499431366214">"بسیار خوب، بگذارید بعداً با شما تماس بگیرم"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
new file mode 100644
index 0000000..a1bf9d8
--- /dev/null
+++ b/res/values-fa/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"پیام‌رسانی"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"پیام‌رسانی"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"انتخاب مکالمه"</string>
+    <string name="action_settings" msgid="1329008122345201684">"تنظیمات"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"ارسال پیام"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"افزودن پیوست"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"راهنما"</string>
+    <string name="welcome" msgid="2857560951820802321">"خوش آمدید"</string>
+    <string name="skip" msgid="7238879696319945853">"رد شدن"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"‏بعدی &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"بعدی"</string>
+    <string name="exit" msgid="1905187380359981199">"خروج"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"‏تنظیمات &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"تنظیمات"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"«پیام‌رسانی» به مجوز دسترسی به پیامک، تلفن و مخاطبین نیاز دارد."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"‏می‌توانید مجوزها را در تنظیمات &gt; برنامه‌ها &gt; پیام‌رسانی &gt; مجوزها تغییر دهید."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"می‌توانید مجوزها را در تنظیمات، برنامه‌ها، پیام‌رسانی، مجوزها تغییر دهید."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"مکرر"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"همه مخاطبین"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"ارسال به <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"گرفتن عکس یا ویدیو"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"انتخاب تصاویر از این دستگاه"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ضبط صدا"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"انتخاب عکس"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"رسانه انتخاب شده است."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"رسانه انتخاب نشده است."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> مورد انتخاب شد"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"تاریخ تصویر <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"تصویر"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ضبط صدا"</string>
+    <string name="action_share" msgid="2143483844803153871">"اشتراک‌گذاری"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"هم‌اکنون"</string>
+    <string name="posted_now" msgid="867560789350406701">"اکنون"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%d</xliff:g> دقیقه</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%d</xliff:g> دقیقه</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%d</xliff:g> ساعت</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%d</xliff:g> ساعت</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%d</xliff:g> روز</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%d</xliff:g> روز</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one">‏<xliff:g id="COUNT">%d</xliff:g> هفته</item>
+      <item quantity="other">‏<xliff:g id="COUNT">%d</xliff:g> هفته</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one">‏<xliff:g id="COUNT">%d</xliff:g> ماه</item>
+      <item quantity="other">‏<xliff:g id="COUNT">%d</xliff:g> ماه</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one">‏<xliff:g id="COUNT">%d</xliff:g> سال</item>
+      <item quantity="other">‏<xliff:g id="COUNT">%d</xliff:g> سال</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"پیام رده ۰"</string>
+    <string name="save" msgid="5081141452059463572">"ذخیره‌"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"فضای ذخیره‌سازی دستگاه کم است. «پیام‌رسانی» برای آزاد کردن فضا، پیام‌های قدیمی‌تر را به‌طور خودکار پاک می‌کند."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"فضای ذخیره‌سازی رو به پایان است"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"شاید تا وقتی فضای بیشتری در دستگاهتان در دسترس نباشد، «پیام‌رسانی» پیام ارسال یا دریافت نکند."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"فضای ذخیره‌سازی پیامک کم است. ممکن است لازم باشد پیام‌ها را حذف کنید."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"شماره تلفنتان را تأیید کنید"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"با انجام این مرحله یک‌باره مطمئن می‌شوید «پیام‌رسانی» پیام‌های گروهی شما را به‌درستی تحویل می‌دهد."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"شماره تلفن"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"حذف همه پیام‌های دارای رسانه"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"حذف پیام‌های قدیمی‌تر از <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"حذف خودکار پیام‌های قدیمی‌تر از <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"نادیده گرفتن"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"همه پیام‌های دارای رسانه حذف شوند؟"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"پیام‌های قدیمی‌تر از <xliff:g id="DURATION">%s</xliff:g> حذف شوند؟"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"پیام‌های قدیمی‌تر از <xliff:g id="DURATION">%s</xliff:g> حذف شود و حذف خودکار روشن شود؟"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> گفت"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"گفتید"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"پیام از <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"پیامی ارسال کردید"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"در حال ارسال…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ارسال نشد. برای امتحان مجدد لمس کنید."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ارسال نشد. در حال امتحان مجدد…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ارسال مجدد یا حذف"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"لطفاً یک تماس صوتی با خدمات اضطراری برقرار کنید. در حال حاضر تحویل پیامک شما ممکن نیست."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"انجام نشد"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"‏پیام MMS جدید برای دانلود"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"‏پیام MMS جدید"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"دانلود نشد"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"برای امتحان مجدد لمس کنید"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"برای دانلود لمس کنید"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"دانلود یا حذف"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"در حال دانلود…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"پیام منقضی شده است یا در دسترس نیست"</string>
+    <string name="mms_info" msgid="3402311750134118165">"اندازه: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>، تاریخ انقضا: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"ارسال نمی‌شود. گیرنده معتبر نیست."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"سرویس در شبکه فعال نشده است"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"به علت مشکل شبکه ارسال نشد"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"پیام منقضی شده است یا در دسترس نیست"</string>
+    <string name="no_subject" msgid="5587715902648568767">"‫(بدون موضوع)‏"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"فرستنده ناشناس"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"تحویل داده شد"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"‫پیام <xliff:g id="SUBJECT">%1$s</xliff:g> از <xliff:g id="FROM">%2$s</xliff:g> دانلود نشد.‏"</string>
+    <string name="low_memory" msgid="5300743415198486619">"به دلیل حافظه کم، عملیات پایگاه داده انجام نشد"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"پیام ارسال نشد"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"بعضی از پیام‌ها در «پیام‌رسانی» ارسال نشدند"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one">‏<xliff:g id="MESSAGES_1">%d</xliff:g> پیام در <xliff:g id="CONVERSATIONS">%d</xliff:g> مکالمه</item>
+      <item quantity="other">‏<xliff:g id="MESSAGES_1">%d</xliff:g> پیام در <xliff:g id="CONVERSATIONS">%d</xliff:g> مکالمه</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"پیام دانلود نشد"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"بعضی از پیام‌ها در «پیام‌رسانی» دانلود نشدند"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one">‏<xliff:g id="MESSAGES_1">%d</xliff:g> پیام در <xliff:g id="CONVERSATIONS">%d</xliff:g> مکالمه</item>
+      <item quantity="other">‏<xliff:g id="MESSAGES_1">%d</xliff:g> پیام در <xliff:g id="CONVERSATIONS">%d</xliff:g> مکالمه</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"پیام به <xliff:g id="NUMBER">%1$s</xliff:g> ارسال نشد"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"لطفاً یک تماس صوتی با خدمات اضطراری برقرار کنید. در حال حاضر تحویل پیامک شما به <xliff:g id="NUMBER">%1$s</xliff:g> ممکن نیست."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> پیام جدید</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> پیام جدید</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"شروع"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"دوربین در دسترس نیست"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"دوربین در دسترس نیست"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ضبط ویدیو در دسترس نیست"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"رسانه ذخیره نمی‌شود"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"عکس نمی‌گیرد"</string>
+    <string name="back" msgid="1477626055115561645">"برگشت"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"بایگانی شده"</string>
+    <string name="action_delete" msgid="4076795795307486019">"حذف"</string>
+    <string name="action_archive" msgid="5437034800324083170">"بایگانی"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"لغو بایگانی"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"خاموش کردن اعلان‌ها"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"روشن کردن اعلان‌ها"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"افزودن مخاطب"</string>
+    <string name="action_download" msgid="7786338136368564146">"دانلود"</string>
+    <string name="action_send" msgid="377635240181672039">"ارسال"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"حذف"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"این پیام حذف شود؟"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"این عملکرد قابل واگرد نیست."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"حذف"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">این مکالمه حذف شود؟</item>
+      <item quantity="other">این مکالمه‌ها حذف شود؟</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"حذف"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"لغو"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"به"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"انتخاب چند تصویر"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"تأیید انتخاب"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"صدا ضبط نمی‌شود. دوباره امتحان کنید."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"صدا پخش نمی‌شود. دوباره امتحان کنید."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"صدا ذخیره نشد. دوباره امتحان کنید."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"لمس کنید و نگه‌دارید"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"، "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"تصویر"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"کلیپ صوتی"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ویدیو"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"کارت ویزیت"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"دانلود"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"پاسخ از طریق پیامک"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"‏پاسخ از طریق MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"پاسخ"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%d</xliff:g> شرکت‌کننده</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%d</xliff:g> شرکت‌کننده</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"من"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"مخاطب مسدود و بایگانی شد"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"انسداد مخاطب برطرف شد و از بایگانی خارج شد"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> بایگانی شد"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> از بایگانی خارج شد"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"اعلان‌ها خاموش شد"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"اعلان‌ها روشن شد"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"همه چیز تنظیم شد. ارسال را دوباره لمس کنید."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"«پیام‌رسانی» با موفقیت به‌عنوان برنامه پیش‌فرض پیامک تنظیم شد."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">صرف‌‌نظر از پیوست</item>
+      <item quantity="other">صرف‌‌نظر از پیوست‌ها</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"پیوست صوتی"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"پخش پیوست صوتی"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"توقف موقت"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"پیام از <xliff:g id="SENDER">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"پیام ناموفق از <xliff:g id="SENDER">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"پیام از <xliff:g id="SENDER">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"پیام ارسال نشده به <xliff:g id="CONTACT">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"ارسال پیام به <xliff:g id="CONTACT">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"پیام ناموفق به <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"پیام به <xliff:g id="CONTACT">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"پیام ناموفق از <xliff:g id="SENDER">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>. ‏<xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"پیام از <xliff:g id="SENDER">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>. ‏<xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"پیام ارسال نشده به <xliff:g id="GROUP">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"ارسال پیام به <xliff:g id="GROUP">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"پیام ناموفق به <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"پیام به <xliff:g id="GROUP">%1$s</xliff:g>: ‏<xliff:g id="MESSAGE">%2$s</xliff:g>. زمان: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"پیام ناموفق. برای امتحان مجدد، لمس کنید."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"مکالمه با <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"حذف موضوع"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"فیلم‌برداری"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ضبط تصویر ثابت"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"عکس گرفتن"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"شروع فیلم‌برداری"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"تغییر به دوربین تمام صفحه"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"جابه‌جایی بین دوربین جلو و عقب"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"توقف ضبط و پیوست ویدیو"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"توقف ضبط ویدیو"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"عکس‌های «پیام‌رسانی»"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> عکس در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> عکس در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ویدیو در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ویدیو در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> پیوست در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> پیوست در آلبوم «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ذخیره شد</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> پیوست در «دانلودها» ذخیره شد</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> پیوست در «دانلودها» ذخیره شد</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one">‏<xliff:g id="QUANTITY_1">%d</xliff:g> پیوست ذخیره شد</item>
+      <item quantity="other">‏<xliff:g id="QUANTITY_1">%d</xliff:g> پیوست ذخیره شد</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">‏<xliff:g id="QUANTITY_1">%d</xliff:g> پیوست ذخیره نشد</item>
+      <item quantity="other">‏<xliff:g id="QUANTITY_1">%d</xliff:g> پیوست ذخیره نشد</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"‏پیوست MMS ذخیره شد"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"تنظیمات"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"بایگانی شد"</string>
+    <string name="action_close" msgid="1840519376200478419">"بستن"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"پیشرفته"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"اشکال‌زدایی"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"اعلان‌ها"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"صدا"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"بی‌صدا"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"لرزش"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"مسدود شده"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"گزارش‌های تحویل پیامک"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"درخواست گزارش تحویل برای هر پیامکی که ارسال می‌کنید"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"بازیابی خودکار"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"‏بازیابی خودکار پیام‌های MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"بازیابی خودکار در طول رومینگ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"‏بازیابی خودکار MMS هنگام رومینگ"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"پیام‌رسانی گروهی"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"‏در صورت وجود چند گیرنده، برای ارسال یک پیام از MMS استفاده شود"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"برنامه پیامک پیش‌فرض"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"برنامه پیامک پیش‌فرض"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"شماره تلفن شما"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"نامشخص"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"صداهای پیام خروجی"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"نسخه‌برداری پیامک"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"نسخه‌برداری اطلاعات خام پیامک دریافتی در فایل فضای ذخیره‌سازی خارجی"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"‏نسخه‌برداری MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"‏نسخه‌برداری از اطلاعات خام MMS دریافتی در فایل فضای ذخیره‌سازی خارجی"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"هشدارهای بی‌سیم"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"گزینه‌های پیام"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"کپی کردن نوشتار"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"مشاهده جزئیات"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"حذف"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"بازارسال"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"جزئیات پیام"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"نوع: "</string>
+    <string name="text_message" msgid="7415419755252205721">"پیامک"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"پیام چندرسانه‌ای"</string>
+    <string name="from_label" msgid="1947831848146564875">"از: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"به: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ارسال شده: "</string>
+    <string name="received_label" msgid="4442494712757995203">"دریافت شده: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"موضوع: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"اندازه: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"اولویت: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"سیم‌کارت: "</string>
+    <string name="priority_high" msgid="728836357310908368">"زیاد"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"عادی"</string>
+    <string name="priority_low" msgid="7398724779026801851">"کم"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"سیم‌کارت <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"مخفی کردن آدرس فرستنده"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"نمی‌توانید در حال بارگیری پیوست‌ها، پیام ارسال کنید."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"پیوست بارگیری نمی‌شود. دوباره امتحان کنید."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"شبکه آماده نیست. دوباره امتحان کنید."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"حذف نوشتار"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"جابه‌جایی بین وارد کردن نوشتار و عدد"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"افزودن شرکت‌کننده‌های بیشتر"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"تأیید شرکت‌کنندگان"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"شروع مکالمه جدید"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"انتخاب این مورد"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"پخش ویدیو"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"افراد و گزینه‌ها"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"اشکال‌زدایی"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"افراد و گزینه‌ها"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"کلی"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"افراد در این مکالمه"</string>
+    <string name="action_call" msgid="6596167921517350362">"برقراری تماس تلفنی"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ارسال پیام"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"‏ارسال پیام&lt;br/&gt;&lt;small&gt;از <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ارسال عکس</item>
+      <item quantity="other">ارسال عکس‌ها</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ارسال فایل صوتی</item>
+      <item quantity="other">ارسال فایل‌های صوتی</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">ارسال ویدیو</item>
+      <item quantity="other">ارسال ویدیوها</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">ارسال کارت تماس</item>
+      <item quantity="other">ارسال کارت‌های تماس</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">ارسال پیوست</item>
+      <item quantity="other">ارسال پیوست‌ها</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">‏<xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> پیوست آماده ارسال است</item>
+      <item quantity="other">‏<xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> پیوست آماده ارسال است</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ارسال بازخورد"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"‏نمایش در فروشگاه Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"اطلاعات نسخه"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"‏نسخه %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"مجوزهای منبع باز"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"اعلان‌ها"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"به حد مجاز پیوست رسیدید"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"پیوست بارگیری نشد."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"به مخاطبین افزوده شود؟"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"افزودن مخاطب"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"موضوع"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"موضوع: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"در حال بارگیری کارت مخاطب"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"کارت مخاطب بارگیری نشد"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"مشاهده کارت مخاطب"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> مخاطب</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> مخاطب</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"کارت‌های مخاطب"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"تاریخ تولد"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"یادداشت‌ها"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"بازارسال پیام"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"پاسخ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"1+"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"پیامک غیرفعال شد"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"برای ارسال، «پیام‌رسانی» را به‌عنوان برنامه پیش‌فرض پیامک تنظیم کنید"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"«پیام‌رسانی» را به‌عنوان برنامه پیش‌فرض پیامک تنظیم کنید"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"تغییر"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"برای دریافت پیام، «پیام‌رسانی» را به‌عنوان برنامه پیش‌فرض پیامک تنظیم کنید"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"هیچ سیم‌کارت برگزیده‌ای برای ارسال پیامک‌ها انتخاب نشده است"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"مالک دستگاه این برنامه را مجاز نکرده است."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"تأیید"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"شرکت‌کننده‌های خیلی زیادی در مکالمه وجود دارد"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">مخاطب نامعتبر</item>
+      <item quantity="other">مخاطبین نامعتبر</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"تصویر دوربین بارگیری نشد"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"شما: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"پيش‌نويس"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"وقتی مکالمه جدیدی را شروع کنید، آن را در این لیست مشاهده می‌کنید"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"مکالمات بایگانی‌شده در اینجا نشان داده می‌شود"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"در حال بارگیری مکالمات…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"تصویر"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"کلیپ صوتی"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ویدیو"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"کارت ویزیت"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"واگرد"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"امتحان مجدد"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"نام یا شماره تلفن مخاطب را برای شروع یک پیام جدید وارد کنید"</string>
+    <string name="action_block" msgid="9032076625645190136">"مسدود کردن"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"مسدود کردن <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"رفع انسداد <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> مسدود شود؟"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"همچنان از این شماره پیام‌ها را دریافت می‌کنید، اما دیگر به شما اطلاع داده نمی‌شود. این مکالمه بایگانی می‌شود."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"مخاطبین مسدود شده"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"رفع انسداد"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"مخاطبین مسدود شده"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"انتخاب تصویر از کتابخانه سند"</string>
+    <string name="sending_message" msgid="6363584950085384929">"در حال ارسال پیام"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"پیام ارسال شد"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"داده شبکه تلفن همراه خاموش است. تنظیماتتان را بررسی کنید."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"در حالت هواپیما پیام‌ها ارسال نمی‌شوند"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"پیام ارسال نشد"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"پیام دانلود شد"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"داده سلولی خاموش است. تنظیماتتان را بررسی کنید."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"پیام‌ در حالت هواپیما دانلود نمی‌شود"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"پیام دانلود نشد"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"صفر"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"یک"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"دو"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"سه"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"چهار"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"پنج"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"شش"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"هفت"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"هشت"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"نه"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"ارسال پیام با <xliff:g id="CARRIERNAME">%1$s</xliff:g> امکان‌پذیر نیست، خطای <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"ارسال پیام با شرکت مخابراتی ناشناس امکان‌پذیر نیست، خطای <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"بازارسال: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"پیام ارسال نشد: سرویس در شبکه فعال نیست"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"پیام ارسال نشد: آدرس مقصد نامعتبر است"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"پیام ارسال نشد: پیام نامعتبر است"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"پیام ارسال نشد: محتوا پشتیبانی نمی‌شود"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"پیام ارسال نشد: پیام پشتیبانی نمی‌شود"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"پیام ارسال نشد: بیش از حد بزرگ است"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"پیام جدید"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"مشاهده"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"تصویر"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"برنامه مناسبی یافت نشد"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"حذف گیرنده"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"پیام جدید"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"لغو"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ویرایش نقطه دستیابی"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"تنظیم نشده"</string>
+    <string name="apn_name" msgid="1572691851070894985">"نام"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"نام نقطه دستیابی"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"پروکسی فراپیام"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"درگاه فراپیام"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"نوع نام نقطه دستیابی"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"حذف نام نقطه دستیابی"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"نام نقطه دستیابی جدید"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"ذخیره‌"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"صرف‌نظر کردن"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"فیلد نام نباید خالی باشد."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"نام نقطه دستیابی نباید خالی باشد."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"‏فیلد MCC باید ۳ رقمی باشد."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"‏فیلد MNC باید ۲ یا ۳ رقمی باشد."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"درحال بازیابی تنظیمات پیش‌فرض نام نقطه دستیابی."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"بازنشانی به پیش‌فرض"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"تنظیمات پیش‌فرض نام نقطه دستیابی بازنشانی شد."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"بدون عنوان"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"نام‌های نقطه دسترسی"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"نام‌های نقاط دستیابی"</string>
+    <string name="menu_new" msgid="8286285392706532511">"نام نقطه دستیابی جدید"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"تنظیمات نام تقطه دسترسی برای این کاربر در دسترس نیست"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"کپی در بریده‌دان؟"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"کپی"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"به <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"کلی"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"پیشرفته"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"تنظیمات کلی"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"تنظیمات پیشرفته"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"سیم کارت «<xliff:g id="SIM_NAME">%s</xliff:g>»"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ارسال پیامک‌های جداگانه به همه گیرندگان. فقط شما جواب‌ها را دریافت می‌کنید"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"‏ارسال یک MMS تکی به همه گیرندگان"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"شماره ناشناس"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"پیام جدید"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"پیام جدید."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"انتخاب سیم"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> انتخاب شد، انتخاب‌گر سیم‌کارت"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ویرایش موضوع"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"انتخاب سیم کارت یا ویرایش موضوع"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"برای ضبط کردن صدا، لمس کنید و نگه‌دارید"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"شروع مکالمه جدید"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"پیام‌رسانی"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"فهرست «پیام‌رسانی»"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"پیام‌رسانی"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"پیام جدید"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"فهرست مکالمات"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"در حال بارگیری مکالمات"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"در حال بارگیری پیام‌ها"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"مشاهده مکالمات بیشتر"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"مشاهده پیام‌های دیگر"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"مکالمه حذف شد"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"مکالمه حذف شد. لمس کنید تا مکالمه «پیام‌رسانی» دیگری نشان داده شود."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"مسدود شد"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"گشوده شد"</string>
+    <string name="db_full" msgid="8459265782521418031">"فضای ذخیره‌سازی کم است. ممکن است برخی از اطلاعات از دست بروند."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"انتخاب پیوست‌ها"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"تأیید انتخاب"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> مورد انتخاب شد"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"لطفاً یک یا چند پیوست را بردارید و دوباره امتحان کنید."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"می‌توانید سعی کنید پیامتان را ارسال کنید اما شاید تا وقتی که یک یا چند پیوست را برندارید، تحویل داده نشود."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"فقط می‌توانید یک ویدیو در هر پیام ارسال کنید. لطفاً ویدیوهای اضافی را حذف کنید و دوباره امتحان نمایید."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"«پیام‌رسانی» پیوست را بارگیری نکرد."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"در هر حال فرستاده شود"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"مکالمه را نمی‌توان شروع کرد"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g>‏ (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> انتخاب شد"</string>
+</resources>
diff --git a/res/values-fi/arrays.xml b/res/values-fi/arrays.xml
new file mode 100644
index 0000000..95d4f23
--- /dev/null
+++ b/res/values-fi/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ei aihetta"</item>
+    <item msgid="272485471009191934">"ei aihetta"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Kyllä"</item>
+    <item msgid="6049132459802288033">"Ei"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Kiitos"</item>
+    <item msgid="4881335087096496747">"Olen samaa mieltä"</item>
+    <item msgid="2422296858597420738">"Kiva"</item>
+    <item msgid="4805581752819452687">"Matkalla"</item>
+    <item msgid="4746700499431366214">"OK, palaan asiaan"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
new file mode 100644
index 0000000..a07825b
--- /dev/null
+++ b/res/values-fi/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Viestit"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Viestit"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Valitse keskustelu"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Asetukset"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Lähetä viesti"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Lisää liite"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ohje"</string>
+    <string name="welcome" msgid="2857560951820802321">"Tervetuloa"</string>
+    <string name="skip" msgid="7238879696319945853">"Ohita"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Seuraava &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Seuraava"</string>
+    <string name="exit" msgid="1905187380359981199">"Sulje"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Asetukset &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Asetukset"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Viestit tarvitsee käyttöoikeuden tekstiviesteihin, puhelimeen ja yhteystietoihin."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Voit muuttaa käyttöoikeuksia kohdassa Asetukset &gt; Sovellukset &gt; Viestit &gt; Käyttöoikeudet."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Voit muuttaa käyttöoikeuksia kohdassa Asetukset, Sovellukset, Viestit, Käyttöoikeudet."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Usein käytetyt"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Yhteystiedot"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Lähetä numeroon <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Tallenna kuva tai video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Valitse kuvia tästä laitteesta"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Tallenna ääntä"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Valitse valokuva"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Media on valittu."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Median valinta on poistettu."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> valittu"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"kuva <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"kuva"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Tallenna ääntä"</string>
+    <string name="action_share" msgid="2143483844803153871">"Jaa"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Juuri nyt"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nyt"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minuutti</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> tuntia</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> tunti</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> päivää</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> päivä</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> viikkoa</item>
+      <item quantity="one">viikko</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> kuukautta</item>
+      <item quantity="one">kuukausi</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> vuotta</item>
+      <item quantity="one">vuosi</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Luokan 0 viesti"</string>
+    <string name="save" msgid="5081141452059463572">"Tallenna"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Laitteen tila on vähissä. Viestit poistaa automaattisesti vanhempia viestejä vapauttaakseen tilaa."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Tallennustila vähissä"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Viestit ei ehkä lähetä tai vastaanota viestejä ennen kuin laitteessa on enemmän vapaata tilaa."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Tekstiviestien tallennustila on vähissä. Harkitse viestien poistamista."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Vahvista puhelinnumerosi"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Tekemällä tämän kertaluontoisen vaiheen varmistat, että Viestit toimittaa ryhmäviestisi oikein."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Puhelinnumero"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Poista kaikki mediaa sisältävät viestit"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Poista viestit, joiden ikä on yli <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Poista automaattisesti viestit, jotka ovat vanhempia kuin <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ohita"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Poistetaanko kaikki mediaa sisältävät viestit?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Poistetaanko viestit, jotka ovat vanhempia kuin <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Poistetaanko viestit, jotka ovat vanhempia kuin <xliff:g id="DURATION">%s</xliff:g>, ja otetaanko automaattinen poisto käyttöön?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sanoi"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Sinä sanoit"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Viesti käyttäjältä <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Lähetit viestin"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Lähetetään…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ei lähetetty. Yritä uudelleen koskettamalla."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ei lähetetty. Yritetään uudelleen…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Lähetä uudelleen tai poista"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Ota yhteyttä hätäpalveluihin soittamalla äänipuhelu. Tekstiviestiäsi ei voida toimittaa tällä hetkellä."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Epäonnistui"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Uusi multimediaviesti ladattavissa"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Uusi multimediaviesti"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Lataus epäonnistui"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Yritä uudelleen koskettamalla"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Lataa koskettamalla"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Lataa tai poista"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Ladataan…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Viesti on vanhentunut tai ei ole käytettävissä"</string>
+    <string name="mms_info" msgid="3402311750134118165">"koko: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, vanhenee: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Ei voi lähettää. Vastaanottaja ei kelpaa."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Palvelua ei ole aktivoitu verkossa"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Ei voitu lähettää verkkovian takia"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Viesti on vanhentunut tai ei ole käytettävissä"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Ei aihetta)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Tuntematon lähettäjä"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Toimitettu"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Lähettäjän <xliff:g id="FROM">%2$s</xliff:g> viestin <xliff:g id="SUBJECT">%1$s</xliff:g> lataaminen epäonnistui."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Tietokantatoimintoa ei voi suorittaa: muisti on vähissä"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Viestiä ei lähetetty"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Joitakin viestejä ei lähetetty Viesteissä."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> viestiä <xliff:g id="CONVERSATIONS">%d</xliff:g> keskustelussa</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> viesti yhdessä keskustelussa</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Viestiä ei ladattu."</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Joitakin viestejä ei ladattu Viesteissä."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> viestiä <xliff:g id="CONVERSATIONS">%d</xliff:g> keskustelussa</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> viesti yhdessä keskustelussa</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Viestiä numeroon <xliff:g id="NUMBER">%1$s</xliff:g> ei lähetetty."</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Ota yhteyttä hätäpalveluihin soittamalla äänipuhelu. Tekstiviestiäsi numeroon <xliff:g id="NUMBER">%1$s</xliff:g> ei voida toimittaa tällä hetkellä."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> uutta viestiä</item>
+      <item quantity="one">Uusi viesti</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Käynnistä"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera ei käytettävissä"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera ei käytettävissä"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Videon kaappaus ei käytettävissä"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Mediaa ei voi tallentaa"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Kuvan ottaminen ei onnistu."</string>
+    <string name="back" msgid="1477626055115561645">"Edellinen"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arkistoitu"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Poista"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkistoi"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Poista arkistosta"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Poista ilmoitukset käytöstä"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Ota ilmoitukset käyttöön"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Lisää kontakti"</string>
+    <string name="action_download" msgid="7786338136368564146">"Lataa"</string>
+    <string name="action_send" msgid="377635240181672039">"Lähetä"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Poista"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Poistetaanko tämä viesti?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tätä toimintoa ei voi kumota."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Poista"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Poistetaanko nämä keskustelut?</item>
+      <item quantity="one">Poistetaanko tämä keskustelu?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Poista"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Peruuta"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Vastaanottaja"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Valitse useita kuvia"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Vahvista valinta"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Ääntä ei voi tallentaa. Yritä uudelleen."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Ääntä ei voi toistaa. Yritä uudelleen."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Ääntä ei voitu tallentaa. Yritä uudelleen."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Kosketa pitkään"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Kuva"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Äänileike"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Yhteystietokortti"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Lataa"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Vastaa tekstiviestitse"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Vastaa MMS-viestillä"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Vastaa"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> osallistujaa</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> osallistuja</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Minä"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Yhteystieto estetty ja arkistoitu"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Yhteystiedon esto on poistettu, ja se on poistettu arkistosta."</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arkistoitua"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> poistettiin arkistosta"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Ilmoitukset on poistettu käytöstä."</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Ilmoitukset on otettu käyttöön."</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Kaikki valmiina. Kosketa Lähetä uudelleen."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Viestit asetettiin oletustekstiviestisovellukseksi."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Hylkää liitteet</item>
+      <item quantity="one">Hylkää liite</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Ääniliite"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Toista ääniliite"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Tauko"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Viesti lähettäjältä <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Epäonnistunut viesti lähettäjältä <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Viesti lähettäjältä <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Lähettämätön viesti vastaanottajalle <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Lähetetään viestiä vastaanottajalle <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Epäonnistunut viesti vastaanottajalle <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Viesti vastaanottajalle <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Epäonnistunut viesti lähettäjältä <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Viesti lähettäjältä <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Lähettämätön viesti vastaanottajalle <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Lähetetään viestiä vastaanottajalle <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Epäonnistunut viesti vastaanottajalle <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Viesti vastaanottajalle <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Aika: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Viesti epäonnistui. Yritä uudelleen koskettamalla."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Keskustelu henkilöiden <xliff:g id="PARTICIPANTS">%s</xliff:g> kanssa"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Poista aihe"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Tallenna video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Ota kuva"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Ota kuva"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Aloita videon tallentaminen"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Siirry koko näytön kameraan"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Vaihda etu- ja takakameran välillä"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Lopeta tallennus ja liitä video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Lopeta videon tallentaminen"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Viestien valokuvat"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> valokuvaa tallennettu albumiin <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> valokuva tallennettu albumiin <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videota tallennettu albumiin <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video tallennettu albumiin <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> liitettä tallennettu albumiin <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> liite tallennettu albumiin <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> liitettä tallennettu Lataukset-kansioon</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> liite tallennettu Lataukset-kansioon</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> liitettä tallennettiin</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> liite tallennettiin.</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> liitteen tallentaminen epäonnistui.</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> liitteen tallentaminen epäonnistui.</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Multimedialiite tallennettiin"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Asetukset"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arkistoitu"</string>
+    <string name="action_close" msgid="1840519376200478419">"Sulje"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Multimediaviesti"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Lisäasetukset"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Vianetsintä"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Ilmoitukset"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ääni"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Äänetön"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Värinä"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Estetty"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Tekstiviestin lähetystiedot"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Pyydä lähetystiedot kaikista lähettämistäsi tekstiviesteistä"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automaattilataus"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Lataa MMS-viestit automaattisesti"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automaattilataus roaming-tilassa"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Hae MMS-viestit automaattisesti roaming-tilassa."</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Ryhmäviestit"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Jaa yksi multimediaviesti useille vastaanottajille"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Oletusarvoinen tekstiviestisovellus"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Oletusarvoinen tekstiviestisovellus"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Puhelinnumerosi"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Tuntematon"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Lähtevien viestien äänet"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Tekstiviestivedos"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Vedosta vastaanotetut tekstiviestien raakatiedot ulkoiseen tallennustiedostoon"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS-vedos"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Vedosta vastaanotetut MMS-raakatiedot ulkoiseen tallennustiedostoon"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Langattoman verkon ilmoitukset"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Viestiasetukset"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopioi teksti"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Näytä tiedot"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Poista"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Lähetä edelleen"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Viestin tiedot"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tyyppi: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Tekstiviesti"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimediaviesti"</string>
+    <string name="from_label" msgid="1947831848146564875">"Lähettäjä: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Vastaanottaja: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Lähetetty: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Vastaanotettu: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Aihe: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Koko: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Tärkeys: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-kortti: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Korkea"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normaali"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Matala"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-kortti <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Piilotettu lähettäjän osoite"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Viestiä ei voi lähettää liitetiedostojen latauksen aikana."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Liitettä ei voi ladata. Yritä uudelleen."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Verkko ei ole valmis. Yritä uudelleen."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Poista teksti"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Vaihda tekstin ja numeroiden syötön välillä"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Lisää osallistujia"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Vahvista osallistujat"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Aloita uusi keskustelu"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Valitse tämä"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Katso video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Henkilöt ja asetukset"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Vianetsintä"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Henkilöt ja asetukset"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Yleiset"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Keskustelun osallistujat"</string>
+    <string name="action_call" msgid="6596167921517350362">"Soita puhelu"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Lähetä viesti"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Lähetä viesti&lt;br/&gt;&lt;small&gt;kortilta <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Lähetä kuvia</item>
+      <item quantity="one">Lähetä kuva</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Lähetä äänitiedostoja</item>
+      <item quantity="one">Lähetä äänitiedosto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Lähetä videoita</item>
+      <item quantity="one">Lähetä video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Lähetä yhteystietokortteja</item>
+      <item quantity="one">Lähetä yhteystietokortti</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Lähetä liitteitä</item>
+      <item quantity="one">Lähetä liite</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> liitettä valmiina lähetettäväksi</item>
+      <item quantity="one">Yksi liite valmiina lähetettäväksi</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Lähetä palautetta"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Näytä Google Play Kaupassa"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versiotiedot"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versio %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Avoimen lähdekoodin käyttöluvat"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Ilmoitukset"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Liitetiedostojen enimmäisraja on saavutettu."</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Liitetiedoston lataaminen epäonnistui."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Lisätäänkö yhteystietoihin?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Lisää yhteystieto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Aihe"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Aihe: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Ladataan yhteystietokorttia"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Yhteystietokorttia ei voitu ladata:"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Näytä yhteystietokortti"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> yhteystietoa</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> yhteystieto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Yhteystietokortit"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Syntymäpäivä"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Muistiinpanot"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Lähetä viesti edelleen"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Vastaa"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Tekstiviestit on poistettu käytöstä"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Voit lähettää valittuasi Viestit oletustekstiviestisovellukseksi."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Aseta Viestit oletustekstiviestisovellukseksi."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Vaihda"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Voit vastaanottaa viestejä valittuasi Viestit oletustekstiviestisovellukseksi."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ensisijaista SIM-korttia ei ole valittu tekstiviestien lähettämiselle"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Laitteen omistaja ei ole myöntänyt lupaa tälle sovellukselle."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Keskustelussa on liian monta osallistujaa"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Virheelliset yhteystiedot</item>
+      <item quantity="one">Virheellinen yhteystieto</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kamerakuvaa ei voitu ladata"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Sinä: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Luonnos"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Uudet keskustelut on lueteltu tässä"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arkistoidut keskustelut näkyvät tässä"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Ladataan keskusteluja…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Kuva"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Äänileike"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Yhteystietokortti"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Multimediaviesti"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Kumoa"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Yritä uudelleen"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Aloita uusi viesti antamalla yhteystiedon nimi tai puhelinnumero"</string>
+    <string name="action_block" msgid="9032076625645190136">"Estä"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Estä <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Kumoa esto: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Estetäänkö <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Saat edelleen viestejä tästä numerosta, mutta et enää ilmoituksia. Tämä keskustelu arkistoidaan."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Estetyt yhteystiedot"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"KUMOA ESTO"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Estetyt yhteystiedot"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Valitse kuva dokumenttikirjastosta"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Lähetetään viestiä"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Viesti lähetetty"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Matkapuhelindata on kytketty pois. Tarkista asetukset."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Viestejä ei voi lähettää lentokonetilassa"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Viestiä ei voitu lähettää"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Viesti ladattu"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Matkapuhelindata on kytketty pois. Tarkista asetukset."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Viestejä ei voi ladata lentokonetilassa."</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Viestin lataaminen epäonnistui."</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nolla"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Yksi"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Kaksi"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Kolme"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Neljä"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Viisi"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Kuusi"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Seitsemän"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Kahdeksan"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Yhdeksän"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Viestin lähettäminen operaattorin <xliff:g id="CARRIERNAME">%1$s</xliff:g> kautta ei onnistunut. Virhe <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Viestin lähettäminen tuntemattoman operaattorin kautta ei onnistunut. Virhe <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Vl: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Viestiä ei lähetetty: palvelu ei ole käytössä verkossa"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Viestiä ei lähetetty: virheellinen kohdeosoite"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Viestiä ei lähetetty: virheellinen viesti"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Viestiä ei lähetetty: sisältöä ei tueta"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Viestiä ei lähetetty: viestiä ei tueta"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Viestiä ei lähetetty: liian suuri"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Uusi viesti"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Näytä"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Kuva"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Sopivaa sovellusta ei löytynyt"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Poista vastaanottaja"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Uusi viesti"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Peruuta"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Muokkaa tukiasemaa"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ei asetettu"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nimi"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Multimediaviestien välityspalvelin"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Multimediaviestien portti"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-tyyppi"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Poista APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Uusi APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Tallenna"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Hylkää"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Nimi-kenttä ei voi olla tyhjä."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ei voi olla tyhjä."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-kentän arvon oltava kolminumeroinen."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-kentän arvon on oltava kaksi- tai kolminumeroinen."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Palautetaan APN-oletusasetuksia"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Palauta oletukseksi"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"APN-oletusasetukset on palautettu."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Nimetön"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Tukiasemien nimet"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN:t"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Uusi APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Tämä käyttäjä ei voi käyttää APN-asetuksia"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopioidaanko leikepöydälle?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopioi"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"vastaanottaja: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Yleiset"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Lisäasetukset"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Yleiset asetukset"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Lisäasetukset"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"<xliff:g id="SIM_NAME">%s</xliff:g> SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Lähetä oma tekstiviesti kullekin vastaanottajalle. Vain sinä saat vastaukset."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Lähetä yksi MMS-viesti kaikille vastaanottajille"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Tuntematon numero"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Uusi viesti"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Uusi viesti."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-valitsin"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> valittu, SIM-valitsin"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Muokkaa aihetta"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Valitse SIM tai muokkaa aihetta"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Nauhoita ääntä koskettamalla pitkään"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Aloita uusi keskustelu."</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Viestit"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Viestit-luettelo"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Viestit"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Uusi viesti"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Keskusteluluettelo"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Ladataan keskusteluja."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Ladataan viestejä."</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Näytä lisää keskusteluita."</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Näytä lisää viestejä."</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Keskustelu on poistettu."</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Keskustelu poistettu. Näytä toinen Viestit-keskustelu."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Estetty"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Esto kumottu"</string>
+    <string name="db_full" msgid="8459265782521418031">"Tallennustila on vähissä. Tietoja voi kadota."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Valitse liitteet"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Vahvista valinta"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> valittu"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Poista yksi tai useampi liitetiedosto ja yritä uudelleen."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Voit yrittää lähettää viestin, mutta sitä ei ehkä toimiteta ennen kuin olet poistanut yhden tai useamman liitetiedoston."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Voit lähettää vain yhden videon viestiä kohden. Poista ylimääräiset videot ja yritä uudelleen."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Viestit ei pystynyt lataamaan liitetiedostoa."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Lähetä silti"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Keskustelun aloittaminen epäonnistui"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> valittu"</string>
+</resources>
diff --git a/res/values-fr-rCA/arrays.xml b/res/values-fr-rCA/arrays.xml
new file mode 100644
index 0000000..05d76fb
--- /dev/null
+++ b/res/values-fr-rCA/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sans objet"</item>
+    <item msgid="272485471009191934">"aucun objet"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Oui"</item>
+    <item msgid="6049132459802288033">"Non"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hé hé"</item>
+    <item msgid="2611328818571146775">"Merci"</item>
+    <item msgid="4881335087096496747">"J\'accepte"</item>
+    <item msgid="2422296858597420738">"Bien"</item>
+    <item msgid="4805581752819452687">"En chemin"</item>
+    <item msgid="4746700499431366214">"OK, je te réponds plus tard"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..a626832
--- /dev/null
+++ b/res/values-fr-rCA/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messagerie"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messagerie"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Sélectionner la conversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Paramètres"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Envoyer un message"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Ajouter une pièce jointe"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Aide"</string>
+    <string name="welcome" msgid="2857560951820802321">"Bienvenue"</string>
+    <string name="skip" msgid="7238879696319945853">"Ignorer"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Suivant &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Suivant"</string>
+    <string name="exit" msgid="1905187380359981199">"Quitter"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Paramètres &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Paramètres"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Vous devez accorder à l\'application Messagerie des autorisations d\'accès aux messages, au téléphone et aux contacts."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Vous pouvez modifier les autorisations dans Paramètres &gt; Applications &gt; Messagerie &gt; Autorisations."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Vous pouvez modifier les autorisations dans Paramètres &gt; Applications &gt; Messagerie &gt; Autorisations."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Fréquents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tous les contacts"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Envoyer à <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Prendre des photos ou filmer une vidéo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Choisir des images de cet appareil"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Enregistrer des fichiers audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Choisir une photo"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Support sélectionné."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Support désélectionné."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> sélectionné(s)"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"Image : <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"image"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Enregistrer des fichiers audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Partager"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"À l\'instant"</string>
+    <string name="posted_now" msgid="867560789350406701">"Maintenant"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> heure</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> heures</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> jour</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> jours</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> semaine</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semaines</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mois</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mois</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> an</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ans</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Message de catégorie 0"</string>
+    <string name="save" msgid="5081141452059463572">"Enregistrer"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"L\'appareil manque d\'espace. Pour en libérer, les messages de l\'application Messagerie les plus anciens seront automatiquement supprimés."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"L\'espace de stockage est presque plein"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Il est possible que vous ne puissiez pas envoyer ni recevoir de messages dans l\'application Messagerie jusqu\'à ce que votre appareil ait plus d\'espace libre."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Stockage limité pour les textos. Vous devrez peut-être supprimer des messages."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirmez votre numéro de téléphone"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Cette étape unique permet de garantir que vos messages de groupe sont correctement envoyés dans Messagerie."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numéro de téléphone"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Supprimer tous les messages avec du contenu multimédia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Supprimer les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Suppression automatique des messages de plus de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorer"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Supprimer tous les messages avec contenu multimédia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Supprimer les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Supprimer les messages de plus de <xliff:g id="DURATION">%s</xliff:g> et activer la suppression automatique?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> a dit"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Vous avez dit"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Message de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Vous avez envoyé un message"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Envoi en cours..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Message non envoyé. Touchez ici pour réessayer."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Message non envoyé. Nouvelle tentative en cours..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Renvoyer ou supprimer"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Veuillez appeler les services d\'urgence. Impossible d\'envoyer votre texto pour l\'instant."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Échec"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nouveau message multimédia à télécharger"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nouveau message multimédia"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Échec du téléchargement"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Touchez ici pour réessayer"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Touchez ici pour lancer le téléchargement."</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Télécharger ou supprimer"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Téléchargement en cours..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Le message a expiré ou n\'est plus disponible."</string>
+    <string name="mms_info" msgid="3402311750134118165">"taille : <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, date d\'expiration : <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Impossible d\'envoyer le message. Destinataire non valide."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Ce service n\'est pas activé sur le réseau"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Impossible d\'envoyer le message en raison d\'un problème de réseau"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Le message est expiration ou n\'est plus disponible."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Aucun objet)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Expéditeur inconnu"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Distribué"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Impossible de télécharger le message « <xliff:g id="SUBJECT">%1$s</xliff:g> » de l\'utilisateur suivant : <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Impossible d\'effectuer cette opération dans la base de données. Mémoire insuffisante."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Le message n\'a pas été envoyé"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Certains messages n\'ont pas été envoyés dans Messagerie"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> message dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Message non téléchargé"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Certains messages n\'ont pas été téléchargés dans Messagerie"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> message dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Échec de l\'envoi du message à <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Veuillez appeler les services d\'urgence. Impossible d\'envoyer votre texto au numéro <xliff:g id="NUMBER">%1$s</xliff:g> pour l\'instant."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> nouveau message</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nouveaux messages</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Démarrer"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"L\'appareil photo n\'est pas disponible"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"L\'appareil photo n\'est pas disponible"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"L\'enregistrement vidéo n\'est pas disponible"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Impossible d\'enregistrer le média"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Impossible de prendre la photo."</string>
+    <string name="back" msgid="1477626055115561645">"Précédent"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivée"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Supprimer"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archiver"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Annuler l\'archivage"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Désactiver les notifications"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activer les notifications"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Ajouter un contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"Télécharger"</string>
+    <string name="action_send" msgid="377635240181672039">"Envoyer"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Supprimer"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Supprimer ce message?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Cette action ne peut être annulée."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Supprimer"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Supprimer cette conversation?</item>
+      <item quantity="other">Supprimer ces conversations?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Supprimer"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Annuler"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"À"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Sélectionner plusieurs images"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmer la sélection"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Impossible d\'enregistrer l\'audio. Veuillez réessayer."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Impossible de lire l\'audio. Veuillez réessayer."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Impossible d\'enregistrer l\'audio. Veuillez réessayer."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Maintenez le doigt ici"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Image"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Extrait audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vidéo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Fiche de contact"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Télécharger"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Répondre par texto"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Rép. m. multim."</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Répondre"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> participant</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Moi"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact bloqué et archivé"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contact débloqué et archivage annulé"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archivée(s)"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Archivage annulé de <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Les notifications sont désactivées"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Les notifications sont activées"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Tout est prêt. Touchez « Envoyer » de nouveau."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"L\'application Messagerie a été définie comme application de messagerie par défaut."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Supprimer la pièce jointe</item>
+      <item quantity="other">Supprimer les pièces jointes</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Contenu audio joint"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Jouer le contenu audio joint"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Échec de la réception du message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Message non envoyé à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Envoi du message à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Échec de l\'envoi du message à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Message à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Échec de la réception du message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Message non envoyé à : <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Envoi du message à <xliff:g id="GROUP">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Échec de l\'envoi du message à <xliff:g id="GROUP">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Message à <xliff:g id="GROUP">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Échec du message. Touchez pour réessayer."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversation avec <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Supprimer l\'objet"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Filmer une vidéo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturer une image fixe"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Prendre une photo"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Lancer l\'enregistrement vidéo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Activer le mode plein écran de l\'appareil photo"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Basculer entre l\'appareil photo avant et arrière"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Arrêter l\'enregistrement et joindre la vidéo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Arrêter l\'enregistrement vidéo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Photos de Messagerie"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> photo enregistrée dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> photos enregistrées dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> vidéo enregistrée dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vidéos enregistrées dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> pièce jointe enregistrée dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> pièces jointes enregistrées dans l\'album « <xliff:g id="ALBUMNAME_3">%s</xliff:g> »</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe enregistrée dans le dossier « Téléchargements »</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes enregistrées dans le dossier « Téléchargements »</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe enregistrée</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes enregistrées</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Impossible d\'enregistrer <xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe</item>
+      <item quantity="other">Impossible d\'enregistrer <xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"La pièce jointe du message multimédia a été enregistrée"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Paramètres"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivée"</string>
+    <string name="action_close" msgid="1840519376200478419">"Fermer"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Message multimédia"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avancés"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Déboguer"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifications"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Son"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Mode silencieux"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibreur"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqué"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Accusés de réception des messages texte"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Demander un accusé de réception pour chaque texto envoyé"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Récupération automatique"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Récupérer automatiquement les messages multimédias"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Récupération auto. en itinérance"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Récupérer automatiquement les messages multimédias en itinérance"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Messagerie de groupe"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utiliser la messagerie multimédia pour envoyer un message unique à plusieurs destinataires"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Application de messagerie texte par défaut"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Application de messagerie texte par défaut"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Votre numéro de téléphone"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Inconnu"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons pour les messages sortants"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Capturer les messages texte"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Capturer les données brutes reçues des messages multimédias dans un fichier de stockage externe"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Capturer les messages multimédias"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Capturer les données brutes reçues des messages multimédias dans un fichier de stockage externe"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertes par réseau sans fil"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Options relatives aux messages"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copier le texte"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Afficher les détails"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Supprimer"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Transférer"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Détails du message"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type : "</string>
+    <string name="text_message" msgid="7415419755252205721">"Message texte"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Message multimédia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De : "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"À : "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Envoyé : "</string>
+    <string name="received_label" msgid="4442494712757995203">"Reçu : "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Objet : "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Taille : "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorité : "</string>
+    <string name="sim_label" msgid="2706003016582772108">"Carte SIM : "</string>
+    <string name="priority_high" msgid="728836357310908368">"Élevée"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normale"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Faible"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"Fente SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Adresse d\'expéditeur masquée"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Impossible d\'envoyer le message pendant le chargement des pièces jointes."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Impossible de charger la pièce jointe. Veuillez réessayer."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Le réseau n\'est pas prêt. Réssayez."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Supprimer le texte"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alterner entre l\'entrée de texte et de chiffres"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Ajouter des participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmer les participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Commencer une nouvelle discussion"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Sélectionner cet article"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Lire la vidéo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Participants et options"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Déboguer"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Participants et options"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Général"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Participants à cette conversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Faire un appel"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Envoyer un message"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Envoyer un message&lt;br/&gt;&lt;small&gt;à partir de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Envoyer la photo</item>
+      <item quantity="other">Envoyer les photos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Envoyer le fichier audio</item>
+      <item quantity="other">Envoyer les fichiers audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Envoyer la vidéo</item>
+      <item quantity="other">Envoyer les vidéos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Envoyer la fiche de contact</item>
+      <item quantity="other">Envoyer les fiches de contact</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Envoyer la pièce jointe</item>
+      <item quantity="other">Envoyer les pièces jointes</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pièce jointe est prête à être envoyée</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pièces jointes sont prêtes à être envoyées</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Envoyer des commentaires"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Afficher dans la boutique Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Détails de la version"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licences de logiciels libres"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifications"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Taille maximale des pièces jointes atteinte"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Échec du chargement de la pièce jointe."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Ajouter aux contacts?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Ajouter un contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Objet"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Objet : "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g> <xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Chargement de la fiche de contact"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Impossible de charger la fiche de contact"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Afficher la fiche de contact"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> contact</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacts</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Fiches de contact"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Anniversaire"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Remarques"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Transférer le message"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Répondre"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Messagerie texte désactivée"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Pour envoyer des messages, définissez Messagerie comme application de messagerie par défaut"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Définissez Messagerie comme application de messagerie par défaut"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Modifier"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Pour recevoir des messages, vous devez définir l\'application Messagerie comme application de messagerie par défaut."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Aucune carte SIM préférée n\'a été sélectionnée pour l\'envoi des messages texte"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Cette application n\'est pas autorisée par le propriétaire de l\'appareil."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Trop de participants dans une conversation"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Contact non valide</item>
+      <item quantity="other">Contacts non valides</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Impossible de charger l\'image de l\'appareil photo"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vous : "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g> : "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Brouillon"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Lorsque vous commencez une conversation, elle s\'affiche ici"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Les conversations archivées s\'affichent ici"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Chargement des conversations en cours..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Image"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Extrait audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vidéo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Fiche de contact"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Message multimédia"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Annuler"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Réessayer"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Entrez le nom d\'un contact ou un numéro de téléphone pour commencer un nouveau message"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquer"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquer <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Débloquer <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Bloquer <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Vous continuerez à recevoir les messages envoyés par ce numéro, mais vous ne recevrez plus de notifications. Cette conversation sera archivée."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contacts bloqués"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DÉBLOQUER"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contacts bloqués"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Choisissez une image dans la bibliothèque de documents"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Envoi du message en cours..."</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Message envoyé"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Les données cellulaires sont désactivées. Vérifiez vos paramètres."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Impossible d\'envoyer des messages en mode Avion"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Le message n\'a pas pu être envoyé"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Message téléchargé"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Les données cellulaires sont désactivées. Vérifiez vos paramètres."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Impossible de télécharger des messages en mode Avion"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Le message n\'a pas pu être téléchargé"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zéro"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Un"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Deux"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trois"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quatre"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinq"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Six"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sept"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Huit"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Neuf"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Impossible d\'envoyer le message par l\'intermédiaire de <xliff:g id="CARRIERNAME">%1$s</xliff:g>. Erreur  : <xliff:g id="ERRORCODE">%2$d</xliff:g>."</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Impossible d\'envoyer le message par l\'intermédiaire d\'un fournisseur de services inconnu. Erreur : <xliff:g id="ERRORCODE">%1$d</xliff:g>."</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Tr : <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Le message n\'a pas été envoyé, car le service n\'est pas activé sur le réseau"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Le message n\'a pas été envoyé, car l\'adresse de destination est incorrecte"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Le message n\'a pas été envoyé, car il n\'est pas valide"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Le message n\'a pas été envoyé, car le contenu est incompatible"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Le message n\'a pas été envoyé, car il n\'est pas pris en charge"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Le message n\'a pas été envoyé, car il est trop gros"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nouveau message"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Afficher"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Image"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Impossible de trouver une application appropriée."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Supprimer le destinataire"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nouveau message"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Annuler"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Modifier le point d\'accès"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Non défini"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nom"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Nom du point d\'accès"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Serveur mandataire pour la messagerie multimédia"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port pour la messagerie multimédia"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Type de point d\'accès"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Supprimer le point d\'accès"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nouveau point d\'accès"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Enregistrer"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Supprimer"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Le champ « Nom » est obligatoire."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Le champ « Point d\'accès » est obligatoire."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Le champ MCC doit contenir 3 chiffres."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Le champ MNC doit contenir 2 ou 3 chiffres."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restauration des paramètres de points d\'accès par défaut en cours..."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Rétablir les valeurs par défaut"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"La réinitialisation des paramètres de points d\'accès par défaut est terminée."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sans titre"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Noms des points d\'accès"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Noms des points d\'accès"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nouveau point d\'accès"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Les paramètres de point d\'accès ne sont pas disponibles pour cet utilisateur"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copier dans le presse-papiers?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copier"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"à <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Général"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avancés"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Paramètres généraux"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Paramètres avancés"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Carte SIM « <xliff:g id="SIM_NAME">%s</xliff:g> »"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Envoyer des textos individuels à tous les destinataires. Vous seul recevrez les réponses."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Envoyer des messages multimédias individuels à tous les destinataires."</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Numéro inconnu"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nouveau message"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nouveau message."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Sélecteur de carte SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> sélectionnée, sélecteur de carte SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Modifier l\'objet"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Sélectionner une carte SIM ou modifier l\'objet"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Maintenez le doigt sur le bouton pour enregistrer des contenus audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Commencer une nouvelle discussion"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messagerie"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Liste des conversations"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messagerie"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nouveau message"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Liste des conversations"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Chargement des conversations en cours..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Messages en cours de chargement…"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Afficher plus de conversations"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Voir plus de messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversation supprimée"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"La conversation a été supprimée. Touchez pour afficher une autre conversation dans Messagerie."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqué"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Débloqué"</string>
+    <string name="db_full" msgid="8459265782521418031">"L\'espace de stockage est faible. Vous risquez de perdre certaines données."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Sélectionner les pièces jointes"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmer la sélection"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> sélectionné(s)"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Veuillez supprimer une ou plusieurs pièces jointes, puis réessayer."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Vous pouvez essayer d\'envoyer votre message, mais il risque de ne pas être remis sauf si vous supprimez une ou plusieurs pièces jointes."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Vous ne pouvez envoyer qu\'une vidéo par message. Veuillez supprimer les vidéos supplémentaires, puis réessayer."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Échec du chargement de la pièce jointe."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Envoyer quand même"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Impossible de démarrer la conversation"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> sélectionnée"</string>
+</resources>
diff --git a/res/values-fr/arrays.xml b/res/values-fr/arrays.xml
new file mode 100644
index 0000000..6bd25ad
--- /dev/null
+++ b/res/values-fr/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"aucun objet"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Oui"</item>
+    <item msgid="6049132459802288033">"Non"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Haha"</item>
+    <item msgid="2611328818571146775">"Merci"</item>
+    <item msgid="4881335087096496747">"J\'accepte."</item>
+    <item msgid="2422296858597420738">"Bien"</item>
+    <item msgid="4805581752819452687">"J\'arrive."</item>
+    <item msgid="4746700499431366214">"OK, je te réponds plus tard."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
new file mode 100644
index 0000000..b9f22af
--- /dev/null
+++ b/res/values-fr/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS/MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS/MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Sélectionner la conversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Paramètres"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Envoyer le message"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Ajouter une pièce jointe"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Aide"</string>
+    <string name="welcome" msgid="2857560951820802321">"Bienvenue"</string>
+    <string name="skip" msgid="7238879696319945853">"Ignorer"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Suivant &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Suivant"</string>
+    <string name="exit" msgid="1905187380359981199">"Quitter"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Paramètres &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Paramètres"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Vous devez accorder à l\'application de SMS/MMS des autorisations d\'accès aux SMS, au téléphone et aux contacts."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Vous pouvez modifier les autorisations dans Paramètres &gt; Applications &gt; SMS/MMS &gt; Autorisations."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Vous pouvez modifier les autorisations dans Paramètres &gt; Applications &gt; SMS/MMS &gt; Autorisations."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Fréquents"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tous les contacts"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Envoyer au <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Prendre des photos ou filmer une vidéo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Sélectionner des images sur cet appareil"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Enregistrer un fichier audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Sélectionner une photo"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Le support est sélectionné."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Le support est désélectionné."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> élément(s) sélectionné(s)"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"image <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"image"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Enregistrer un fichier audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Partager"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"À l\'instant"</string>
+    <string name="posted_now" msgid="867560789350406701">"À l\'instant"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> heure</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> heures</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> jour</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> jours</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> semaine</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semaines</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mois</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mois</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> an</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ans</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Message de catégorie 0"</string>
+    <string name="save" msgid="5081141452059463572">"Enregistrer"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"L\'appareil manque d\'espace. Pour en libérer, les messages de l\'application SMS/MMS les plus anciens seront supprimés automatiquement."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Espace de stockage bientôt saturé"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Il est possible que vous ne puissiez pas envoyer ni recevoir de messages via l\'application de SMS/MMS jusqu\'à ce que votre appareil dispose de plus d\'espace."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Espace de stockage limité. Il est possible que vous deviez supprimer des SMS."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirmez votre numéro de téléphone"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Cette étape unique permet de garantir que vos messages de groupe sont correctement envoyés via les SMS/MMS."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numéro de téléphone"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Supprimer tous les messages comportant du contenu multimédia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Supprimer les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Supprimer automatiquement les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorer"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Supprimer tous les messages comportant du contenu multimédia ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Supprimer les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g> ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Supprimer les messages datant de plus de <xliff:g id="DURATION">%s</xliff:g> et activer la suppression automatique ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> a dit"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Vous avez dit"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Expéditeur du message : <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Vous avez envoyé un message."</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Envoi en cours…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Message non envoyé. Veuillez appuyer ici pour réessayer."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Message non envoyé. Nouvelle tentative en cours…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Renvoyer ou supprimer"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Veuillez appeler les services d\'urgence. Impossible d\'envoyer votre SMS pour l\'instant."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Échec."</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nouveau MMS à télécharger"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nouveau message MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Téléchargement impossible."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Appuyer ici pour réessayer"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Appuyer ici pour lancer le téléchargement"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Télécharger ou supprimer"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Téléchargement en cours…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Le message est arrivé à expiration ou n\'est plus disponible."</string>
+    <string name="mms_info" msgid="3402311750134118165">"taille : <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration : <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Impossible d\'envoyer le message. Destinataire non valide."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Service non activé sur le réseau."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Impossible d\'envoyer le message en raison de problèmes sur le réseau."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Le message est arrivé à expiration ou n\'est plus disponible."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Aucun objet)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Expéditeur inconnu"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Distribué"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Impossible de télécharger le message \"<xliff:g id="SUBJECT">%1$s</xliff:g>\" de l\'utilisateur suivant : <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Impossible d\'effectuer cette opération dans la base de données. Mémoire insuffisante."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Le message n\'a pas été envoyé."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Certains messages n\'ont pas été envoyés via les SMS/MMS."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversation</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Message non téléchargé."</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Certains messages n\'ont pas été téléchargés via les SMS/MMS."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversation</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messages dans <xliff:g id="CONVERSATIONS">%d</xliff:g> conversations</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Échec de l\'envoi du message à <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Veuillez appeler les services d\'urgence. Impossible d\'envoyer votre SMS au numéro <xliff:g id="NUMBER">%1$s</xliff:g> pour l\'instant."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> nouveau message</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nouveaux messages</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Démarrer"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Caméra indisponible."</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Caméra indisponible."</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Enregistrement vidéo indisponible."</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Impossible d\'enregistrer le fichier multimédia."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Impossible de prendre la photo."</string>
+    <string name="back" msgid="1477626055115561645">"Retour"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivées"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Supprimer"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archiver"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Annuler l\'archivage"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Désactiver les notifications"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activer les notifications"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Ajouter un contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"Télécharger"</string>
+    <string name="action_send" msgid="377635240181672039">"Envoyer"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Supprimer"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Supprimer ce message ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Cette action est irréversible."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Supprimer"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Supprimer cette conversation ?</item>
+      <item quantity="other">Supprimer ces conversations ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Supprimer"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Annuler"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"À"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Sélectionner plusieurs images"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmer la sélection"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Impossible d\'enregistrer l\'audio. Veuillez réessayer."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Impossible de lire l\'audio. Veuillez réessayer."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Impossible d\'enregistrer l\'audio. Veuillez réessayer."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Appuyez ici de manière prolongée"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">" : "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Image"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Extrait audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vidéo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Fiche de contact"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Télécharger"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Répondre par SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Répondre par MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Répondre"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> participant</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participants</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Moi"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact bloqué et archivé"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contact débloqué et archivage annulé."</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archivée(s)"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Archivage annulé de <xliff:g id="COUNT">%d</xliff:g> conversation(s)."</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifications désactivées."</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifications activées."</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Configuration réussie. Appuyez de nouveau sur \"Envoyer\"."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"L\'application de SMS/MMS a bien été définie comme application de SMS par défaut."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Supprimer la pièce jointe</item>
+      <item quantity="other">Supprimer les pièces jointes</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Pièce jointe audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Jouer le contenu audio joint"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Message de <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Échec de la réception du message envoyé par <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Message envoyé par <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Message non envoyé à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Envoi du message à <xliff:g id="CONTACT">%1$s</xliff:g> en cours : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Échec de l\'envoi du message à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Message à <xliff:g id="CONTACT">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Échec de la réception du message envoyé par <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Message envoyé par <xliff:g id="SENDER">%1$s</xliff:g> : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Message non envoyé au groupe \"<xliff:g id="GROUP">%1$s</xliff:g>\" : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Envoi du message au groupe \"<xliff:g id="GROUP">%1$s</xliff:g>\" en cours : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Échec de l\'envoi du message au groupe \"<xliff:g id="GROUP">%1$s</xliff:g>\" : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Message au groupe \"<xliff:g id="GROUP">%1$s</xliff:g>\" : <xliff:g id="MESSAGE">%2$s</xliff:g>. Heure : <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Échec du message. Appuyez pour réessayer."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversation avec <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Supprimer l\'objet"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Enregistrer une vidéo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturer une image fixe"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Prendre une photo"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Lancer l\'enregistrement vidéo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Passer en caméra plein écran"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Passer de la caméra frontale à la caméra arrière, et inversement"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Arrêter l\'enregistrement et joindre la vidéo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Arrêter l\'enregistrement vidéo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Photos envoyées ou reçues par SMS/MMS"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> photo a été enregistrée dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> photos ont été enregistrées dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\".</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> vidéo a été enregistrée dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\".</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vidéos ont été enregistrées dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\".</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> pièce jointe a été enregistrée dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\".</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> pièces jointes ont été enregistrées dans l\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\".</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe a été enregistrée dans le dossier \"Téléchargements\".</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes ont été enregistrées dans le dossier \"Téléchargements\".</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe a été enregistrée.</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes ont été enregistrées.</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Impossible d\'enregistrer <xliff:g id="QUANTITY_1">%d</xliff:g> pièce jointe.</item>
+      <item quantity="other">Impossible d\'enregistrer <xliff:g id="QUANTITY_1">%d</xliff:g> pièces jointes.</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Pièce jointe du MMS enregistrée"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Paramètres"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivées"</string>
+    <string name="action_close" msgid="1840519376200478419">"Fermer"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Paramètres avancés"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Déboguer"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifications"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Son"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Mode silencieux"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibreur"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqué"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Accusés de réception de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Demander un accusé de réception pour chaque SMS envoyé"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Récupération automatique"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Récupérer automatiquement les MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Récupération auto. en itinérance"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Récupérer automatiquement les MMS en itinérance"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Messagerie de groupe"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utiliser un MMS pour envoyer un message unique à plusieurs destinataires"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Application SMS par défaut"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Application SMS par défaut"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Votre numéro de téléphone"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Inconnu"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons pour les messages sortants"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Créer une copie des SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Créer une copie des données SMS brutes reçues dans un fichier de stockage externe"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Créer une copie des MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Créer une copie des données MMS brutes reçues dans un fichier de stockage externe"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertes via le réseau sans fil"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Options relatives au message"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copier le texte"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Afficher les détails"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Supprimer"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Transférer"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Détails du message"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type : "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"MMS"</string>
+    <string name="from_label" msgid="1947831848146564875">"Expéditeur : "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Destinataire : "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Envoyé le : "</string>
+    <string name="received_label" msgid="4442494712757995203">"Reçu le : "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Objet : "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Taille : "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorité : "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM : "</string>
+    <string name="priority_high" msgid="728836357310908368">"Élevée"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normale"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Basse"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Adresse de l\'expéditeur masquée"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Impossible d\'envoyer le message pendant le chargement des pièces jointes."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Impossible de charger la pièce jointe. Veuillez réessayer."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Le réseau n\'est pas prêt. Veuillez réessayer."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Supprimer le texte"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alterner entre la saisie de texte et de chiffres"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Ajouter d\'autres participants"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmer les participants"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Démarrer une nouvelle conversation"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Sélectionner cet article"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Lire la vidéo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Participants et options"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Déboguer"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Participants et options"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Général"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Participants à cette conversation"</string>
+    <string name="action_call" msgid="6596167921517350362">"Passer un appel"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Envoyer un message"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Envoyer un message&lt;br/&gt;&lt;small&gt;avec la carte SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\"&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Envoyer la photo</item>
+      <item quantity="other">Envoyer les photos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Envoyer le fichier audio</item>
+      <item quantity="other">Envoyer les fichiers audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Envoyer la vidéo</item>
+      <item quantity="other">Envoyer les vidéos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Envoyer la carte de visite</item>
+      <item quantity="other">Envoyer les cartes de visite</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Envoyer la pièce jointe</item>
+      <item quantity="other">Envoyer les pièces jointes</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pièce jointe est prête à être envoyée.</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pièces jointes sont prêtes à être envoyées.</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Envoyer des commentaires"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Afficher sur le Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informations sur la version"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licences Open Source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifications"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Taille maximale des pièces jointes atteinte"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Échec du chargement de la pièce jointe."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Ajouter aux contacts ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Ajouter un contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Objet"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Objet : "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Chargement de la fiche de contact en cours…"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Impossible de charger la fiche de contact."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Afficher la fiche de contact"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> contact</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacts</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Fiches de contacts"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Anniversaire"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Remarques"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Transférer le message"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Répondre"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+ 1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS désactivés"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Pour envoyer des messages, vous devez définir l\'application de SMS/MMS comme application de SMS par défaut."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Définissez l\'application de SMS/MMS comme application de SMS par défaut."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Modifier"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Pour recevoir des messages, vous devez définir l\'application de SMS/MMS comme application de SMS par défaut."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Aucune carte SIM préférée sélectionnée pour l\'envoi de SMS."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Cette application n\'est pas autorisée par le propriétaire de l\'appareil."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Trop de participants dans une conversation."</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Contact non valide.</item>
+      <item quantity="other">Contacts non valides.</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Impossible de charger l\'image de la caméra."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vous : "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g> : "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Brouillon"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Lorsque vous commencez une conversation, elle s\'affiche ici."</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Les conversations archivées s\'affichent ici."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Chargement des conversations en cours…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Image"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Extrait audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vidéo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Fiche de contact"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Annuler"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Réessayer"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Saisissez le nom d\'un contact ou un numéro de téléphone pour commencer un nouveau message"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquer"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquer \"<xliff:g id="DESTINATION">%s</xliff:g>\""</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Débloquer \"<xliff:g id="DESTINATION">%s</xliff:g>\""</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Bloquer <xliff:g id="DESTINATION">%s</xliff:g> ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Vous continuerez à recevoir les messages envoyés par ce numéro, mais vous ne recevrez plus de notifications. Cette conversation sera archivée."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contacts bloqués"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DÉBLOQUER"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contacts bloqués"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Sélectionner une image dans la bibliothèque de documents"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Envoi du message en cours..."</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Message envoyé."</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Les données cellulaires sont désactivées. Veuillez vérifier vos paramètres."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Impossible d\'envoyer des messages en mode Avion."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Envoi du SMS impossible."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Message téléchargé."</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Les données cellulaires sont désactivées. Veuillez vérifier vos paramètres."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Impossible de télécharger les messages en mode Avion."</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Impossible de télécharger le message."</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zéro"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Un"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Deux"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trois"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quatre"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinq"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Six"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sept"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Huit"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Neuf"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Impossible d\'envoyer le message via <xliff:g id="CARRIERNAME">%1$s</xliff:g>. Erreur : <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Impossible d\'envoyer le message via un opérateur inconnu. Erreur : <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"TR : <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Le message n\'a pas été envoyé, car le service n\'est pas activé sur le réseau."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Le message n\'a pas été envoyé, car l\'adresse de destination est incorrecte."</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Le message n\'a pas été envoyé, car il n\'est pas valide."</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Le message n\'a pas été envoyé, car le contenu est incompatible."</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Le message n\'a pas été envoyé, car il est incompatible."</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Le message n\'a pas été envoyé, car il est trop volumineux."</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nouveau message"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Afficher"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Image"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Impossible de trouver une application appropriée."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Supprimer le destinataire"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nouveau message"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Annuler"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Modifier le point d\'accès"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Non défini"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nom"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy pour les MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port pour les MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Type d\'APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Supprimer l\'APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nouvel APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Enregistrer"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Supprimer"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Champ \"Nom\" obligatoire."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN obligatoire."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Le champ \"MCC\" doit contenir trois chiffres."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Le champ \"MNC\" doit contenir deux ou trois chiffres."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restauration des paramètres APN par défaut en cours…"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Rétablir les paramètres par défaut"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Les paramètres APN par défaut ont bien été réinitialisés."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sans titre"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Points d\'accès"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nouvel APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Les paramètres de point d\'accès ne sont pas disponibles pour cet utilisateur."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copier dans le Presse-papiers ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copier"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"destinataire : \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="general_settings" msgid="5409336577057897710">"Général"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Paramètres avancés"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Paramètres généraux"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Paramètres avancés"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Carte SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Envoyer des SMS individuels à tous les destinataires. Vous seul recevrez les réponses."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Envoyer un MMS unique à tous les destinataires"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Depuis un numéro inconnu"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nouveau message"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nouveau message."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Sélecteur de carte SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"\"<xliff:g id="SIM_0">%1$s</xliff:g>\" sélectionnée – Sélecteur de carte SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Modifier l\'objet"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Sélectionner une carte SIM ou modifier l\'objet"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Appuyer de manière prolongée pour enregistrer des contenus audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Lancer une conversation"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS/MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Liste des SMS/MMS"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS/MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nouveau message"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Liste des conversations"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Chargement des conversations en cours…"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Chargement des messages en cours…"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Afficher plus de conversations"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Afficher d\'autres messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversation supprimée."</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"La conversation a bien été supprimée. Appuyez pour afficher une autre conversation de SMS/MMS."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqué"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Débloqué"</string>
+    <string name="db_full" msgid="8459265782521418031">"L\'espace de stockage est faible. Vous risquez de perdre certaines données."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Sélectionner les pièces jointes"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmer la sélection"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> élément(s) sélectionné(s)"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Veuillez supprimer une ou plusieurs pièces jointes, puis réessayer."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Vous pouvez essayer d\'envoyer votre message, mais il risque de ne pas être remis sauf si vous supprimez une ou plusieurs pièces jointes."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Vous ne pouvez envoyer qu\'une vidéo par message. Veuillez supprimer les vidéos supplémentaires, puis réessayer."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Échec du chargement de la pièce jointe via les SMS/MMS."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Envoyer quand même"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Impossible de lancer la conversation."</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> sélectionnée"</string>
+</resources>
diff --git a/res/values-gl/arrays.xml b/res/values-gl/arrays.xml
new file mode 100644
index 0000000..1e43974
--- /dev/null
+++ b/res/values-gl/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sen asunto"</item>
+    <item msgid="272485471009191934">"senasunto"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Si"</item>
+    <item msgid="6049132459802288033">"Non"</item>
+    <item msgid="3084376867445867895">"Aceptar"</item>
+    <item msgid="3155097332660174689">"He he"</item>
+    <item msgid="2611328818571146775">"Grazas"</item>
+    <item msgid="4881335087096496747">"Acepto"</item>
+    <item msgid="2422296858597420738">"Excelente"</item>
+    <item msgid="4805581752819452687">"Á miña maneira"</item>
+    <item msgid="4746700499431366214">"De acordo, póñome en contacto contigo máis tarde"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
new file mode 100644
index 0000000..8a626c2
--- /dev/null
+++ b/res/values-gl/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mensaxería"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mensaxería"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Seleccionar conversa"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Configuración"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Enviar mensaxe"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Engadir un anexo"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Axuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Dámosche a benvida"</string>
+    <string name="skip" msgid="7238879696319945853">"Omitir"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Seguinte &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Seguinte"</string>
+    <string name="exit" msgid="1905187380359981199">"Saír"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Configuración &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Configuración"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mensaxería necesita permiso para acceder ás SMS, ao teléfono e aos contactos."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Podes cambiar os permisos en Configuración &gt; Aplicacións &gt; Mensaxería &gt; Permisos."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Podes cambiar os permisos en Configuración, Aplicacións, Mensaxería, Permisos."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frecuentes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Todos os contactos"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Enviar ao <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capturar fotos ou vídeo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Escoller imaxes deste dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Gravar audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Escoller foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"O ficheiro multimedia está seleccionado."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"O ficheiro multimedia non está seleccionado."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> seleccionado"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imaxe do <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imaxe"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Gravar audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Compartir"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Agora mesmo"</string>
+    <string name="posted_now" msgid="867560789350406701">"Agora"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> días</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> día</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+      <item quantity="one">unha semana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+      <item quantity="one">un mes</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> anos</item>
+      <item quantity="one">un ano</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mensaxe de clase 0"</string>
+    <string name="save" msgid="5081141452059463572">"Gardar"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Este dispositivo ten pouco espazo. Mensaxería eliminará automaticamente as mensaxes antigas para liberar espazo."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Estase esgotando o espazo de almacenamento"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"É posible que Mensaxería non envíe nin reciba mensaxes ata que haxa máis espazo dispoñible no teu dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Queda pouco almacenamento de SMS restante. É posible que precises eliminar mensaxes."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirma o teu número de teléfono"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Este paso único garantirá que Mensaxería entregue as túas mensaxes de grupo de forma adecuada."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de teléfono"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Eliminar todas as mensaxes con ficheiros multimedia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Eliminar mensaxes anteriores a <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Eliminar automaticamente mensaxes anteriores a <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorar"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Queres eliminar todas as mensaxes con ficheiros multimedia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Queres eliminar as mensaxes anteriores a <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Queres eliminar mensaxes anteriores a <xliff:g id="DURATION">%s</xliff:g> e activar a eliminación automática?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> dixo"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Dixeches"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensaxe de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Enviaches unha mensaxe"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Enviando…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Non se enviou. Toca para tentalo de novo."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Non se enviou. Tentando de novo…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Reenviar ou eliminar"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Realiza unha chamada de voz aos servizos de emerxencia. Non se puido entregar a túa mensaxe de texto neste momento."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Erro"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nova mensaxe MMS para descargar"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nova mensaxe MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Non se puido descargar"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tocar para tentalo de novo"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Tocar para descargar"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Descargar ou eliminar"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Descargando..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"A mensaxe caducou ou non está dispoñible"</string>
+    <string name="mms_info" msgid="3402311750134118165">"tamaño: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, caducidade: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Non se pode enviar. O destinatario non é válido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Servizo non activado na rede"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Non se puido enviar debido a un problema de rede"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"A mensaxe caducou ou non está dispoñible"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sen asunto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Remitente descoñecido"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregado"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Non se puido descargar a mensaxe <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Non se puido completar a operación da base de datos debido a que queda pouca memoria"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mensaxe non enviada"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Hai mensaxes non enviadas en Mensaxería"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensaxes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensaxes nunha conversa</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Non se descargou a mensaxe"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Algunhas mensaxes non se descargaron en Mensaxería"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensaxes en <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensaxes nunha conversa</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Non se enviou a mensaxe ao <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Realiza unha chamada de voz aos servizos de emerxencia. Non se puido entregar a túa mensaxe de texto ao <xliff:g id="NUMBER">%1$s</xliff:g> neste momento."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mensaxes novas</item>
+      <item quantity="one">Mensaxe nova</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Iniciar"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"A cámara non está dispoñible"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"A cámara non está dispoñible"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"A captura de vídeo non está dispoñible"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Non se pode gardar o ficheiro multimedia"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Non se pode sacar a foto"</string>
+    <string name="back" msgid="1477626055115561645">"Atrás"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arquivadas"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Eliminar"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arquivar"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Cancelar o arquivado"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desactivar notificacións"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activar notificacións"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Engadir contacto"</string>
+    <string name="action_download" msgid="7786338136368564146">"Descargar"</string>
+    <string name="action_send" msgid="377635240181672039">"Enviar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Eliminar"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Queres eliminar esta mensaxe?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Esta acción non se pode desfacer."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Eliminar"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Queres eliminar estas conversas?</item>
+      <item quantity="one">Queres eliminar esta conversa?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Eliminar"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancelar"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Seleccionar varias imaxes"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmar selección"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Non se pode gravar o audio. Téntao de novo."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Non se pode reproducir o audio. Téntao de novo."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Non se puido gardar o audio. Téntao de novo."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Mantén premido"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imaxe"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip de audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vídeo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Tarxeta de contacto"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Descargar"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Responder mediante SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Resposta MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Responde"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participante</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Eu"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contacto bloqueado e arquivado"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contacto desbloqueado e sen arquivar"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arquivada/s"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> non arquivada/s"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificacións desactivadas"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificacións activadas"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Todo listo. Toca Enviar de novo."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mensaxería estableceuse correctamente como a aplicación de SMS predeterminada."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Descartar anexos</item>
+      <item quantity="one">Descartar anexo</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Anexo de audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproducir anexo de audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausa"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensaxe de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Erro ao recibir a mensaxe de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensaxe de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Non se enviou a mensaxe a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Enviando mensaxe a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>E. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Erro ao enviar a mensaxe a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensaxe para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Erro ao recibir a mensaxe de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensaxe de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Non se enviou a mensaxe a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Enviando mensaxe a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>E. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Erro ao enviar a mensaxe a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensaxe para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Erro na mensaxe. Toca para tentalo de novo."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversa con <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Borrar asunto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capturar vídeo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturar unha imaxe estática"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Sacar foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Comezar a gravar vídeo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Cambiar á cámara de pantalla completa"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Cambiar entre a cámara dianteira e traseira"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Deter a gravación e anexar vídeo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Deter a gravación de vídeo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos de Mensaxería"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">Gardáronse <xliff:g id="QUANTITY_2">%d</xliff:g> fotos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Gardouse <xliff:g id="QUANTITY_0">%d</xliff:g> foto no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">Gardáronse <xliff:g id="QUANTITY_2">%d</xliff:g> vídeos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Gardouse <xliff:g id="QUANTITY_0">%d</xliff:g> vídeo no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">Gardáronse <xliff:g id="QUANTITY_2">%d</xliff:g> anexos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Gardouse <xliff:g id="QUANTITY_0">%d</xliff:g> anexo no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">Gardáronse <xliff:g id="QUANTITY_1">%d</xliff:g> anexos en \"Descargas\"</item>
+      <item quantity="one">Gardouse <xliff:g id="QUANTITY_0">%d</xliff:g> anexo en \"Descargas\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Gardáronse <xliff:g id="QUANTITY_1">%d</xliff:g> anexos</item>
+      <item quantity="one">Gardouse <xliff:g id="QUANTITY_0">%d</xliff:g> anexo</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Non se puideron gardar <xliff:g id="QUANTITY_1">%d</xliff:g> anexos</item>
+      <item quantity="one">Non se puido gardar <xliff:g id="QUANTITY_0">%d</xliff:g> anexo</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Anexo de MMS gardado"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Configuración"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arquivadas"</string>
+    <string name="action_close" msgid="1840519376200478419">"Pechar"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avanzado"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depuración"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificacións"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Son"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silencio"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqueado"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Informes de entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicita un informe de entrega cando envías un SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperación automática"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recupera mensaxes MMS automaticamente"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recuperación automática en itinerancia"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recuperación automática de MMS en itinerancia"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mensaxería en grupo"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utiliza MMS para enviar unha soa mensaxe cando hai varios destinatarios"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicación de SMS predeterminada"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicación de SMS predeterminada"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"O teu número de teléfono"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Descoñecido"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons de mensaxes saíntes"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Pasar SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Pasa os datos recibidos de SMS sen procesar a un ficheiro de almacenamento externo"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Pasar MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Pasa os datos recibidos de MMS sen procesar a un ficheiro de almacenamento externo"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertas sen fíos"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opcións de mensaxes"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiar texto"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ver detalles"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Eliminar"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Reenviar"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalles da mensaxe"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mensaxe de texto"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mensaxe multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Para: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviada: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Recibida: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Asunto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamaño: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioridade: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baixa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Enderezo do remitente oculto"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Non é posible enviar a mensaxe ao cargar anexos."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Non se pode cargar o anexo. Téntao de novo."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"A rede non está lista. Téntao de novo."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Eliminar texto"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Cambiar entre introducir texto e números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Engadir máis participantes"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmar participantes"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Iniciar nova conversa"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selecciona este elemento"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproducir vídeo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Persoas e opcións"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depurar"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Persoas e opcións"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Xeral"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Persoas que participan nesta conversa"</string>
+    <string name="action_call" msgid="6596167921517350362">"Facer unha chamada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Enviar mensaxe"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Envía a mensaxe&lt;br/&gt;&lt;small&gt;desde <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Enviar fotos</item>
+      <item quantity="one">Enviar foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Enviar gravacións de audio</item>
+      <item quantity="one">Enviar gravación de audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Enviar vídeos</item>
+      <item quantity="one">Enviar vídeo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Enviar tarxetas de contacto</item>
+      <item quantity="one">Enviar tarxeta de contacto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Enviar anexos</item>
+      <item quantity="one">Enviar anexo</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> anexos listos para enviar</item>
+      <item quantity="one">Un anexo listo para enviar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Dános a túa opinión"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ver en Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Información da versión"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versión %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenzas de código aberto"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificacións"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Acadouse o límite para anexos"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Non se puido cargar o anexo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Queres engadir este número aos teus contactos?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Engadir contacto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Asunto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Asunto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Cargando tarxeta de contacto"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Non se puido cargar a tarxeta de contacto"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ver tarxeta de contacto"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contactos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contacto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Tarxetas de contacto"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Aniversario"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Reenviar mensaxe"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Responder"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS desactivadas"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Establece Mensaxería como a aplicación de SMS predeterminada para enviar mensaxes"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Establece Mensaxería como a aplicación de SMS predeterminada"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Cambiar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Establece Mensaxería como a aplicación de SMS predeterminada para recibir mensaxes"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Non se seleccionou unha SIM preferida para o envío de mensaxes SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"O propietario do dispositivo non permite esta aplicación."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Aceptar"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Hai demasiados participantes nunha conversa"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Contactos non válidos</item>
+      <item quantity="one">Contacto non válido</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Non se puido cargar a imaxe da cámara"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ti: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Borrador"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Cando inicies unha nova conversa, aparecerá aquí"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"As conversas arquivadas aparecen aquí"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Cargando conversas..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imaxe"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip de audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vídeo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Tarxeta de contacto"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Desfacer"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Tentar de novo"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Introduce o nome dun contacto ou o número de teléfono para iniciar unha mensaxe nova"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquear"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Queres bloquear <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Seguirás recibindo mensaxes deste número, pero xa non se notificarán. Arquivarase esta conversa."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contactos bloqueados"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEAR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contactos bloqueados"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Escolle unha imaxe da biblioteca de documentos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Enviando a mensaxe"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mensaxe enviada"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Os datos móbiles están desactivados. Comproba a túa configuración."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Non se poden enviar mensaxes en modo avión"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Erro ao enviar a mensaxe"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mensaxe descargada"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Os datos móbiles están desactivados. Comproba a túa configuración."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Non se poden descargar mensaxes no modo avión"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Non se puido descargar a mensaxe"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Cero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Un"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dous"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tres"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Catro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinco"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sete"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Oito"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nove"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Non se pode enviar a mensaxe con <xliff:g id="CARRIERNAME">%1$s</xliff:g>. Erro: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Non se pode enviar a mensaxe cun operador descoñecido. Erro: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Rv: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mensaxe non enviada: servizo non activado na rede"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mensaxe non enviada: enderezo de destino non válido"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mensaxe non enviada: mensaxe non válida"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mensaxe non enviada: contido non compatible"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mensaxe non enviada: mensaxe non compatible"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mensaxe non enviada: demasiado longa"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mensaxe nova"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ver"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imaxe"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Non se puido encontrar unha aplicación adecuada"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Elimina o destinatario"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mensaxe nova"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancelar"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editar punto de acceso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Sen configurar"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nome"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Porto de MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo de APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Eliminar APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Novo APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Gardar"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Descartar"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"O nome do campo non pode estar baleiro."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"O APN non pode estar baleiro."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"O campo MCC debe conter 3 díxitos."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"O campo MNC debe conter 2 ou 3 díxitos."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restaurando a configuración de APN predeterminada."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Restablecer aos valores predeterminados"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Completouse o restablecemento da configuración de APN predeterminada."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sen título"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nomes do punto de acceso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Novo APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"A configuración do nome do punto de acceso non está dispoñible para este usuario"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copiar no portapapeis?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiar"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"en <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Xeral"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avanzada"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Configuración xeral"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Configuración avanzada"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Enviar mensaxes SMS individuais a todos os destinatarios. Só ti recibirás as respostas"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Enviar unha mensaxe MMS simple a todos os destinatarios"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número descoñecido"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mensaxe nova"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mensaxe nova."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selector de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Seleccionouse <xliff:g id="SIM_0">%1$s</xliff:g>, selector da SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editar asunto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Seleccionar a SIM ou editar o asunto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Tocar e manter premido para gravar audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Iniciar nova conversa"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mensaxería"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista de Mensaxería"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mensaxería"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mensaxe nova"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversas"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Cargando conversas"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Cargando mensaxes"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ver máis conversas"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ver máis mensaxes"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversa eliminada"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Eliminouse a conversa. Toca para mostrar unha conversa de Mensaxería diferente"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqueado"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desbloqueado"</string>
+    <string name="db_full" msgid="8459265782521418031">"Queda pouco espazo de almacenamento. É posible que se perdan algúns datos."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Seleccionar anexos"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmar selección"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> seleccionado/s"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Elimina un ou varios anexos e téntao de novo."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Podes probar a enviar a túa mensaxe, pero é posible que non se entregue a menos que elimines un ou varios anexos."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Só podes enviar un vídeo por mensaxe. Elimina os vídeos adicionais e téntao de novo."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mensaxería non puido cargar o anexo."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Enviar igualmente"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Non se puido iniciar a conversa"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Seleccionouse <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-gu/arrays.xml b/res/values-gu/arrays.xml
new file mode 100644
index 0000000..89975e0
--- /dev/null
+++ b/res/values-gu/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"કોઇ વિષય નહીં"</item>
+    <item msgid="272485471009191934">"વિષય નથી"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"હા"</item>
+    <item msgid="6049132459802288033">"નહીં"</item>
+    <item msgid="3084376867445867895">"ઑકે"</item>
+    <item msgid="3155097332660174689">"હીહી"</item>
+    <item msgid="2611328818571146775">"આભાર"</item>
+    <item msgid="4881335087096496747">"હું સહમત છું"</item>
+    <item msgid="2422296858597420738">"સરસ"</item>
+    <item msgid="4805581752819452687">"મારી અનુકૂળતાએ"</item>
+    <item msgid="4746700499431366214">"ઑકે, હું તમને પછી મળું છું"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
new file mode 100644
index 0000000..8d2adaf
--- /dev/null
+++ b/res/values-gu/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"મેસેજિંગ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"મેસેજિંગ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"વાર્તાલાપ પસંદ કરો"</string>
+    <string name="action_settings" msgid="1329008122345201684">"સેટિંગ્સ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"સંદેશ મોકલો"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"એક જોડાણ ઉમેરો"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"સહાય"</string>
+    <string name="welcome" msgid="2857560951820802321">"સ્વાગત છે"</string>
+    <string name="skip" msgid="7238879696319945853">"છોડી દો"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"આગલું &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"આગલું"</string>
+    <string name="exit" msgid="1905187380359981199">"બહાર નીકળો"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"સેટિંગ્સ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"સેટિંગ્સ"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"મેસેજિંગને SMS, ફોન અને સંપર્કોની પરવાનગીની જરૂર છે."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"તમે સેટિંગ્સ &gt; એપ્લિકેશન્સ &gt; મેસેજિંગ &gt; પરવાનગીઓમાં પરવાનગીઓ બદલી શકો છો."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"તમે સેટિંગ્સ, એપ્લિકેશન્સ, મેસેજિંગ, પરવાનગીઓમાં પરવાનગીઓ બદલી શકો છો."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"વારંવાર"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"તમામ સંપર્કો"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> પર મોકલો"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ચિત્રો અથવા વિડિઓ કેપ્ચર કરો"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"આ ઉપકરણથી છબીઓ પસંદ કરો"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ઑડિઓ રેકોર્ડ કરો"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ફોટો પસંદ કરો"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"મીડિયા પસંદ થયેલ છે."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"મીડિયા પસંદ કરેલ નથી."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> પસંદ કર્યાં"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"છબી <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"છબી"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ઑડિઓ રેકોર્ડ કરો"</string>
+    <string name="action_share" msgid="2143483844803153871">"શેર કરો"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"હમણાં જ"</string>
+    <string name="posted_now" msgid="867560789350406701">"હમણાં"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> મિનિટ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> મિનિટ</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> કલાક</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> કલાક</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> દિવસ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> દિવસ</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> અઠવાડિયા</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> અઠવાડિયા</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> મહિના</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> મહિના</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> વર્ષ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> વર્ષ</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"વર્ગ 0 સંદેશ"</string>
+    <string name="save" msgid="5081141452059463572">"સાચવો"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ઉપકરણ પર જગ્યા ઓછી છે. મેસેજિંગ જગ્યા ખાલી કરવા માટે જૂના સંદેશા આપમેળે કાઢી નાખશે."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"સ્ટોરેજ સ્થાન સમાપ્ત થયું"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"તમારા ઉપકરણ પર વધુ સ્થાન ઉપલબ્ધ ન થાય ત્યાં સુધી મેસેજિંગ સંદેશા મોકલી અથવા પ્રાપ્ત કરી શકશે નહીં."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ઓછો SMS સંગ્રહ. તમારે કેટલાક સંદેશા કાઢી નાખવાની જરૂર હોઈ શકે છે."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"તમારા ફોન નંબરની પુષ્ટિ કરો"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"મેસેજિંગ તમારા જૂથ સંદેશાનું યોગ્ય રીતે વિતરણ કરે તે બાબતની આ એક-વારનું પગલું ખાતરી કરશે."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ફોન નંબર"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"મીડિયા સાથેના તમામ સંદેશા કાઢી નાખો"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> કરતાં જૂનાં સંદેશા કાઢી નાખો"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> કરતા જૂના સંદેશા આપમેળે કાઢી નાખો"</string>
+    <string name="ignore" msgid="7063392681130898793">"અવગણો"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"મીડિયા સાથેના તમામ સંદેશા કાઢી નાખીએ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> કરતા જૂના સંદેશા કાઢી નાખીએ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> કરતા જૂનાં સંદેશા કાઢી નાખીએ અને આપમેળે કાઢી નાખવું ચાલુ કરીએ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> એ કહ્યું"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"તમે કહ્યું"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> તરફથી સંદેશ"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"તમે એક સંદેશ મોકલ્યો"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"મોકલી રહ્યાં છે…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"મોકલાયો નથી. ફરીથી પ્રયાસ કરવા માટે ટચ કરો."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"મોકલાયું નથી. ફરીથી પ્રયાસ કરી રહ્યું છે…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ફરીથી મોકલો અથવા કાઢી નાખો"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"કૃપા કરીને કટોકટીની સેવાઓ માટે એક વૉઇસ કૉલ કરો. તમારો ટેક્સ્ટ સંદેશ આ સમયે વિતરિત કરી શકાયો નથી."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"નિષ્ફળ થયું"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ડાઉનલોડ કરવા માટેનો નવો MMS સંદેશ"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"નવો MMS સંદેશ"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ડાઉનલોડ કરી શક્યાં નથી"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ફરીથી પ્રયત્ન કરવા ટચ કરો"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ડાઉનલોડ કરવા ટચ કરો"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ડાઉનલોડ કરો અથવા કાઢી નાખો"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ડાઉનલોડ કરી રહ્યાં છે..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"સંદેશની સમયસીમા સમાપ્ત થઈ અથવા ઉપલબ્ધ નથી"</string>
+    <string name="mms_info" msgid="3402311750134118165">"કદ: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, સમય સમાપ્તિ: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"મોકલી શકતા નથી. પ્રાપ્તકર્તા માન્ય નથી."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"નેટવર્ક પર સેવા સક્રિય કરી નથી"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"નેટવર્ક સમસ્યાને કારણે મોકલી શકાયો નથી"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"સંદેશની સમયસીમા સમાપ્ત થઈ અથવા ઉપલબ્ધ નથી"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(કોઇ વિષય નથી)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"અજાણ્યો પ્રેષક"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"વિતરિત"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> તરફનાં <xliff:g id="SUBJECT">%1$s</xliff:g> સંદેશા ડાઉનલોડ કરી શકાયા નથી."</string>
+    <string name="low_memory" msgid="5300743415198486619">"ઓછી મેમરીને કારણે ડેટાબેસ ક્રિયા પૂર્ણ કરી શકાઈ નથી"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"સંદેશ મોકલ્યો નથી"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"મેસેજિંગમાં કેટલાક સંદેશા મોકલ્યાં નથી"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> વાર્તાલાપમાં <xliff:g id="MESSAGES_1">%d</xliff:g> સંદેશા</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> વાર્તાલાપમાં <xliff:g id="MESSAGES_1">%d</xliff:g> સંદેશા</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"સંદેશ ડાઉનલોડ થયેલ નથી"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"મેસેજિંગમાં કેટલાક સંદેશા ડાઉનલોડ થયાં નથી"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> વાર્તાલાપમાં <xliff:g id="MESSAGES_1">%d</xliff:g> સંદેશા</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> વાર્તાલાપમાં <xliff:g id="MESSAGES_1">%d</xliff:g> સંદેશા</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> ને સંદેશ મોકલાયો નથી"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"કટોકટી સેવાઓને કૃપા કરીને એક વૉઇસ કૉલ કરો. <xliff:g id="NUMBER">%1$s</xliff:g> ને તમારો ટેક્સ્ટ સંદેશ આ સમયે વિતરિત કરી શકાયો નથી."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> નવા સંદેશા</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> નવા સંદેશા</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"પ્રારંભ કરો"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"કૅમેરો ઉપલબ્ધ નથી"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"કૅમેરો ઉપલબ્ધ નથી"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"વિડિઓ કેપ્ચર ઉપલબ્ધ નથી"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"મીડિયા સાચવી શકતા નથી"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ચિત્ર લઈ શકતા નથી"</string>
+    <string name="back" msgid="1477626055115561645">"પાછળ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"આર્કાઇવ કરેલા"</string>
+    <string name="action_delete" msgid="4076795795307486019">"કાઢી નાખો"</string>
+    <string name="action_archive" msgid="5437034800324083170">"આર્કાઇવ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"આર્કાઇવ.કરેલ નથી"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"સૂચનાઓ બંધ કરો"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"સૂચનાઓ ચાલુ કરો"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"સંપર્ક ઉમેરો"</string>
+    <string name="action_download" msgid="7786338136368564146">"ડાઉનલોડ કરો"</string>
+    <string name="action_send" msgid="377635240181672039">"મોકલો"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"કાઢી નાખો"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"આ સંદેશ કાઢી નાખીએ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"આ ક્રિયા પૂર્વવત્ કરી શકાતી નથી."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"કાઢી નાખો"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">આ વાર્તાલાપ કાઢી નાખીએ?</item>
+      <item quantity="other">આ વાર્તાલાપ કાઢી નાખીએ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"કાઢી નાખો"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"રદ કરો"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"પ્રતિ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"બહુવિધ છબીઓ પસંદ કરો"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"પસંદગીની પુષ્ટિ કરો"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ઑડિઓ રેકોર્ડ કરી શકાતો નથી. ફરીથી પ્રયાસ કરો."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ઑડિઓ ચલાવી શકાતો નથી. ફરીથી પ્રયાસ કરો."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ઑડિઓ સાચવી શકાયો નથી. ફરીથી પ્રયાસ કરો."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ટચ કરો અને પકડો"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ચિત્ર"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ઑડિઓ ક્લિપ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"વિડિઓ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"સંપર્ક કાર્ડ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ડાઉનલોડ કરો"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS દ્વારા જવાબ આપો"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS દ્વારા જવાબ આપો"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"જવાબ આપો"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> સહભાગીઓ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> સહભાગીઓ</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"મારા"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"સંપર્ક અવરોધિત કર્યો અને આર્કાઇવ કર્યો"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"સંપર્ક અનાવરોધિત અને અનઆર્કાઇવ કર્યો"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> આર્કાઇવ કર્યાં"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> અનઆર્કાઇવ કર્યા"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"સૂચનાઓ બંધ કરી"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"સૂચનાઓ ચાલુ કરી"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"બધું સેટ થયું. મોકલો ને ફરીથી ટચ કરો."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"ડિફોલ્ટ SMS એપ્લિકેશન તરીકે મેસેજિંગ સફળતાપૂર્વક સેટ થયું."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">જોડાણો નિકાળો</item>
+      <item quantity="other">જોડાણો નિકાળો</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ઑડિઓ જોડાણ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ઑડિઓ જોડાણ ચલાવો"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"થોભો"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> તરફથી સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> તરફથી સંદેશ નિષ્ફળ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> તરફથી સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> ને વણમોકલાયેલ સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> ને સંદેશ મોકલી રહ્યું છે: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> ને સંદેશ મોકલવું નિષ્ફળ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> ને સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> તરફથી સંદેશ નિષ્ફળ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> તરફથી સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> ને વણમોકલાયેલ સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> ને સંદેશ મોકલી રહ્યું છે: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> ને સંદેશ મોકલવું નિષ્ફળ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> ને સંદેશ: <xliff:g id="MESSAGE">%2$s</xliff:g>. સમય: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"નિષ્ફળ સંદેશ. ફરી પ્રયાસ કરવા ટચ કરો."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> સાથે વાર્તાલાપ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"વિષય કાઢી નાખો"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"વિડિઓ કેપ્ચર કરો"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"એક સ્થિર છબી કેપ્ચર કરો"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ફોટો લો"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"વિડિઓ રેકોર્ડિંગ પ્રારંભ કરો"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"પૂર્ણ સ્ક્રીન કૅમેરા પર સ્વિચ કરો"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"આગળનાં અને પાછળનાં કૅમેરા વચ્ચે સ્વિચ કરો"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"રેકોર્ડિંગ બંધ કરો અને વિડિઓ જોડો"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"વિડિઓ રેકોર્ડિંગ બંધ કરો"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"મેસેજિંગ ફોટા"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> ફોટા સાચવ્યાં</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> ફોટા સાચવ્યાં</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> વિડિઓઝ સાચવી</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> વિડિઓઝ સાચવી</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> જોડાણો સાચવ્યાં</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" આલ્બમમાં <xliff:g id="QUANTITY_2">%d</xliff:g> જોડાણો સાચવ્યાં</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one">\"ડાઉનલોડ્સ\"માં <xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણો સાચવ્યાં</item>
+      <item quantity="other">\"ડાઉનલોડ્સ\"માં <xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણો સાચવ્યાં</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણ સાચવ્યાં</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણ સાચવ્યાં</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણ સાચવી શક્યાં નથી</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> જોડાણ સાચવી શક્યાં નથી</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"સાચવેલ MMS જોડાણ"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"સેટિંગ્સ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"આર્કાઇવ કરેલા"</string>
+    <string name="action_close" msgid="1840519376200478419">"બંધ કરો"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"વિગતવાર"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ડીબગ"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"સૂચનાઓ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ધ્વનિ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"શાંત"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"વાઇબ્રેટ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"અવરોધિત"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS વિતરણ રિપોર્ટ્સ"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"તમે મોકલેલા દરેક SMS માટે વિતરણ રિપોર્ટની વિનંતી કરો"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"સ્વતઃ-પુનર્પ્રાપ્ત કરો"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS સંદેશા સ્વતઃ-પુનર્પ્રાપ્ત કરો"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"રોમિંગ સ્વતઃ-પુનર્પ્રાપ્ત કરો"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"રોમિંગ પર હોય ત્યારે MMS આપમેળે પુનર્પ્રાપ્ત કરો"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"જૂથ મેસેજિંગ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"બહુવિધ પ્રાપ્તકર્તાઓ હોય ત્યારે એક જ સંદેશ મોકલવા માટે MMS નો ઉપયોગ કરો"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ડિફોલ્ટ SMS એપ્લિકેશન"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ડિફોલ્ટ SMS એપ્લિકેશન"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"તમારો ફોન નંબર"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"અજાણ્યો"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"આઉટગોઇંગ સંદેશ ધ્વનિઓ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS ડમ્પ કરો"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"પ્રાપ્ત થયેલ SMS અપૂર્ણ ડેટાને બાહ્ય સંગ્રહ ફાઇલમાં ડમ્પ કરો"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS ડમ્પ કરો"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"પ્રાપ્ત થયેલ MMS અપૂર્ણ ડેટાને બાહ્ય સંગ્રહ ફાઇલમાં ડમ્પ કરો"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"વાયરલેસ ચેતવણીઓ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"સંદેશ વિકલ્પો"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ટેક્સ્ટ કૉપિ કરો"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"વિગતો જુઓ"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"કાઢી નાખો"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ફોરવર્ડ કરો"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"સંદેશ વિગતો"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"પ્રકાર: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ટેક્સ્ટ સંદેશ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"મલ્ટિમીડિયા સંદેશ"</string>
+    <string name="from_label" msgid="1947831848146564875">"અહીંથી: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"પ્રતિ: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"મોકલ્યું: "</string>
+    <string name="received_label" msgid="4442494712757995203">"પ્રાપ્ત કર્યુ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"વિષય: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"કદ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"પ્રાધાન્યતા: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"ઉચ્ચ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"સામાન્ય"</string>
+    <string name="priority_low" msgid="7398724779026801851">"નિમ્ન"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"પ્રેષક સરનામું છુપાયેલ છે"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"જોડાણો લોડ કરતી વખતે સંદેશ મોકલી શકાતો નથી."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"જોડાણ લોડ કરી શકાતું નથી. ફરીથી પ્રયાસ કરો."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"નેટવર્ક તૈયાર નથી. ફરીથી પ્રયાસ કરો."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ટેક્સ્ટ કાઢી નાખો"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ટેક્સ્ટ અને સંખ્યાઓ દાખલ કરવા વચ્ચે સ્વિચ કરો"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"વધુ સહભાગીઓ ઉમેરો"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"સહભાગીઓની પુષ્ટિ કરો"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"નવો વાર્તાલાપ પ્રારંભ કરો"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"આ આઇટમ પસંદ કરો"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"વિડિઓ ચલાવો"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"લોકો અને વિકલ્પો"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ડીબગ"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"લોકો અને વિકલ્પો"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"સામાન્ય"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"આ વાર્તાલાપમાંના લોકો"</string>
+    <string name="action_call" msgid="6596167921517350362">"એક કૉલ કરો"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"સંદેશ મોકલો"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; દ્વારા &lt;br/&gt;&lt;small&gt;સંદેશ મોકલો"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ફોટા મોકલો</item>
+      <item quantity="other">ફોટા મોકલો</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ઑડિઓ મોકલો</item>
+      <item quantity="other">ઑડિઓ મોકલો</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">વિડિઓઝ મોકલો</item>
+      <item quantity="other">વિડિઓઝ મોકલો</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">સંપર્ક કાર્ડ્સ મોકલો</item>
+      <item quantity="other">સંપર્ક કાર્ડ્સ મોકલો</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">જોડાણ મોકલો</item>
+      <item quantity="other">જોડાણ મોકલો</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">મોકલવા માટે <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> જોડાણ તૈયાર છે</item>
+      <item quantity="other">મોકલવા માટે <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> જોડાણ તૈયાર છે</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"પ્રતિસાદ મોકલો"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store માં જુઓ"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"સંસ્કરણ માહિતી"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"સંસ્કરણ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ઓપન સોર્સ લાઇસેંસેસ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"સૂચનાઓ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"જોડાણની મર્યાદા સુધી પહોંચ્યાં"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"જોડાણ લોડ કરવામાં નિષ્ફળ."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"સંપર્કોમાં ઉમેરીએ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"સંપર્ક ઉમેરો"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"વિષય"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"વિષય: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"સંપર્ક કાર્ડ લોડ કરી રહ્યું છે"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"સંપર્ક કાર્ડ લોડ કરી શકાયું નથી"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"સંપર્ક કાર્ડ જુઓ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> સંપર્કો</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> સંપર્કો</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"સંપર્ક કાર્ડ્સ"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"જન્મદિવસ"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"નોંધો"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"સંદેશ ફોરવર્ડ કરો"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"જવાબ આપો"</string>
+    <string name="plus_one" msgid="9010288417554932581">"પસંદ"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS અક્ષમ કરેલ છે"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"મોકલવા માટે, મેસેજિંગને ડિફોલ્ટ SMS એપ્લિકેશન તરીકે સેટ કરો"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"મેસેજિંગને ડિફોલ્ટ SMS એપ્લિકેશન તરીકે સેટ કરો"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"બદલો"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"સંદેશા પ્રાપ્ત કરવા માટે, મેસેજિંગને ડિફોલ્ટ SMS એપ્લિકેશન તરીકે સેટ કરો"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS સંદેશા મોકલવા માટે પસંદીદા SIM પસંદ કરેલ નથી"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"આ એપ્લિકેશનને ઉપકરણ માલિક દ્વારા મંજૂરી નથી."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ઑકે"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"વાર્તાલાપમાં ઘણાં બધા સહભાગીઓ છે"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">અમાન્ય સંપર્કો</item>
+      <item quantity="other">અમાન્ય સંપર્કો</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"કૅમેરા છબી લોડ કરી શકાઈ નથી"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"તમે: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ડ્રાફ્ટ"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"એકવાર તમે એક નવો વાર્તાલાપ પ્રારંભ કરી લો તે પછી, તમે તેને અહીં સૂચિબદ્ધ જોશો"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"આર્કાઇવ કરેલ વાર્તાલાપ અહીં દેખાશે"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"વાર્તાલાપ લોડ કરી રહ્યાં છે…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ચિત્ર"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ઑડિઓ ક્લિપ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"વિડિઓ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"સંપર્ક કાર્ડ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"પૂર્વવત્ કરો"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ફરી પ્રયાસ કરો"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"એક નવો સંદેશ પ્રારંભ કરવા માટે સંપર્ક નામ અથવા ફોન નંબર દાખલ કરો"</string>
+    <string name="action_block" msgid="9032076625645190136">"અવરોધિત કરો"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> ને અવરોધિત કરો"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> ને અનાવરોધિત કરો"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> ને અવરોધિત કરીએ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"તમે આ નંબરથી સંદેશા પ્રાપ્ત કરવાનું ચાલુ રાખશો પરંતુ હવેથી સૂચિત કરવામાં આવશે નહીં. આ વાર્તાલાપ આર્કાઇવ કરવામાં આવશે."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"અવરોધિત કરેલા સંપર્કો"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"અનાવરોધિત કરો"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"અવરોધિત કરેલા સંપર્કો"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"દસ્તાવેજ લાઇબ્રેરીમાંથી છબી પસંદ કરો"</string>
+    <string name="sending_message" msgid="6363584950085384929">"સંદેશ મોકલી રહ્યાં છીએ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"સંદેશ મોકલ્યો"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"સેલ્યુલર ડેટા બંધ છે. તમારી સેટિંગ્સ તપાસો."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"એરપ્લેન મોડમાં સંદેશા મોકલી શકાતા નથી"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"સંદેશ મોકલી શકાયો નથી"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"સંદેશ ડાઉનલોડ થયો"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"સેલ્યુલર ડેટા બંધ છે. તમારી સેટિંગ્સ તપાસો."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"એરપ્લેન મોડમાં સંદેશા ડાઉનલોડ કરી શકાતા નથી"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"સંદેશ ડાઉનલોડ કરી શકાયો નથી"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"શૂન્ય"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"એક"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"બે"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"ત્રણ"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"ચાર"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"પાંચ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"છ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"સાત"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"આઠ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"નવ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> સાથે સંદેશ મોકલી શકાતો નથી, ભૂલ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"અજાણ્યાં કેરીઅર સાથે સંદેશ મોકલી શકાતો નથી, ભૂલ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ફોરવર્ડ: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"સંદેશ મોકલાયો નથી: નેટવર્ક પર સેવા સક્રિય કરેલ નથી"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"સંદેશ મોકલાયો નથી: અમાન્ય લક્ષ્યસ્થાન સરનામું"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"સંદેશ મોકલાયો નથી: અમાન્ય સંદેશ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"સંદેશ મોકલાયો નથી: અસમર્થિત સામગ્રી"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"સંદેશ મોકલાયો નથી: અસમર્થિત સંદેશ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"સંદેશ મોકલ્યો નથી: ખૂબ મોટો"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"નવો સંદેશ"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"જુઓ"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"છબી"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"કોઈ યોગ્ય એપ્લિકેશન મળી શકી નથી"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"પ્રાપ્તકર્તા દૂર કરો"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"નવો સંદેશ"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"રદ કરો"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"અ‍ૅક્સેસ પોઇન્ટ સંપાદિત કરો"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"સેટ નથી"</string>
+    <string name="apn_name" msgid="1572691851070894985">"નામ"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS પ્રોક્સી"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS પોર્ટ"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN પ્રકાર"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN કાઢી નાખો"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"નવું APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"સાચવો"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"છોડી દો"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"નામ ફીલ્ડ ખાલી હોઈ શકતી નથી."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ખાલી હોઈ શકતું નથી."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ફીલ્ડ 3 અંકોની હોવી આવશ્યક છે."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ફીલ્ડ 2 અથવા 3 અંકોની હોવી આવશ્યક છે."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ડિફોલ્ટ APN સેટિંગ્સ પુનર્સ્થાપિત કરવી."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ડિફોલ્ટ પર ફરીથી સેટ કરો"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"ડિફોલ્ટ APN સેટિંગ્સ ફરીથી સેટ કરો પૂર્ણ થયું."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"મથાળા વગર"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ઍક્સેસ પોઇન્ટનું નામ"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"નવું APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"અ‍ૅક્સેસ પોઇન્ટનું નામ સેટિંગ્સ આ વપરાશકર્તા માટે ઉપલબ્ધ નથી"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ક્લિપબોર્ડ પર કૉપિ કરીએ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"કૉપિ કરો"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> પર"</string>
+    <string name="general_settings" msgid="5409336577057897710">"સામાન્ય"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"વિગતવાર"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"સામાન્ય સેટિંગ્સ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"વિગતવાર સેટિંગ્સ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"તમામ પ્રાપ્તકર્તાઓને વ્યક્તિગત SMS સંદેશાઓ મોકલો. ફક્ત તમને જ કોઇ જવાબો મળશે"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"તમામ પ્રાપ્તકર્તાઓને એક જ MMS મોકલો"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"અજાણ્યો નંબર"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"નવો સંદેશ"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"નવો સંદેશ."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM પસંદગીકર્તા"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> પસંદ કર્યા, SIM પસંદગીકર્તા"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"વિષય સંપાદિત કરો"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM પસંદ કરો અથવા વિષય સંપાદિત કરો"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ઑડિઓ રેકોર્ડ કરવા માટે ટચ કરો અને પકડો"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"નવો વાર્તાલાપ પ્રારંભ કરો"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"મેસેજિંગ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"મેસેજિંગ સૂચિ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"મેસેજિંગ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"નવો સંદેશ"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"વાર્તાલાપની સૂચિ"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"વાર્તાલાપ લોડ કરી રહ્યાં છે"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"સંદેશા લોડ કરી રહ્યું છે"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"વધુ વાર્તાલાપ જુઓ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"વધુ સંદેશા જુઓ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"વાર્તાલાપ કાઢી નખાયો"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"વાર્તાલાપ કાઢી નાખ્યો. એક ભિન્ન મેસેજિંગ વાર્તાલાપ દર્શાવવા માટે ટચ કરો"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"અવરોધિત"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"અનાવરોધિત"</string>
+    <string name="db_full" msgid="8459265782521418031">"સંગ્રહ સ્થાન ઓછું છે. કેટલોક ડેટા ખોવાઈ શકે છે."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"જોડાણો પસંદ કરો"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"પસંદગીની પુષ્ટિ કરો"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> પસંદ કર્યાં"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"કૃપા કરીને એક અથવા વધુ જોડાણો દૂર કરો અને ફરીથી પ્રયાસ કરો."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"તમે તમારો સંદેશ મોકલવાનો પ્રયાસ કરી શકો છો, પરંતુ તમે એક અથવા વધુ જોડાણો દૂર નહીં કરો ત્યાં સુધી તે વિતરિત કરવામાં આવી શકશે નહીં."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"તમે પ્રતિ સંદેશ ફક્ત એક વિડિઓ મોકલી શકો છો. કૃપા કરીને અતિરિક્ત વિડિઓઝ દૂર કરો અને ફરી પ્રયાસ કરો."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"જોડાણ લોડ કરવામાં મેસેજિંગ નિષ્ફળ."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"કોઈપણ રીતે મોકલો"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"વાર્તાલાપ પ્રારંભ કરી શકાયો નથી"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> પસંદ કરી"</string>
+</resources>
diff --git a/res/values-hi/arrays.xml b/res/values-hi/arrays.xml
new file mode 100644
index 0000000..abdcedf
--- /dev/null
+++ b/res/values-hi/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"कोई विषय नहीं"</item>
+    <item msgid="272485471009191934">"कोई विषय नहीं"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"हां"</item>
+    <item msgid="6049132459802288033">"नहीं"</item>
+    <item msgid="3084376867445867895">"ठीक"</item>
+    <item msgid="3155097332660174689">"हेहे"</item>
+    <item msgid="2611328818571146775">"धन्यवाद"</item>
+    <item msgid="4881335087096496747">"मैं सहमत हूं"</item>
+    <item msgid="2422296858597420738">"बढ़िया"</item>
+    <item msgid="4805581752819452687">"मेरे रास्ते में रहने के दौरान"</item>
+    <item msgid="4746700499431366214">"ठीक है, मैं आपसे बाद में संपर्क करूंगा/करूंगी"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
new file mode 100644
index 0000000..7e7a780
--- /dev/null
+++ b/res/values-hi/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"संदेश सेवा"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"संदेश सेवा"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"वार्तालाप चुनें"</string>
+    <string name="action_settings" msgid="1329008122345201684">"सेटिंग"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"संदेश भेजें"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"कोई अटैचमेंट जोड़ें"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"सहायता"</string>
+    <string name="welcome" msgid="2857560951820802321">"स्वागत है"</string>
+    <string name="skip" msgid="7238879696319945853">"अभी नहीं"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"अगला &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"अगला"</string>
+    <string name="exit" msgid="1905187380359981199">"बाहर निकलें"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"सेटिंग &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"सेटिंग"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"संदेश सेवा को SMS, फ़ोन और संपर्कों के लिए अनुमति की आवश्यकता होती है."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"आप अनुमतियों को सेटिंग &gt; ऐप्स &gt; संदेश सेवा &gt; अनुमतियां में बदल सकते हैं."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"आप अनुमतियों को सेटिंग, ऐप्‍स, संदेश सेवा, अनुमतियां में बदल सकते हैं."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"अक्सर"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"सभी संपर्क"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> पर भेजें"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"चित्र या वीडियो कैप्चर करें"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"इस डिवाइस के चित्र चुनें"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ऑडियो रिकॉर्ड करें"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"फ़ोटो चुनें"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"मीडिया को चुना है."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"मीडिया को नहीं चुना है."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> चुने गए"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"चित्र <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"चित्र"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ऑडियो रिकॉर्ड करें"</string>
+    <string name="action_share" msgid="2143483844803153871">"साझा करें"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"अभी-अभी"</string>
+    <string name="posted_now" msgid="867560789350406701">"अभी"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> मिनट</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनट</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> घंटे</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> घंटे</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> दिन</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> दिन</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सप्‍ताह</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सप्‍ताह</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> महीने</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> महीने</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> वर्ष</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> वर्ष</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"वर्ग 0 संदेश"</string>
+    <string name="save" msgid="5081141452059463572">"जोड़ें"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"डिवाइस में स्थान कम है. स्थान खाली करने के लिए संदेश सेवा पुराने संदेशों को अपने आप हटा देगी."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"मेमोरी स्‍थान समाप्‍त हो रहा है"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"हो सकता है कि आपके डिवाइस पर अधिक स्‍थान उपलब्‍ध होने तक संदेश सेवा संदेशों को ना भेजे या प्राप्‍त ना करे."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"कम SMS मेमोरी. आपको संदेशों को हटाने की आवश्‍यकता हो सकती है."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"अपने फ़ोन नंबर की पुष्टि करें"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"यह एक-बार का चरण यह सुनिश्चित करेगा कि संदेश सेवा आपके समूह संदेशों को ठीक से वितरित करेगी."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"फ़ोन नंबर"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"मीडिया वाले सभी संदेशों को हटाएं"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> से पुराने संदेशों को हटाएं"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> से पुराने संदेशों को स्‍वत: हटाएं"</string>
+    <string name="ignore" msgid="7063392681130898793">"अनदेखा करें"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"मीडिया वाले सभी संदेशों को हटाएं?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> से पुराने संदेशों को हटाएं?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> से पुराने संदेश हटाएं और स्‍वत: हटाना चालू करें?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"प्रेषक: <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"आपने कहा"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> की ओर से संदेश"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"आपने एक संदेश भेजा"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"भेजा जा रहा है..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"नहीं भेजा गया. पुन: प्रयास करने के लिए स्‍पर्श करें."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"नहीं भेजा गया. पुन: प्रयास किया जा रहा है…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"फिर से भेजें या हटाएं"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"कृपया आपातकालीन सेवाओं को वॉइस कॉल करें. आपका लेख संदेश इस समय वितरित नहीं किया जा सकता."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"विफल रहा"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"डाउनलोड करने के लिए नया MMS संदेश"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"नया MMS संदेश"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"डाउनलोड नहीं किया जा सका"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"पुन: प्रयास करने के लिए स्पर्श करें"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"डाउनलोड करने के लिए स्‍पर्श करें"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"डाउनलोड करें या हटाएं"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"डाउनलोड किया जा रहा है..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"संदेश की समय सीमा समाप्त हो गई या वह उपलब्ध नहीं है"</string>
+    <string name="mms_info" msgid="3402311750134118165">"आकार: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, समाप्‍ति: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"भेजा नहीं जा सकता. प्राप्‍तकर्ता मान्‍य नहीं है."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"नेटवर्क पर सेवा सक्रिय नहीं है"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"नेटवर्क समस्‍या के कारण भेजा नहीं जा सका"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"संदेश की समय सीमा समाप्त हो गई या वह उपलब्ध नहीं है"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(कोई विषय नहीं)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"अज्ञात प्रेषक"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"डिलीवर कर दिया गया"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> से <xliff:g id="SUBJECT">%1$s</xliff:g> संदेश डाउनलोड नहीं किया जा सका."</string>
+    <string name="low_memory" msgid="5300743415198486619">"कम मेमोरी के कारण डेटाबेस कार्रवाई पूर्ण नहीं किया जा सका"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"संदेश नहीं भेजा गया"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"कुछ संदेशों को संदेश सेवा में नहीं भेजा गया है"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापों में <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापों में <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"संदेश डाउनलोड नहीं किया गया"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"कुछ संदेशों को संदेश सेवा में डाउनलोड नहीं किया गया है"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापों में <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापों में <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> को संदेश नहीं भेजा गया"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"कृपया आपातकालीन सेवाओं को वॉइस कॉल करें. <xliff:g id="NUMBER">%1$s</xliff:g> को भेजा गया आपका लेख संदेश इस समय वितरित नहीं किया जा सकता."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> नए संदेश</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> नए संदेश</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"प्रारंभ करें"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"कैमरा उपलब्ध नहीं है"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"कैमरा उपलब्ध नहीं है"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"वीडियो कैप्‍चर उपलब्‍ध नहीं है"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"मीडिया सहेजा नहीं जा सकता"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"चित्र नहीं लिया जा सकता"</string>
+    <string name="back" msgid="1477626055115561645">"पीछे"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"संग्रहीत"</string>
+    <string name="action_delete" msgid="4076795795307486019">"हटाएं"</string>
+    <string name="action_archive" msgid="5437034800324083170">"संग्रहीत करें"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"संग्रह से निकालें"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"नोटिफिकेशन बंद करें"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"नोटिफिकेशन चालू करें"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"संपर्क जोड़ें"</string>
+    <string name="action_download" msgid="7786338136368564146">"डाउनलोड करें"</string>
+    <string name="action_send" msgid="377635240181672039">"भेजें"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"हटाएं"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"इस संदेश को हटाएं?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"इस क्रिया को पूर्ववत नहीं किया जा सकता."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"हटाएं"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">इन वार्तालापों को हटाएं?</item>
+      <item quantity="other">इन वार्तालापों को हटाएं?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"हटाएं"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"अभी नहीं"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"प्रति"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"एकाधिक चित्र चुनें"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"चयन की दुबारा पूछें"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ऑडियो रिकॉर्ड नहीं किया जा सकता. पुनः प्रयास करें."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ऑडियो नहीं चलाया जा सकता. पुन: प्रयास करें."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ऑडियो सहेजा नहीं जा सका. पुनः प्रयास करें."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"स्पर्श करके रखें"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"चित्र"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ऑडियो क्लिप"</string>
+    <string name="notification_video" msgid="4331423498662606204">"वीडियो"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"संपर्क कार्ड"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"डाउनलोड करें"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS के द्वारा उत्तर दें"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS से उत्तर दें"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"उत्तर दें"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> प्रतिभागी</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> प्रतिभागी</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"मुझे"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"संपर्क अवरोधित तथा संग्रहीत किया गया"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"संपर्क को अनवरोधित किया गया और संग्रह से निकाला गया"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> को संग्रहीत किया गया"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> को संग्रह से निकाला गया"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"नोटिफ़िकेशन बंद हैं"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"नोटिफ़िकेशन चालू हैं"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"बिल्‍कुल तैयार. भेजें को पुन: स्‍पर्श करें."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"संदेश सेवा को डिफ़ॉल्ट SMS ऐप के रूप में सफलतापूर्वक सेट कर दिया गया है."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">अटैचमेंट छोड़ें</item>
+      <item quantity="other">अटैचमेंट छोड़ें</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ऑडियो अटैचमेंट"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ऑडियो अटैचमेंट चलाएं"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"रोकें"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> की ओर से संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> का भेजने में विफल रहा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> का संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> को नहीं भेजा गया संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> को संदेश भेजा जा रहा है: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> को भेजने में विफल रहा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> के लिए संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> का विफल रहा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> का संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> को नहीं भेजा गया संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> को संदेश भेजा जा रहा है: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> को भेजने में विफल रहा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> के लिए संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"विफल रहा संदेश. पुन: प्रयास करने के लिए स्पर्श करें."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> के साथ बातचीत"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"विषय हटाएं"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"वीडियो कैप्चर करें"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"स्थिर चित्र कैप्चर करें"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"चित्र लें"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"वीडियो रिकॉर्ड करना प्रारंभ करें"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"पूर्ण स्क्रीन कैमरा पर स्विच करें"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"सामने और पीछे वाले कैमरे के बीच स्‍विच करें"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"रिकॉर्डिंग रोकें और वीडियो अटैच करें"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"वीडियो रिकॉर्ड करना बंद करें"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"संदेश सेवा फ़ोटो"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> फ़ोटो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजी गईं</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> फ़ोटो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजी गईं</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> वीडियो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजे गए</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> वीडियो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजे गए</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> अटैचमेंट \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजे गए</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> अटैचमेंट \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बम में सहेजे गए</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट \"डाउनलोड\" में सहेजे गए</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट \"डाउनलोड\" में सहेजे गए</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट सहेजे गए</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट सहेजे गए</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट सहेजे नहीं जा सके</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> अटैचमेंट सहेजे नहीं जा सके</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS अटैचमेंट सहेजा गया"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"सेटिंग"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"संग्रहीत"</string>
+    <string name="action_close" msgid="1840519376200478419">"बंद करें"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"अतिरिक्त सेटिंग"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"डीबग"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"नोटिफिकेशन"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ध्वनि"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"मौन"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"वाइब्रेट"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"अवरोधित"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS वितरण रिपोर्ट"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"आपके द्वारा भेजे गए प्रत्येक SMS की वितरण रिपोर्ट का अनुरोध करें"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"स्वतः पुनर्प्राप्ति"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS संदेशों को अपने आप प्राप्त करें"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"रोमिंग स्वतः पुनर्प्राप्ति"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"रोमिंग के दौरान MMS अपने आप प्राप्त करें"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"समूह संदेश सेवा"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"एक से अधिक प्राप्तकर्ता होने पर एक ही संदेश भेजने के लिए MMS का उपयोग करें"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"डिफ़ॉल्ट SMS ऐप"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"डिफ़ॉल्ट SMS ऐप"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"आपका फ़ोन नंबर"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"अज्ञात"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"आउटगोइंग संदेश ध्वनि"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS डंप करें"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"बाहरी मेमोरी फ़ाइल में प्राप्त किया गया SMS अपरिष्कृत डेटा डंप करें"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS डंप करें"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"बाहरी मेमोरी फ़ाइल में प्राप्त किया गया MMS अपरिष्कृत डेटा डंप करें"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"वायरलेस अलर्ट"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"संदेश के विकल्प"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"लेख की प्रतिलिपि बनाएं"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"विवरण देखें"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"हटाएं"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"अग्रेषित करें"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"संदेश के विवरण"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"प्रकार: "</string>
+    <string name="text_message" msgid="7415419755252205721">"लेख संदेश"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"मल्टीमीडिया संदेश"</string>
+    <string name="from_label" msgid="1947831848146564875">"प्रेषक: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"प्रति: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"भेजा गया: "</string>
+    <string name="received_label" msgid="4442494712757995203">"प्राप्त हुआ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"विषय: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"आकार: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"प्राथमिकता: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"सिम: "</string>
+    <string name="priority_high" msgid="728836357310908368">"उच्च"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"सामान्य"</string>
+    <string name="priority_low" msgid="7398724779026801851">"निम्न"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"सिम <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"प्रेषक का पता छिपाएं"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"अटैचमेंट लोड करते समय संदेश नहीं भेजा जा सकता."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"अटैचमेंट लोड नहीं किया जा सकता. पुन: प्रयास करें."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"नेटवर्क तैयार नहीं है. पुनः प्रयास करें."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"लेख हटाएं"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"लेख और संख्याएं डालने के बीच स्विच करें"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"और अधिक प्रतिभागी जोड़ें"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"प्रतिभागियों की पुष्‍टि करें"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"नई बातचीत प्रारंभ करें"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"यह आइटम चुनें"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"वीडियो चलाएं"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"लोग और विकल्प"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"डीबग"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"लोग और विकल्प"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"सामान्य"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"इस वार्तालाप में लोग"</string>
+    <string name="action_call" msgid="6596167921517350362">"कॉल करें"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"संदेश भेजें"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; से संदेश भेजें"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">फ़ोटो भेजें</item>
+      <item quantity="other">फ़ोटो भेजें</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ऑडियो भेजें</item>
+      <item quantity="other">ऑडियो भेजें</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">वीडियो भेजें</item>
+      <item quantity="other">वीडियो भेजें</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">संपर्क कार्ड भेजें</item>
+      <item quantity="other">संपर्क कार्ड भेजें</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">अटैचमेंट भेजें</item>
+      <item quantity="other">अटैचमेंट भेजें</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> अटैचमेंट भेजे जाने के लिए तैयार हैं</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> अटैचमेंट भेजे जाने के लिए तैयार हैं</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"फ़ीडबैक भेजें"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play स्टोर में देखें"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"वर्शन जानकारी"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"वर्शन %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ओपन सोर्स लाइसेंस"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"नोटिफिकेशन"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"अटैचमेंट सीमा पर पहुंच गए"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"अटैचमेंट लोड करने में विफल रहा."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"संपर्कों में जोड़ें?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"संपर्क जोड़ें"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"विषय"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"विषय: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"संपर्क कार्ड लोड हो रहा है"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"संपर्क कार्ड लोड नहीं किया जा सका"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"संपर्क कार्ड देखें"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> संपर्क</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> संपर्क</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"संपर्क कार्ड"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"जन्मदिन"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"नोट"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"संदेश अग्रेषित करें"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"जवाब दें"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS अक्षम है"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"भेजने के लिए, संदेश सेवा को डिफ़ॉल्ट SMS ऐप के रूप में सेट करें"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"संदेश सेवा को डिफ़ॉल्ट SMS ऐप के रूप में सेट करें"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"बदलें"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"संदेश प्राप्‍त करने के लिए, संदेश सेवा को डिफ़ॉल्‍ट SMS ऐप के रूप में सेट करें"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS संदेश भेजने के लिए कोई भी पसंदीदा सिम नहीं चुनी गई है"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"डिवाइस स्‍वामी द्वारा इस ऐप्स की अनुमति नहीं दी गई है."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ठीक"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"बातचीत में बहुत अधिक प्रतिभागी हैं"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">अमान्‍य संपर्क</item>
+      <item quantity="other">अमान्‍य संपर्क</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"कैमरे का चित्र लोड नहीं किया जा सका"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"आप: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ड्राफ़्ट"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"आपके द्वारा नया वार्तालाप प्रारंभ करने के बाद, वह आपको यहां सूचीबद्ध दिखाई देगा"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"संग्रहीत वार्तालाप यहां दिखाई देते हैं"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"वार्तालाप लोड हो रहे हैं…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"चित्र"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ऑडियो क्लिप"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"वीडियो"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"संपर्क कार्ड"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"वापस लाएं"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"पुन: प्रयास करें"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"नया संदेश प्रारंभ करने के लिए कोई संपर्क नाम या फ़ोन नंबर डालें"</string>
+    <string name="action_block" msgid="9032076625645190136">"अवरुद्ध करें"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> को अवरुद्ध करें"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> को अनवरोधित करें"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> को अवरोधित करें?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"आपको इस संदेश से नंबर प्राप्‍त होते रहेंगे लेकिन अब उनकी सूचना नहीं दी जाएगी. इस वार्तालाप को संग्रहीत किया जाएगा."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"अवरोधित संपर्क"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"अनवरोधित करें"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"अवरोधित संपर्क"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"दस्‍तावेज़ लाइब्रेरी से चित्र चुनें"</string>
+    <string name="sending_message" msgid="6363584950085384929">"संदेश भेजा जा रहा है"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"संदेश भेजा गया"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"सेलुलर डेटा बंद हो गया है. अपनी सेटिंग जांचें."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"हवाई जहाज़ मोड में संदेश नहीं भेजे जा सकते"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"संदेश भेजा नहीं जा सका"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"संदेश डाउनलोड किया गया"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"सेल्‍युलर डेटा बंद हो गया है. अपनी सेटिंग जांचें."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"संदेश को हवाई जहाज़ मोड में डाउनलोड नहीं किया जा सकता"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"संदेश डाउनलोड नहीं किया जा सका"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"शून्य"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"एक"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"दो"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"तीन"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"चार"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"पांच"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"छह"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"सात"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"आठ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"नौ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> के साथ संदेश नहीं भेजा जा सकता, त्रुटि <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"अज्ञात वाहक के साथ संदेश नहीं भेजा जा सकता, त्रुटि <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"अग्रेषित: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"संदेश नहीं भेजा गया: नेटवर्क पर सेवा सक्रिय नहीं है"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"संदेश नहीं भेजा गया: अमान्य गंतव्य पता"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"संदेश नहीं भेजा गया: अमान्य संदेश"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"संदेश नहीं भेजा गया: असमर्थित सामग्री"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"संदेश नहीं भेजा गया: असमर्थित संदेश"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"संदेश नहीं भेजा गया: बहुत बड़ा है"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"नया संदेश"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"देखें"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"चित्र"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"उपयुक्त ऐप्लिकेशन नहीं मिला"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"प्राप्तकर्ता को निकालें"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"नया संदेश"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"अभी नहीं"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"पहुंच बिंदु संपादित करें"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"सेट नहीं है"</string>
+    <string name="apn_name" msgid="1572691851070894985">"नाम"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS प्रॉक्‍सी"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS पोर्ट"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN प्रकार"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN हटाएं"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"नया APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"सहेजें"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"छोड़ें"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"नाम फ़ील्‍ड खाली नहीं हो सकता."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN खाली नहीं हो सकता."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC फ़ील्‍ड में 3 अंक होने चाहिए."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MCC फ़ील्‍ड में 2 या 3 अंक होने चाहिए."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"डिफ़ॉल्‍ट APN सेटिंग पुनर्स्थापित हो रही हैं."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"डिफ़ॉल्ट पर रीसेट करें"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"डिफ़ॉल्‍ट APN सेटिंग रीसेट करना पूर्ण हुआ."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"शीर्षक रहित"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"पहुंच बिंदु के नाम"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"नया APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"एैक्सेस बिंदु नाम सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"क्लिपबोर्ड पर कॉपी बनाएं?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"कॉपी बनाएं"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> पर"</string>
+    <string name="general_settings" msgid="5409336577057897710">"सामान्य"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"अतिरिक्त सेटिंस"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"सामान्य सेटिंग"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"अतिरिक्त सेटिंग"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" सिम"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"सभी प्राप्‍तकर्ताओं को व्‍यक्‍तिगत SMS संदेश भेजें. कोई भी जवाब केवल आपको प्राप्‍त होंगे"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"सभी प्राप्‍तकर्ताआें को एकल MMS भेजें"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"अज्ञात नंबर"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"नया संदेश"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"नया संदेश."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"सिम चयनकर्ता"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> चयनित, SIM चयनकर्ता"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"विषय संपादित करें"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"सिम चुनें या विषय संपादित करें"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ऑडियो रिकॉर्ड करने के लिए स्‍पर्श करके रखें"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"नई बातचीत प्रारंभ करें"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"संदेश सेवा"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"संदेश सेवा सूची"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"संदेश सेवा"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"नया संदेश"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"वार्तालाप सूची"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"बातचीत लोड हो रही हैं…"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"संदेश लोड हो रहे हैं"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"और बातचीत देखें"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"अधिक संदेश देखें"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"वार्तालाप हटा दिया गया है"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"वार्तालाप हटा दिया गया. कोई भिन्न संदेश सेवा वार्तालाप दिखाने के लिए स्पर्श करें"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"अवरोधित"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"अनवरोधित"</string>
+    <string name="db_full" msgid="8459265782521418031">"मेमोरी स्‍थान कम है. कुछ डेटा खो सकता है."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"अटैचमेंट चुनें"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"चयन की पुष्टि करें"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> चुने गए"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"कृपया एक या अधिक अटैचमेंट निकालें और पुन: प्रयास करें."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"आप अपना संदेश भेजकर देख सकते हैं, लेकिन यह तब तक वितरित नहीं होगा जब तक कि आप एक या कुछ और अटैचमेंट निकाल नहीं देते."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"आप प्रति संदेश केवल एक वीडियो भेज सकते हैं. कृपया अतिरिक्‍त वीडियो निकालें और पुन: प्रयास करें."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"संदेश सेवा अटैचमेंट लोड करने में विफल रही."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"फिर भी भेजें"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"बातचीत प्रारंभ नहीं की जा सकी"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> चुनी गई"</string>
+</resources>
diff --git a/res/values-hr/arrays.xml b/res/values-hr/arrays.xml
new file mode 100644
index 0000000..5ebf706
--- /dev/null
+++ b/res/values-hr/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"nema predmeta"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Da"</item>
+    <item msgid="6049132459802288033">"Ne"</item>
+    <item msgid="3084376867445867895">"U redu"</item>
+    <item msgid="3155097332660174689">"He-he"</item>
+    <item msgid="2611328818571146775">"Hvala"</item>
+    <item msgid="4881335087096496747">"Slažem se"</item>
+    <item msgid="2422296858597420738">"Lijepo"</item>
+    <item msgid="4805581752819452687">"Krećem"</item>
+    <item msgid="4746700499431366214">"U redu, javit ću se kasnije"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
new file mode 100644
index 0000000..b8bb490
--- /dev/null
+++ b/res/values-hr/strings.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Slanje poruka"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Slanje poruka"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Odabir razgovora"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Postavke"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Pošalji poruku"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Dodajte privitak"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Pomoć"</string>
+    <string name="welcome" msgid="2857560951820802321">"Dobro došli"</string>
+    <string name="skip" msgid="7238879696319945853">"Preskoči"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Dalje &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Dalje"</string>
+    <string name="exit" msgid="1905187380359981199">"Izlaz"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Postavke &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Postavke"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Slanje poruka treba dopuštenje za SMS, Telefon i Kontakte."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Dopuštenja možete promijeniti u Postavkama &gt; Aplikacije &gt; Slanje poruka &gt; Dopuštenja."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Dopuštenja možete promijeniti tako da u Postavkama otvorite Aplikacije, Slanje poruka, Dopuštenja."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Često kontaktirani"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Svi kontakti"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Pošalji na <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Snimite fotografije ili videozapis"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Odaberite slike s ovog uređaja"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Snimanje zvuka"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Odaberite fotografiju"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Medij je odabran."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Odabir medija poništen je."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Odabrano: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"slika <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"slika"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Snimanje zvuka"</string>
+    <string name="action_share" msgid="2143483844803153871">"Dijeljenje"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Upravo sada"</string>
+    <string name="posted_now" msgid="867560789350406701">"Sad"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> sat</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> sata</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> sati</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dan</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dana</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dana</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> tjedan</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> tjedna</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tjedana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mjesec</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> mjeseca</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mjeseci</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> godina</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> godine</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> godina</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Poruka klase 0"</string>
+    <string name="save" msgid="5081141452059463572">"Spremi"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Na uređaju ponestaje prostora. Slanje poruka automatski će izbrisati starije poruke da bi se oslobodio prostor."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Ponestaje prostora za pohranu"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Slanje poruka možda neće slati ili primati poruke dok se na uređaju ne oslobodi više prostora."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Nema dovoljno prostora za pohranu SMS-a. Možda ćete morati izbrisati poruke."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Potvrđivanje telefonskog broja"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Taj jednokratni korak omogućit će Slanju poruka pravilnu isporuku vaših grupnih poruka."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonski broj"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Izbriši sve poruke s medijskim sadržajima"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Izbriši poruke starije od <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automatski izbriši poruke starije od <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Zanemari"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Izbrisati sve poruke s medijskim sadržajima?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Izbrisati poruke starije od <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Izbrisati poruke starije od <xliff:g id="DURATION">%s</xliff:g> i uključiti automatsko brisanje?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> kaže"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Rekli ste"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Poruka pošiljatelja <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Poslali ste poruku"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Slanje…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nije poslano. Dodirnite za ponovni pokušaj."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nije poslano. Pokušavamo ponovo…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Ponovno slanje ili brisanje"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Nazovite hitnu službu. Vaša tekstna poruka nije isporučena."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Nije poslano"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nova MMS poruka za preuzimanje"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nova MMS poruka"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Preuzimanje nije moguće"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Dodirnite za ponovni pokušaj"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Dodirnite za preuzimanje"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Preuzimanje ili brisanje"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Preuzimanje..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Poruka je istekla ili nije dostupna"</string>
+    <string name="mms_info" msgid="3402311750134118165">"veličina: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, istek: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nije poslano. Primatelj nije važeći."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Usluga nije aktivirana na mreži"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Slanje nije uspjelo zbog problema s mrežom"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Poruka je istekla ili nije dostupna"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Bez predmeta)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Nepoznati pošiljatelj"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Isporučeno"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Preuzimanje poruke <xliff:g id="SUBJECT">%1$s</xliff:g> od pošiljatelja <xliff:g id="FROM">%2$s</xliff:g> nije uspjelo."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Radnja baze podataka nije dovršena zbog nedostatka memorije"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Poruka nije poslana"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Neke poruke nisu poslane u Slanju poruka"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> poruka u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovoru</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> poruke u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovora</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> poruka u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovora</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Poruka nije preuzeta"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Neke poruke nisu preuzete u Slanje poruka"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> poruka u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovoru</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> poruke u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovora</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> poruka u <xliff:g id="CONVERSATIONS">%d</xliff:g> razgovora</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Poruka na broj <xliff:g id="NUMBER">%1$s</xliff:g> nije poslana"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Nazovite hitnu službu. Vaša tekstna poruka na broj <xliff:g id="NUMBER">%1$s</xliff:g> nije isporučena."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> nova poruka</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nove poruke</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> novih poruka</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Započni"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotoaparat nije dostupan"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotoaparat nije dostupan"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Snimanje videozapisa nije dostupno"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Medij nije spremljen"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nije moguće snimiti sliku"</string>
+    <string name="back" msgid="1477626055115561645">"Natrag"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arhivirano"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Izbriši"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arhiviraj"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Poništi arhiviranje"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Isključi obavijesti"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Uključi obavijesti"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Dodaj kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Preuzmi"</string>
+    <string name="action_send" msgid="377635240181672039">"Pošalji"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Izbriši"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Želite li izbrisati tu poruku?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tu radnju nije moguće poništiti."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Izbriši"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Izbrisati razgovore?</item>
+      <item quantity="few">Izbrisati razgovore?</item>
+      <item quantity="other">Izbrisati razgovore?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Izbriši"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Odustani"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Odredište"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Odaberi više slika"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Potvrdite odabir"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Audioporuka nije snimljena. Pokušajte ponovo."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Audioporuku nije moguće reproducirati. Pokušajte ponovo."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Audioporuka nije spremljena. Pokušajte ponovo."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Dodirnite i zadržite"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Slika"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audioisječak"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videozapis"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kartica kontakta"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Preuzmi"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Odgovorite putem SMS-a"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Odgovor MMS-om"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Odgovorite"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> sudionik</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> sudionika</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> sudionika</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ja"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt je blokiran i arhiviran"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt deblokiran i dearhiviran"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Arhivirano: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Poništena arhiviranja: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Obavijesti isključene"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Obavijesti uključene"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Sve je postavljeno. Ponovo dodirnite Pošalji."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Slanje poruka uspješno je postavljeno kao zadana aplikacija za SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Odbacivanje privitaka</item>
+      <item quantity="few">Odbacivanje privitaka</item>
+      <item quantity="other">Odbacivanje privitaka</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audioprivitak"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproduciraj audioprivitak"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pauziraj"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Poruka pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Poruka pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g> nije uspjela: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Poruka pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Poruka za kontakt <xliff:g id="CONTACT">%1$s</xliff:g> nije poslana: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Slanje poruke kontaktu <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Poruka za kontakt <xliff:g id="CONTACT">%1$s</xliff:g> nije uspjela: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Poruka kontaktu <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Neuspjela poruka pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Poruka pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Poruka za grupu <xliff:g id="GROUP">%1$s</xliff:g> nije poslana: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Slanje poruke grupi <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Poruka za grupu <xliff:g id="GROUP">%1$s</xliff:g> nije uspjela: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Poruka grupi <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vrijeme: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Poruka nije uspjela. Dodirnite za ponovni pokušaj."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Razgovor sa sljedećima: <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Brisanje predmeta"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Snimi videozapis"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Snimi fotografiju"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Snimi sliku"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Početak snimanja videozapisa"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Prebacivanje na fotoaparat na punom zaslonu"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Prebacivanje između prednjeg i stražnjeg fotoaparata"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Zaustavi snimanje i priloži videozapis"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Zaustavi snimanje videozapisa"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotografije Slanja poruka"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografija spremljena je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografije spremljene su u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografija spremljeno je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> videozapis spremljen je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> videozapisa spremljena su u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videozapisa spremljeno je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> privitak spremljen je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> privitka spremljena su u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> privitaka spremljeno je u album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> privitak spremljen je u \"Preuzimanja\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> privitka spremljena su u \"Preuzimanja\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> privitaka spremljeno je u \"Preuzimanja\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> privitak spremljen</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> privitka spremljena</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> privitaka spremljeno</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Spremanje <xliff:g id="QUANTITY_1">%d</xliff:g> privitka nije uspjelo</item>
+      <item quantity="few">Spremanje <xliff:g id="QUANTITY_1">%d</xliff:g> privitaka nije uspjelo</item>
+      <item quantity="other">Spremanje <xliff:g id="QUANTITY_1">%d</xliff:g> privitaka nije uspjelo</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS privitak spremljen"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Postavke"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arhivirano"</string>
+    <string name="action_close" msgid="1840519376200478419">"Zatvori"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Napredno"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Otklanjanje pogrešaka"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Obavijesti"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Zvuk"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Bešumno"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibriranje"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokirano"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Izvješća o isporuci SMS-a"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Zahtijevanje izvješća o isporuci za svaki poslani SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatski dohvat"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatsko dohvaćanje MMS-ova"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatski dohvati u roamingu"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatsko dohvaćanje MMS-ova u roamingu"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Grupne poruke"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Slanje jedne poruke za više primatelja pomoću MMS-a"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Zadana aplikacija za SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Zadana aplikacija za SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Vaš telefonski broj"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Nepoznato"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Zvukovi odlazne poruke"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Sigurnosno kopiraj SMS-ove"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Sigurnosno kopiranje neobrađenih podataka primljenih SMS-ova u datoteku vanjske pohrane"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Sigurnosno kopiraj MMS-ove"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Sigurnosno kopiranje neobrađenih podataka primljenih MMS-ova u datoteku vanjske pohrane"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Upozorenja putem mobilne mreže"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opcije poruka"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiraj tekst"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Prikaz pojedinosti"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Izbriši"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Proslijedi"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Pojedinosti poruke"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Vrsta: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS poruka"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedijska poruka"</string>
+    <string name="from_label" msgid="1947831848146564875">"Šalje: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Prima: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Poslano: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Primljeno: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Predmet: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Veličina: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Visok"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Uobičajeni"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Niski"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skrivena adresa pošiljatelja"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Slanje poruke nije moguće tijekom učitavanja privitaka."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Privitak nije učitan. Pokušajte ponovo."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Mreža nije spremna. Pokušajte ponovo."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Brisanje teksta"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Prebacivanje između unosa teksta i brojeva"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Dodaj još sudionika"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Potvrdi sudionike"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Započnite novi razgovor"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Odaberite ovu stavku"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproduciraj videozapis"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Osobe i opcije"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Otkloni pogreške"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Osobe i opcije"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Općenito"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Osobe u ovom razgovoru"</string>
+    <string name="action_call" msgid="6596167921517350362">"Uputite poziv"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Pošaljite poruku"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Pošalji poruku&lt;br/&gt;&lt;small&gt;sa SIM kartice <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Pošaljite fotografije</item>
+      <item quantity="few">Pošaljite fotografije</item>
+      <item quantity="other">Pošaljite fotografije</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Pošaljite audiozapise</item>
+      <item quantity="few">Pošaljite audiozapise</item>
+      <item quantity="other">Pošaljite audiozapise</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Pošaljite videozapise</item>
+      <item quantity="few">Pošaljite videozapise</item>
+      <item quantity="other">Pošaljite videozapise</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Pošaljite kartice kontakata</item>
+      <item quantity="few">Pošaljite kartice kontakata</item>
+      <item quantity="other">Pošaljite kartice kontakata</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Pošaljite privitke</item>
+      <item quantity="few">Pošaljite privitke</item>
+      <item quantity="other">Pošaljite privitke</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> privitak spreman je za slanje</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> privitka spremna su za slanje</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> privitaka spremno je za slanje</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Slanje povratnih informacija"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Prikaži u Trgovini Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informacije o verziji"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Verzija %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licence otvorenog koda"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Obavijesti"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Dosegnuto je ograničenje za privitke"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Učitavanje privitka nije uspjelo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Želite li dodati u Kontakte?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Dodavanje kontakta"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Predmet"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Predmet: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Učitavanje kartice kontakta"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kartica kontakta nije učitana"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Prikaz kartice kontakta"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> kontakt</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> kontakta</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakata</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kartice kontakata"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Rođendan"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Bilješke"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Proslijedi poruku"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Odgovori"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS je onemogućen"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Postavite Slanje poruka kao zadanu aplikaciju za SMS da biste slali poruke"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Postavite Slanje poruka kao zadanu aplikaciju za SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Promijeni"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Postavite Slanje poruka kao zadanu aplikaciju za SMS da biste primali poruke"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nije odabran preferirani SIM za slanje SMS poruka"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Vlasnik uređaja nije odobrio upotrebu te aplikacije."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"U redu"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Previše sudionika u razgovoru"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Nevažeći kontakti</item>
+      <item quantity="few">Nevažeći kontakti</item>
+      <item quantity="other">Nevažeći kontakti</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Slika nije učitana"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vi: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Skica"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Ovdje će biti naveden novi razgovor kada ga pokrenete"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arhivirani razgovori prikazuju se ovdje"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Učitavanje razgovora..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Slika"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audioisječak"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Videozapis"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kartica kontakta"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Poništi"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Pokušaj ponovo"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Unesite ime kontakta ili telefonski broj da biste započeli novu poruku"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokiraj"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokiranje <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Deblokiraj <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokirati <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"I dalje ćete primati poruke s tog broja, ali više nećete primati obavijesti o tome. Razgovor će se arhivirati."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokirani kontakti"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DEBLOKIRAJ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokirani kontakti"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Odaberite sliku iz knjižnice dokumenata"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Slanje poruke"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Poruka je poslana"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobilni su podaci isključeni. Provjerite postavke."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Ne možete slati poruke u načinu rada u zrakoplovu"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Slanje poruke nije uspjelo"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Poruka preuzeta"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobilni su podaci isključeni. Provjerite postavke."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Nije moguće preuzimanje poruka u načinu  rada u zrakoplovu"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Preuzimanje poruke nije uspjelo"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nula"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Jedan"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dva"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tri"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Četiri"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pet"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Šest"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sedam"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Osam"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Devet"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Poruka nije poslana putem operatera <xliff:g id="CARRIERNAME">%1$s</xliff:g>, pogreška <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Poruka nije poslana putem nepoznatog mobilnog operatera, pogreška <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Poruka nije poslana jer usluga nije aktivirana na mreži"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Poruka nije poslana jer odredišna adresa nije važeća"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Poruka nije poslana jer nije važeća"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Poruka nije poslana jer sadržaj nije podržan"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Poruka nije poslana jer nije podržana"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Poruka nije poslana jer je prevelika"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nova poruka"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Prikaz"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Slika"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nije pronađena odgovarajuća aplikacija"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Uklanjanje primatelja"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nova poruka"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Odustani"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Uređivanje pristupne točke"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nije postavljeno"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Naziv"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS priključak"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Vrsta APN-a"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Izbriši APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Novi APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Spremi"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Odbaci"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Polje naziva ne može biti prazno."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ne može biti prazan."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC polje mora imati 3 znamenke."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Polje MNC mora imati 2 ili 3 znamenke."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Vraćaju se zadane postavke APN-a."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Vrati na zadano"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Dovršeno je vraćanje zadanih postavki APN-a."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Bez naziva"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nazivi pristupnih točaka"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-ovi"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Novi APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Postavke naziva pristupne točke nisu dostupne ovom korisniku"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopirati u međuspremnik?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiraj"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"na <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Općenito"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Napredno"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Opće postavke"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Napredne postavke"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Slanje pojedinačnih SMS poruka svim primateljima. Eventualne odgovore dobit ćete samo vi"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Slanje pojedinačnog MMS-a svim primateljima"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nepoznati broj"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nova poruka"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nova poruka."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Gumb za odabir SIM-a"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> odabran, gumb za odabir SIM-a"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Uredi predmet"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Odabir SIM-a ili uređivanje predmeta"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Dodirnite i zadržite da biste snimili zvuk"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Započnite novi razgovor"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Slanje poruka"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Popis Slanja poruka"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Slanje poruka"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nova poruka"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Popis razgovora"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Učitavanje razgovora"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Učitavanje poruka"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Prikaži više razgovora"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Prikaži više poruka"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Razgovor je izbrisan"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Razgovor izbrisan. Dodirnite za prikaz drugog razgovora iz Slanja poruka"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokirano"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Deblokirano"</string>
+    <string name="db_full" msgid="8459265782521418031">"Nedostaje prostora za pohranu. Neki se podaci mogu izgubiti."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Odaberite privitke"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Potvrdite odabir"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Odabrano: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Uklonite jedan ili više privitaka i pokušajte ponovo."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Možete pokušati poslati poruku, ali možda neće biti dostavljena ako ne uklonite jedan ili više privitaka."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Možete poslati samo jedan videozapis u poruci. Uklonite dodatne videozapise i pokušajte ponovo."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Slanje poruka nije uspjelo učitati privitak."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Svejedno pošalji"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Pokretanje razgovora nije uspjelo"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Odabrani SIM: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-hu/arrays.xml b/res/values-hu/arrays.xml
new file mode 100644
index 0000000..36c0cd0
--- /dev/null
+++ b/res/values-hu/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"nincs tárgy"</item>
+    <item msgid="272485471009191934">"nincs tárgy"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Igen"</item>
+    <item msgid="6049132459802288033">"Nem"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Haha!"</item>
+    <item msgid="2611328818571146775">"Köszönöm!"</item>
+    <item msgid="4881335087096496747">"Egyetértek"</item>
+    <item msgid="2422296858597420738">"Ügyes"</item>
+    <item msgid="4805581752819452687">"Úton vagyok"</item>
+    <item msgid="4746700499431366214">"Rendben, később jelentkezem"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
new file mode 100644
index 0000000..9203514
--- /dev/null
+++ b/res/values-hu/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Üzenetváltás"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Üzenetváltás"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Beszélgetés kijelölése"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Beállítások"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Üzenet küldése"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Melléklet hozzáadása"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Súgó"</string>
+    <string name="welcome" msgid="2857560951820802321">"Üdvözöljük!"</string>
+    <string name="skip" msgid="7238879696319945853">"Kihagyás"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Következő &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Tovább"</string>
+    <string name="exit" msgid="1905187380359981199">"Kilépés"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Beállítások &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Beállítások"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"A Messaging engedélyt kér a következőkhöz: SMS, telefon és névjegyek."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Az engedélyeket a Beállítások &gt; Alkalmazások &gt; Messaging &gt; Engedélyek lehetőségnél módosíthatja."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Az engedélyeket a Beállítások, Alkalmazások, Messaging, Engedélyek lehetőségnél módosíthatja."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Gyakran használt névjegyek"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Az összes névjegy"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Küldés: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Kép vagy videó rögzítése"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Képek kiválasztása erről az eszközről"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Hanganyag rögzítése"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Fotó kiválasztása"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Kijelölte a médiaelemet."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Visszavonta a médiaelem kijelölését."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> kiválasztva"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"kép <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"kép"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Hanganyag rögzítése"</string>
+    <string name="action_share" msgid="2143483844803153871">"Megosztás"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Éppen most"</string>
+    <string name="posted_now" msgid="867560789350406701">"Most"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> perce</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> perce</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> órája</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> órája</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> napja</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> napja</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hét</item>
+      <item quantity="one">egy hét</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hónap</item>
+      <item quantity="one">egy hónap</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> év</item>
+      <item quantity="one">egy év</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0. osztályú üzenet"</string>
+    <string name="save" msgid="5081141452059463572">"Mentés"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Az eszközön kevés a tárhely. A Messaging automatikusan törli a régebbi üzeneteket tárhely felszabadítása érdekében."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Kevés a szabad terület"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"A Messaging nem küldhet vagy fogadhat üzenetet, amíg nem áll rendelkezésre több hely az eszközön."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Kevés a tárhely az SMS-eknek. Lehet, hogy üzeneteket kell törölnie."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Telefonszám megerősítése"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Ez az egyszeri lépés biztosítja, hogy a Messaging megfelelően továbbítsa a csoportos üzeneteket."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonszám"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Az összes médiatartalommal bíró üzenet törlése"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"A(z) <xliff:g id="DURATION">%s</xliff:g> időtartamnál régebbi üzenetek törlése"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"A(z) <xliff:g id="DURATION">%s</xliff:g> időtartamnál régebbi üzenetek automatikus törlése"</string>
+    <string name="ignore" msgid="7063392681130898793">"Mellőzés"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Törli az összes, médiát tartalmazó üzenetet?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Törli a(z) <xliff:g id="DURATION">%s</xliff:g> időtartamnál régebbi üzeneteket?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Törli a(z) <xliff:g id="DURATION">%s</xliff:g> időtartamnál régebbi üzeneteket, és bekapcsolja az automatikus törlést?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> a következőt mondta:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ön a következőt mondta"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> üzenete:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Ön elküldött egy üzenetet"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Küldés…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nem lehetett elküldeni. Érintse meg az újbóli próbálkozáshoz."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nem lehetett elküldeni. Újabb próbálkozás…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Újraküldés vagy törlés"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Kérjük, tárcsázza a segélyhívót. A szöveges üzenetet jelenleg nem tudjuk elküldeni."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Sikertelen"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Új letölthető MMS üzenet"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Új MMS üzenet"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nem sikerült letölteni"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Érintse meg az újabb próbálkozáshoz"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Érintse meg a letöltéshez"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Letöltés vagy törlés"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Letöltés…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Az üzenet vagy lejárt, vagy nem érhető el."</string>
+    <string name="mms_info" msgid="3402311750134118165">"méret: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, lejárat: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nem lehetett elküldeni. A címzett érvénytelen."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"A szolgáltatás nincs aktiválva a hálózaton"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Hálózati probléma miatt nem lehetett elküldeni"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Az üzenet vagy lejárt, vagy nem érhető el."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Nincs tárgy)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Ismeretlen feladó"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Kézbesítve"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nem sikerült letölteni <xliff:g id="FROM">%2$s</xliff:g> „<xliff:g id="SUBJECT">%1$s</xliff:g>” tárgyú levelét."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Kevés a memória, ezért nem sikerült végrehajtani a műveletet az adatbázison"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"A rendszer nem küldte el az üzenetet"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"A Messaging egyes üzeneteit nem lehetett elküldeni"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> üzenet <xliff:g id="CONVERSATIONS">%d</xliff:g> beszélgetésben</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> üzenet egy beszélgetésben</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Az üzenet nincs letöltve"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"A Messaging egyes üzeneteit nem lehetett letölteni"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> üzenet <xliff:g id="CONVERSATIONS">%d</xliff:g> beszélgetésben</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> üzenet egy beszélgetésben</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Nem sikerült elküldeni az üzenetet a(z) <xliff:g id="NUMBER">%1$s</xliff:g> számra"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Kérjük, tárcsázza a segélyhívót. A szöveges üzenetet jelenleg nem tudjuk elküldeni erre a számra: <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> új üzenet</item>
+      <item quantity="one">Új üzenet</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Indítás"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"A kamera nem érhető el"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"A kamera nem érhető el"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"A videorögzítés nem érhető el"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nem lehetett menteni a médiát"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nem lehet képet készíteni"</string>
+    <string name="back" msgid="1477626055115561645">"Vissza"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archiválva"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Törlés"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archiválás"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Archiválás visszavonása"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Értesítések kikapcsolása"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Értesítések bekapcsolása"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Névjegy hozzáadása"</string>
+    <string name="action_download" msgid="7786338136368564146">"Letöltés"</string>
+    <string name="action_send" msgid="377635240181672039">"Küldés"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Törlés"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Törli ezt az üzenetet?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ez a művelet nem vonható vissza."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Törlés"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Törli ezeket a beszélgetéseket?</item>
+      <item quantity="one">Törli ezt a beszélgetést?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Törlés"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Mégse"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Címzett"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Több kép kiválasztása"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Kiválasztás megerősítése"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Nem sikerült rögzíteni a hangot. Próbálja újra."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"A hanganyag nem játszható le. Próbálja újra."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Nem sikerült elmenteni a hangot. Próbálja újra."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Érintés és tartás"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Kép"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Hangfelvétel"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videó"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Névjegykártya"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Letöltés"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Válasz SMS-ben"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Válasz MMS-ben"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Válasz"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> résztvevő</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> résztvevő</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Én"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Ismerős letiltva és archiválva"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Névjegy tiltása és archiválása visszavonva"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archiválva"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> archiválása megszüntetve"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Értesítések kikapcsolva"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Értesítések bekapcsolva"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Minden készen áll. Érintse meg újra a Küldés lehetőséget."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"A Messaging sikeresen beállítva alapértelmezett SMS-alkalmazásként."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Mellékletek elvetése</item>
+      <item quantity="one">Melléklet elvetése</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Hangmelléklet"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Hangmelléklet lejátszása"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Szünet"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> üzenete: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Sikertelen üzenet <xliff:g id="SENDER">%1$s</xliff:g> feladótól: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Üzenet <xliff:g id="SENDER">%1$s</xliff:g> feladótól: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Elküldetlen üzenet a(z) <xliff:g id="CONTACT">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Üzenet küldése a(z) <xliff:g id="CONTACT">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Sikertelen üzenet a(z) <xliff:g id="CONTACT">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Üzenet a(z) <xliff:g id="CONTACT">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Sikertelen üzenet <xliff:g id="SENDER">%1$s</xliff:g> feladótól: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Üzenet <xliff:g id="SENDER">%1$s</xliff:g> feladótól: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Elküldetlen üzenet a(z) <xliff:g id="GROUP">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Üzenet küldése a(z) <xliff:g id="GROUP">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Sikertelen üzenet a(z) <xliff:g id="GROUP">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Üzenet a(z) <xliff:g id="GROUP">%1$s</xliff:g> csoportnak: <xliff:g id="MESSAGE">%2$s</xliff:g>. Idő: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Sikertelen üzenet. Érintse meg az újrapróbáláshoz."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Beszélgetés a következőkkel: <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Tárgy törlése"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Videó rögzítése"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Állókép rögzítése"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Kép készítése"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Videofelvétel megkezdése"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Váltás teljes képernyős kameranézetre"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Váltás az elülső és a hátulsó kamera között"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Rögzítés leállítása és a videó csatolása"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Videofelvétel leállítása"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging-fotók"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotó mentve a következő albumba: <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotó mentve a következő albumba: <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videó mentve a következő albumba: <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> videó mentve a következő albumba: <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> melléklet mentve a következő albumba: <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> melléklet mentve a következő albumba: <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> melléklet mentve a „Letöltések” közé</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> melléklet mentve a „Letöltések” közé</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> melléklet sikeresen mentve</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> melléklet sikeresen mentve</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> melléklet mentése nem sikerült</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> melléklet mentése nem sikerült</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Mentett MMS-melléklet"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Beállítások"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archiválva"</string>
+    <string name="action_close" msgid="1840519376200478419">"Bezárás"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Speciális"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Hibakeresés"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Értesítések"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Hang"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Néma"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Rezgés"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Letiltva"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-kézbesítési jelentések"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Kézbesítési jelentés kérése minden elküldött SMS-ről"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatikus letöltés"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS-üzenetek automatikus letöltése"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Auto. letöltés barangoláskor"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"MMS-ek automatikus lekérése adatbarangoláskor"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Csoportos üzenetküldés"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Küldjön MMS-t, amikor több címzettnek szeretne üzenetet küldeni."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Alapértelmezett SMS-alkalmazás"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Alapértelmezett SMS-alkalmazás"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Az Ön telefonszáma"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Ismeretlen"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Kimenő üzenetek hangja"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS kiírása"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Beérkező nyers SMS-adatok kiírása külső tárolófájlba"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS kiírása"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Beérkező nyers MMS-adatok kiírása külső tárolófájlba"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Vezeték nélküli értesítések"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Üzenetbeállítások"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Szöveg másolása"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Részletek megjelenítése"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Törlés"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Továbbítás"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Üzenet részletei"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Típus: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Szöveges üzenet"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimédiás üzenet"</string>
+    <string name="from_label" msgid="1947831848146564875">"Küldő: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Címzett: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Elküldve: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Érkezett: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Tárgy: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Méret: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritás: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Magas"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normál"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Alacsony"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"<xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>. SIM"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"A küldő címe elrejtve"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"A mellékletek betöltése közben nem lehet elküldeni az üzenetet."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nem lehetett betölteni a mellékletet. Próbálja újra."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"A hálózat nem áll készen. Próbálja újra."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Szöveg törlése"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Váltás szöveg és számok bevitele között"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"További résztvevők hozzáadása"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Résztvevők megerősítése"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Új beszélgetés indítása"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Elem kiválasztása"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Videó lejátszása"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Személyek és beállítások"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Hibakeresés"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Személyek és beállítások"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Általános"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"A jelen beszélgetésben részt vevő személyek"</string>
+    <string name="action_call" msgid="6596167921517350362">"Hívásindítás"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Üzenet küldése"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Üzenet küldése&lt;br/&gt;&lt;small&gt;a következő SIM kártyáról: <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Fotók küldése</item>
+      <item quantity="one">Fotó küldése</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Hangok küldése</item>
+      <item quantity="one">Hang küldése</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Videók küldése</item>
+      <item quantity="one">Videó küldése</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Névjegykártyák küldése</item>
+      <item quantity="one">Névjegykártya küldése</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Mellékletek küldése</item>
+      <item quantity="one">Melléklet küldése</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> melléklet készen áll a küldésre</item>
+      <item quantity="one">Egy melléklet készen áll a küldésre</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Visszajelzés küldése"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Megtekintés a Google Play Áruházban"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Verzióadatok"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Verzió: %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Nyílt forráskódú licencek"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Értesítések"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Elérte a mellékletekre vonatkozó korlátot"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Nem sikerült betölteni a mellékletet."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Hozzáadja a Névjegyekhez?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Névjegy hozzáadása"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Tárgy"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Tárgy: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Névjegykártya betöltése"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nem lehetett betölteni a névjegykártyát"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Névjegykártya megtekintése"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> névjegy</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> névjegy</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Névjegykártyák"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Születésnap"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Jegyzetek"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Üzenet továbbítása"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Válasz"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-ek letiltva"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"A küldéshez állítsa be, hogy a Messaging legyen az alapértelmezett SMS-alkalmazás"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"A Messaging beállítása alapértelmezett SMS-alkalmazásként"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Módosítás"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Üzenetek fogadásához állítsa be, hogy a Messaging legyen az alapértelmezett SMS-alkalmazás"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nincs SIM kiválasztva az SMS-küldéshez"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Az eszköz tulajdonosa nem engedélyezi ezt az alkalmazást."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Túl sok a résztvevő a beszélgetésben"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Érvénytelen névjegy</item>
+      <item quantity="one">Érvénytelen névjegy</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nem lehetett betölteni a kamera képét"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ön: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Piszkozat"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Amikor új beszélgetésbe kezd, az itt jelenik meg"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Itt jelennek meg az archivált beszélgetések"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Beszélgetések betöltése…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Kép"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Hangfelvétel"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Videó"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Névjegykártya"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Visszavonás"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Újra"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Új üzenet létrehozásához adjon meg egy névjegyet vagy telefonszámot"</string>
+    <string name="action_block" msgid="9032076625645190136">"Tiltás"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> letiltása"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> feloldása"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Letiltja ezt: <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Továbbra is kap üzeneteket erről a számról, ám a rendszer nem küld róluk értesítést. A beszélgetést a rendszer archiválja."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Letiltott ismerősök"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"FELOLD"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Letiltott ismerősök"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Kép választása a dokumentumtárból"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Üzenet küldése"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Üzenet elküldve"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"A mobiladat-kapcsolat ki van kapcsolva. Ellenőrizze beállításait."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Repülős módban nem lehet üzeneteket küldeni"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Az üzenetet nem sikerült elküldeni"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Üzenet letöltve"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"A mobiladat-kapcsolat ki van kapcsolva. Ellenőrizze beállításait."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Repülős üzemmódban nem lehet üzenetet letölteni"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Az üzenetet nem sikerült letölteni"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nulla"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Egy"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Kettő"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Három"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Négy"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Öt"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Hat"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Hét"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Nyolc"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Kilenc"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nem lehet elküldeni az üzenetet a következő szolgáltatónál: <xliff:g id="CARRIERNAME">%1$s</xliff:g> (hibakód: <xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nem lehet elküldeni az üzenetet egy ismeretlen szolgáltatónál (hibakód: <xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Továbbítás: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Az üzenet nincs elküldve: a szolgáltatás nincs aktiválva a hálózaton"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Az üzenet küldése sikertelen: a címzett címe érvénytelen"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Az üzenet küldése sikertelen: érvénytelen üzenet"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Az üzenet küldése sikertelen: nem támogatott tartalom"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Az üzenet küldése sikertelen: nem támogatott üzenet"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Az üzenet nincs elküldve: túl nagy"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Új üzenet"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Megtekintés"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Kép"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nem található megfelelő alkalmazás"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Címzett eltávolítása"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Új üzenet"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Mégse"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Hozzáférési pont szerkesztése"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nincs megadva"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Név"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN típusa"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN törlése"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Új APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Mentés"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Elvetés"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"A Név mező nem lehet üres."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Az APN nem lehet üres."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Az MCC mezőnek három számjegyet kell tartalmaznia."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Az MNC mezőbe 2 vagy 3 számjegyet kell írni."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Alapértelmezett APN-beállítások visszaállítása."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Visszaállítás alaphelyzetbe"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Az alapértelmezett APN-beállítások visszaállítása befejeződött."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Névtelen"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Hozzáférési pontok nevei"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-ek"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Új APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"A hozzáférési pont nevének beállításai nem érhetők el ennél a felhasználónál"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Átmásolja a vágólapra?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Másolás"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"fogadás a következőn: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Általános"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Speciális"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Általános beállítások"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Speciális beállítások"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"„<xliff:g id="SIM_NAME">%s</xliff:g>” SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Külön SMS küldése valamennyi címzettnek. Csak Ön kap választ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Egyetlen MMS küldése valamennyi címzettnek"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Ismeretlen szám"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Új üzenet"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Új üzenet"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM kártya kiválasztása"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"A(z) <xliff:g id="SIM_0">%1$s</xliff:g> SIM kártya kiválasztva (SIM-választó)"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Tárgy szerkesztése"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM kártya kiválasztása vagy a tárgy szerkesztése"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Hangfelvétel készítéséhez tartsa nyomva"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Új beszélgetés indítása"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging-lista"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Új üzenet"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Beszélgetéslista"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Beszélgetések betöltése"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Üzenetek betöltése"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"További beszélgetések megtekintése"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"További üzenetek megtekintése"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Beszélgetés törölve"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Beszélgetés törölve. Másik Messaging-beszélgetés megjelenítéséhez érintse meg."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Letiltva"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Letiltás visszavonva"</string>
+    <string name="db_full" msgid="8459265782521418031">"Kevés a tárhely. Lehet, hogy bizonyos adatok elvesztek."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Mellékletek kiválasztása"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Kiválasztás megerősítése"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> kiválasztva"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Távolítson el legalább egy mellékletet, majd próbálja újra."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Megpróbálhatja elküldeni az üzenetet, de előfordulhat, hogy az csak akkor lesz kézbesíthető, ha legalább egy mellékletet eltávolít."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Üzenetenként csak egy videót lehet küldeni. Távolítsa el a többi videót, és próbálja újra."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"A Messaging nem tudta betölteni a mellékletet."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Küldés mindenképpen"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Nem sikerült elindítani a beszélgetést"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> kiválasztva"</string>
+</resources>
diff --git a/res/values-hy/arrays.xml b/res/values-hy/arrays.xml
new file mode 100644
index 0000000..d520d07
--- /dev/null
+++ b/res/values-hy/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"անվերնագիր"</item>
+    <item msgid="272485471009191934">"անվերնագիր"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Այո"</item>
+    <item msgid="6049132459802288033">"Ոչ"</item>
+    <item msgid="3084376867445867895">"Լավ"</item>
+    <item msgid="3155097332660174689">"Հե-հե"</item>
+    <item msgid="2611328818571146775">"Շնորհակալություն"</item>
+    <item msgid="4881335087096496747">"Համաձայն եմ"</item>
+    <item msgid="2422296858597420738">"Գերազանց է"</item>
+    <item msgid="4805581752819452687">"Ճանապարհին եմ"</item>
+    <item msgid="4746700499431366214">"Լավ, կմիանամ ձեզ ավելի ուշ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
new file mode 100644
index 0000000..4dd99b0
--- /dev/null
+++ b/res/values-hy/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Հաղորդակցում"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Հաղորդակցում"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Ընտրեք խոսակցությունը"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Կարգավորումներ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Ուղարկել հաղորդագրություն"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Ավելացնել կցորդ"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Օգնություն"</string>
+    <string name="welcome" msgid="2857560951820802321">"Բարի գալուստ"</string>
+    <string name="skip" msgid="7238879696319945853">"Բաց թողնել"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Հաջորդը &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Հաջորդը"</string>
+    <string name="exit" msgid="1905187380359981199">"Ելք"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Կարգավորումներ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Կարգավորումներ"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Հաղորդակցում հավելվածին հարկավոր է թույլտվություն SMS-ներին, հեռախոսին ու կոնտակտներին:"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Կարող եք փոխել թույլտվությունները՝ անցնելով Կարգավորումներ &gt; Հավելվածներ &gt; Հաղորդակցում &gt; Թույլտվություններ:"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Կարող եք փոխել թույլտվությունները՝ անցնելով Կարգավորումներ, Հավելվածներ, Հաղորդակցում, Թույլտվություններ:"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Հաճախակի օգտագործվող կոնտակտներ"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Բոլոր կոնտակտները"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Ուղարկել <xliff:g id="DESTINATION">%s</xliff:g> համարին"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Լուսանկարել կամ տեսագրել"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Ընտրեք պատկերներ այս սարքից"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Ձայնագրել ձայնանյութ"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Ընտրել լուսանկար"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Մեդիա ֆայլն ընտրված է:"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Մեդիա ֆայլն ապընտրված է:"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ընտրված"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"պատկեր <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"պատկեր"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Ձայնագրել ձայնանյութ"</string>
+    <string name="action_share" msgid="2143483844803153871">"Տարածել"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Հենց հիմա"</string>
+    <string name="posted_now" msgid="867560789350406701">"Այժմ"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> րոպե</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> րոպե</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ժամ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ժամ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> օր</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> օր</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> շաբաթ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> շաբաթ</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ամիս</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ամիս</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> տարի</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> տարի</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 հաղորդագրություն"</string>
+    <string name="save" msgid="5081141452059463572">"Պահել"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Սարքի վրա բավարար ազատ տարածք չկա: Հաղորդակցում հավելվածը ինքնաշխատորեն կջնջի հին հաղորդագրությունները, որպեսզի տեղ ազատի:"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Պահոցային տարածքը սպառվում է"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Հաղորդակցումը չի կարող ուղարկել կամ ստանալ հաղորդագրություններ, քանի դեռ սարքում բավարար տարածք չկա:"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS պահոցի ծավալը փոքր է: Հնարավոր է՝ հաղորդագրություններ ջնջելու կարիք լինի:"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Հաստատեք ձեր հեռախոսահամարը"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Սա մեկանգամյա քայլ է, որի շնորհիվ Հաղորդակցումը անսխալ կուղարկի ձեր խմբային հաղորդագրությունները:"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Հեռախոսահամար"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Ջնջել մեդիաֆայլեր պարունակող բոլոր հաղորդագրությունները"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Ջնջել <xliff:g id="DURATION">%s</xliff:g>-ից հին հաղորդագրությունները"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Ավտոմատ ջնջել <xliff:g id="DURATION">%s</xliff:g>-ից հին հաղորդագրությունները"</string>
+    <string name="ignore" msgid="7063392681130898793">"Անտեսել"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Ջնջե՞լ մեդիա պարունակող բոլոր հաղորդագրությունները:"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Ջնջե՞լ <xliff:g id="DURATION">%s</xliff:g>-ից հին հաղորդագրությունները:"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Ջնջե՞լ <xliff:g id="DURATION">%s</xliff:g>-ից հին հաղորդագրությունները և միացնել ավտոմատ հեռացումը:"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>-ը ասել է"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Դուք ասել եք"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Հաղորդագրություն <xliff:g id="SENDER">%s</xliff:g>-ից"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Դուք հաղորդագրություն եք ուղարկել"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Ուղարկվում է…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Չի ուղարկվել: Հպեք՝ կրկին փորձելու համար:"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Չի ուղարկվել: Փորձում է կրկին…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Կրկին ուղարկել թե ջնջել"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Խնդրում ենք հեռախոսազանգ կատարել արտակարգ իրավիճակների ծառայություններին: Ձեր տեքստային հաղորդագրությունն այս պահին չի կարող առաքվել:"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Ձախողվեց"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Նոր MMS հաղորդագրություն՝ ներբեռնելու հաար"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Նոր MMS հաղորդագրություն"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Չհաջողվեց ներբեռնել"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Հպեք՝ նորից փորձելու համար"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Հպեք՝ ներբեռնելու համար"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Ներբեռնել թե ջնջել"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Ներբեռնում…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Հաղորդագրության ժամկետը սպառվել է կամ հասանելի չէ"</string>
+    <string name="mms_info" msgid="3402311750134118165">"չափը՝ <xliff:g id="MESSAGESIZE">%1$s</xliff:g> , պիտանիությունը՝ <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Հնարավոր չէ ուղարկել: Ստացողը վավեր չէ:"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Ծառայությունն ակտիվացված չէ ցանցում"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Հնարավոր չէ ուղարկել ցանցային խնդրի պատճառով"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Հաղորդագրության ժամկետը սպառվել է կամ հասանելի չէ"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Անվերնագիր)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Անհայտ ուղարկող"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Առաքված է"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Հնարավոր չէ ներբեռնել <xliff:g id="SUBJECT">%1$s</xliff:g> հաղորդագրությունը <xliff:g id="FROM">%2$s</xliff:g>-ից:"</string>
+    <string name="low_memory" msgid="5300743415198486619">"Չստացվեց ավարտել տվյալների շտեմարանի աշխատանքը՝ փոքր հիշողության պատճառով"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Հաղորդագրությունը չի ուղարկվել"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Հաղորդակցման որոշ հաղորդագրություններ չեն ուղարկվել"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> հաղորդագրություն <xliff:g id="CONVERSATIONS">%d</xliff:g> խոսակցությունում</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> հաղորդագրություն <xliff:g id="CONVERSATIONS">%d</xliff:g> խոսակցությունում</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Հաղորդագրությունը չի ներբեռնվել"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Որոշ հաղորդագրություններ չեն ներբեռնվել Հաղորդակցման մեջ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> հաղորդագրություն <xliff:g id="CONVERSATIONS">%d</xliff:g> խոսակցությունում</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> հաղորդագրություն <xliff:g id="CONVERSATIONS">%d</xliff:g> խոսակցությունում</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Հաղորդագրությունը <xliff:g id="NUMBER">%1$s</xliff:g> համարին չի ուղարկվել"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Խնդրում ենք հեռախոսազանգ կատարել արտակարգ իրավիճակների ծառայություններին: Ձեր տեքստային հաղորդագրությունն այս պահին չի կարող առաքվել <xliff:g id="NUMBER">%1$s</xliff:g> համարին:"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> նոր հաղորդագրություն</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> նոր հաղորդագրություն</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Սկսել"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Խցիկն անհասանելի է"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Խցիկն անհասանելի է"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Տեսանյութը հասանելի չէ"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Հնարավոր չէ պահել մեդիա ֆայլը"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Չհաջողվեց լուսանկարել"</string>
+    <string name="back" msgid="1477626055115561645">"Հետ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Արխիվացված"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Ջնջել"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Արխիվ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Ապարխիվացնել"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Անջատել ծանուցումները"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Միացնել ծանուցումները"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Ավելացնել կոնտակտ"</string>
+    <string name="action_download" msgid="7786338136368564146">"Ներբեռնել"</string>
+    <string name="action_send" msgid="377635240181672039">"Ուղարկել"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Ջնջել"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Ջնջե՞լ այս հաղորդագրությունը"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Այս գործողությունը չի կարող հետարկվել:"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Ջնջել"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Ջնջե՞լ այս խոսակցությունները:</item>
+      <item quantity="other">Ջնջե՞լ այս խոսակցությունները:</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Ջնջել"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Չեղարկել"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Ստացող`"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Ընտրել մի քանի պատկեր"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Հաստատել ընտրությունը"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Հնարավոր չէ ձայնագրել: Կրկին փորձեք:"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Հնարավոր չէ նվագարկել աուդիո ֆայլը: Կրկին փորձեք:"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Հնարավոր չէր պահել աուդիո ֆայլը: Կրկին փորձեք:"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Հպել և պահել"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Նկար"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Ձայնահոլովակ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Տեսանյութ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Կոնտակտային քարտ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Ներբեռնել"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Պատասխանել SMS-ով"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Պատասխանել MMS-ով"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Պատասխանել"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> մասնակից</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> մասնակից</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ես"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Կոնտակտն արգելափակված և արխիվացված է"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Կոնտակտն արգելաբացվեց և ապաարխիվացվեց"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Արխիվացվեց <xliff:g id="COUNT">%d</xliff:g> խոսակցություն"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Ապաարխիվացվեց <xliff:g id="COUNT">%d</xliff:g> խոսակցություն"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Ծանուցումներն անջատվեցին"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Ծանուցումները միացվեցին"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Սահմանված է: Հպեք Ուղարկել կրկին:"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Հաղորդակցումը դարձավ SMS-ների կանխադրված հավելված:"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Հեռացնել կցորդները</item>
+      <item quantity="other">Հեռացնել կցորդները</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Կցված ձայնային ֆայլ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Նվագարկել աուդիո կցորդը"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Դադարեցնել"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Հաղորդագրություն <xliff:g id="SENDER">%1$s</xliff:g>-ից՝ <xliff:g id="MESSAGE">%2$s</xliff:g>:"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Չառաքված հաղորդագրություն <xliff:g id="SENDER">%1$s</xliff:g>-ից՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Հաղորդագրություն <xliff:g id="SENDER">%1$s</xliff:g>-ից՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> կոնտակտին չուղարկված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Հաղորդագրության ուղարկում <xliff:g id="CONTACT">%1$s</xliff:g> կոնտակտին՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> կոնտակտին չառաքված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> կոնտակտին հասցեագրված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Չառաքված հաղորդագրություն <xliff:g id="SENDER">%1$s</xliff:g>-ից՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>: <xliff:g id="GROUPINFO">%4$s</xliff:g>:"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Հաղորդագրություն <xliff:g id="SENDER">%1$s</xliff:g>-ից՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>: <xliff:g id="GROUPINFO">%4$s</xliff:g>:"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> խմբին չուղարկված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Հաղորդագրության ուղարկում <xliff:g id="GROUP">%1$s</xliff:g> խմբին՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> խմբին չառաքված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> խմբին հասցեագրված հաղորդագրություն՝ <xliff:g id="MESSAGE">%2$s</xliff:g>: Ժամանակ՝ <xliff:g id="TIME">%3$s</xliff:g>:"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Հաղորդագրությունը չի առաքվել: Հպեք՝ նորից փորձելու համար:"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Զրույց <xliff:g id="PARTICIPANTS">%s</xliff:g>-ի հետ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Ջնջել վերնագիրը"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Տեսագրել"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Նկարահանել ստատիկ պատկեր"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Լուսանկարել"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Սկսել տեսաձայնագրումը"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Անցնել լիաէկրան ֆոտոխցիկի"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Փոխարկել դիմացի և հետևի տեսախցիկները"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Կանգնեցնել ձայնագրումը և կցել տեսանյութը"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Դադարեցնել տեսանկարահանումը"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Հաղորդակցման լուսանկարներ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> լուսանկար</item>
+      <item quantity="other">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> լուսանկար</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> տեսանյութ</item>
+      <item quantity="other">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> տեսանյութ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> կցորդ</item>
+      <item quantity="other">«<xliff:g id="ALBUMNAME_3">%s</xliff:g>» ալբոմում պահվել է <xliff:g id="QUANTITY_2">%d</xliff:g> կցորդ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one">«Ներբեռնումներ» պանակում պահվել է <xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ</item>
+      <item quantity="other">«Ներբեռնումներ» պանակում պահվել է <xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ պահվեց</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ պահվեց</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Չհաջողվեց պահել <xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ</item>
+      <item quantity="other">Չհաջողվեց պահել <xliff:g id="QUANTITY_1">%d</xliff:g> կցորդ</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS կցորդը պահվեց"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Կարգավորումներ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Արխիվացված"</string>
+    <string name="action_close" msgid="1840519376200478419">"Փակել"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Հավելյալ"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Կարգաբերում"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Ծանուցումներ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ձայն"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Լուռ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Թրթռոց"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Արգելափակված է"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-ի առաքման հաշվետվություններ"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Առաքման ծանուցում հայցել յուրաքանչյուր ուղարկվող հաղորդագրության համար"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Ինքնաառբերում"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Ավտոմատ առբերել MMS հաղորդագրությունները"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Ավտոմատ առբերում ռոումինգում"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Ինքնաշխատորեն առբերել MMS-ը ռոումինգում"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Խմբային հաղորդագրություններ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Օգտագործել MMS՝ մեկ հաղորդագրությունը մի քանի ստացողների ուղարկելու համար"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"SMS-ների կանխադրված հավելված"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"SMS-ների կանխադրված հավելված"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Ձեր հեռախոսահամարը"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Անհայտ է"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Ելից հաղորդագրությունների ձայներ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Տեղափոխել SMS հաղորդագրությունները"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Տեղափոխել ստացված SMS հաղորդագրությունների չմշակված տվյալները արտաքին հիշողության մեջ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Տեղափոխել MMS հաղորդագրությունները"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Տեղափոխել ստացված MMS հաղորդագրությունների չմշակված տվյալները արտաքին հիշողության մեջ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Ծանուցումներ անլար կապի միջոցով"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Հաղորդագրության ընտրանքներ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Պատճենել տեքստը"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Տեսնել մանրամասները"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Ջնջել"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Առաջ"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Հաղորդագրության մանրամասները"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Տեսակ՝ "</string>
+    <string name="text_message" msgid="7415419755252205721">"Տեքստային հաղորդագրություն"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Մուլտիմեդիա հաղորդագրություն"</string>
+    <string name="from_label" msgid="1947831848146564875">"Ումից` "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Ում` "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Ուղարկվել է՝ "</string>
+    <string name="received_label" msgid="4442494712757995203">"Ստացվել է՝ "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Վերնագիր՝ "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Չափ՝ "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Առաջնահերթություն՝ "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM՝ "</string>
+    <string name="priority_high" msgid="728836357310908368">"Բարձր"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Սովորական"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Ցածր"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Թաքնված ուղարկողի հասցեն"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Կցորդները բեռնելիս հնարավոր չէ ուղարկել հաղորդագրությունը:"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Հնարավոր չէ բեռնել կցորդը: Փորձեք կրկին:"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Ցանցը պատրաստ չէ: Նորից փորձեք:"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Ջնջել տեքստը"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Փոխարկել թվեր և տեքստ մուտքագրելու ռեժիմների միջև"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Ավելացնել այլ մասնակիցների"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Հաստատեք մասնակիցներին"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Սկսել նոր խոսակցություն"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Ընտրել այս նյութը"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Նվագարկել տեսանյութը"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Մարդիկ և ընտրանքներ"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Կարգաբերել"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Մարդիկ և ընտրանքներ"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Ընդհանուր"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Այս խոսակցության մասնակիցները"</string>
+    <string name="action_call" msgid="6596167921517350362">"Զանգահարել"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Ուղարկել հաղորդագրություն"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Ուղարկել հաղորդագրություն&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>-ից&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Ուղարկել լուսանկարները</item>
+      <item quantity="other">Ուղարկել լուսանկարները</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Ուղարկել ձայնագրությունները</item>
+      <item quantity="other">Ուղարկել ձայնագրությունները</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Ուղարկել տեսանյութերը</item>
+      <item quantity="other">Ուղարկել տեսանյութերը</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Ուղարկել կոնտակտի քարտերը</item>
+      <item quantity="other">Ուղարկել կոնտակտի քարտերը</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Ուղարկել կցորդները</item>
+      <item quantity="other">Ուղարկել կցորդները</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> կցորդ պատրաստ է ուղարկելու համար</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> կցորդ պատրաստ է ուղարկելու համար</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Ուղարկել կարծիք"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Դիտել Google Play Store-ում"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Տեղեկություններ տարբերակի մասին"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Տարբերակ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Բաց աղբյուրով ծրագրերի լիցենզիաներ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Ծանուցումներ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Կցորդի սահմանաչափը լրացել է"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Չհաջողվեց բեռնել կցորդը:"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Ավելացնե՞լ կոնտակտներում"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Ավելացնել կոնտակտ"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Թեմա"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Թեմա՝ "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Կոնտակտի քարտը բեռնվում է"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Հնարավոր չէ բեռնել կոնտակտի քարտը"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Դիտել կոնտակտի քարտը"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> կոնտակտ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> կոնտակտ</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Կոնտակտների քարտեր"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Ծննդյան օր"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Գրառումներ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Փոխանցել հաղորդագրությունը"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Պատասխանել"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-ն անջատված է"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Հաղորդագրություններ ուղարկելու համար դարձրեք Հաղորդակցումը SMS-ների կանխադրված հավելված"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Դարձրեք Հաղորդակցումը SMS-ների կանխադրված հավելված"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Փոխել"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Հաղորդագրություններ ստանալու համար դարձրեք Հաղորդակցումը SMS-ների կանխադրված հավելված"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Դուք չեք նշել նախընտրելի SIM քարտը՝ SMS հաղորդագրություններն ուղարկելու համար"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Այս հավելվածը սարքի սեփականատիրոջ կողմից թույլատրված չէ:"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Լավ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Չափից շատ մասնակիցներ կան զրույցին"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Անվավեր կոնտակտներ</item>
+      <item quantity="other">Անվավեր կոնտակտներ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Չհաջողվեց բեռնել տեսախցիկի պատկերը"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Դուք՝ "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>՝ "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Սևագիր"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Հենց նոր զրույց սկսեք, այն կտեսնեք այս ցուցակում"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Արխիվացված խոսակցությունները հայտնվում են այստեղ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Խոսակցությունները բեռնվում են…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Նկար"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Ձայնահոլովակ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Տեսանյութ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Կոնտակտային քարտ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Հետարկել"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Կրկնել"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Մուտքագրեք կոնտակտի անունը կամ հեռախոսահամարը՝ նոր հաղորդագրություն սկսելու համար"</string>
+    <string name="action_block" msgid="9032076625645190136">"Արգելափակել"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Արգելափակել <xliff:g id="DESTINATION">%s</xliff:g>-ին"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Արգելաբացել <xliff:g id="DESTINATION">%s</xliff:g>-ին"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Արգելափակե՞լ <xliff:g id="DESTINATION">%s</xliff:g>-ը:"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Դուք կշարունակեք ստանալ հաղորդագրություններ այս հեռախոսահամարից, բայց չեք ծանուցվի դրանց մասին: Այս խոսակցությունը կարխիվացվի:"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Արգելափակված կոնտակտներ"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ԱՐԳԵԼԱԲԱՑԵԼ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Արգելափակված կոնտակտներ"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Ընտրեք պատկեր՝ փաստաթղթերի գրադարանից"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Հաղորդագրությունն ուղարկվում է"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Հաղորդագրությունն ուղարկվել է"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Բջջային տվյալների կապն անջատված է: Ստուգեք ձեր կարգավորումները:"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Հնարավոր չէ ուղարկել հաղորդագրություններ Թռիչքի ռեժիմում"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Հաղորդագրությունը չհաջողվեց ուղարկել"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Հաղորդագրությունը բեռնվել է"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Բջջային տվյալների կապն անջատված է: Ստուգեք ձեր կարգավորումները:"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Հնարավոր չէ ներբեռնել հաղորդագրությունները Ինքնաթիռի ռեժիմում"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Հաղորդագրությունը չներբեռնվեց"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Զրո"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Մեկ"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Երկու"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Երեք"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Չորս"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Հինգ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Վեց"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Յոթ"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Ութ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Ինը"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Հնարավոր չէ ուղարկել հաղորդագրությունը <xliff:g id="CARRIERNAME">%1$s</xliff:g>-ի միջոցով: Սխալի կոդ՝ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Հնարավոր չէ ուղարկել հաղորդագրությունը անհայտ օպերատորի միջոցով: Սխալի կոդ՝ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Փխնց՝ <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Հաղորդագրությունը չի ուղարկվել. Ծառայությունն ակտիվացված չէ ցանցում"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Հաղորդագրությունը չի ուղարկվել. ստացողի հասցեն սխալ է"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Հաղորդագրությունը չի ուղարկվել. անվավեր հաղորդագրություն"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Հաղորդագրությունը չի ուղարկվել. չաջակցվող բովանդակություն"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Հաղորդագրությունը չի ուղարկվել. չաջակցվող հաղորդագրություն"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Հաղորդագրությունը չուղարկվեց: Այն չափազանց մեծ է"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Նոր հաղորդագրություն"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Դիտել"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Պատկեր"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Հնարավոր չէր գտնել համապատասխան հավելված"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Հեռացնել ստացողին"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Նոր հաղորդագրություն"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Չեղարկել"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Խմբագրել մուտքի կետը"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Կարգավորված չէ"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Անուն"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS պրոքսի"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS միացք"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-ի տեսակը"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Ջնջել APN-ը"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Նոր APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Պահել"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Հրաժարվել"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Անվանման դաշտը պետք է լրացված լինի:"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN-ը չի կարող դատարկ լինել:"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC դաշտը պետք է 3 նիշ ունենա:"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC դաշտը պետք է լինի առնվազն 2 կամ 3 թվանշան:"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Լռելյայն APN կարգավորումների վերականգնում:"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Վերականգնել կանխադրվածը"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Սկզբնական APN կարգավորումների վերակարգավորումն ավարտված է:"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Անվերնագիր"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Մատչման կետերի անունները"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-ներ"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Նոր APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Մատչման կետի անվան կարգավորումները հասանելի չեն այս օգտվողին"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Պատճենել սեղմատախտակին"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Պատճենել"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g>-ին"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Ընդհանուր"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Հավելյալ"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ընդհանուր կարգավորումներ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Ընդլայնված կարգավորումներ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"«<xliff:g id="SIM_NAME">%s</xliff:g>» SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Ուղարկել անհատական ​​SMS հաղորդագրություններ բոլոր ստացողներին: Միայն դուք կստանաք պատասխաններ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Բոլոր ստացողներին ուղարկել առանձին MMS"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Անհայտ համար"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Նոր հաղորդագրություն"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Նոր հաղորդագրություն:"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM քարտի ընտրում"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Ընտրված է <xliff:g id="SIM_0">%1$s</xliff:g>-ը, SIM քարտի ընտրում"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Խմբագրել վերնագիրը"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Ընտրել SIM քարտ կամ խմբագրել վերնագիրը"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Հպեք և պահեք՝ ձայնագրելու համար"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Սկսել նոր խոսակցություն"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Հաղորդակցում"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Հաղորդակցման ցանկ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Հաղորդակցում"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Նոր հաղորդագրություն"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Խոսակցությունների ցանկ"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Խոսակցությունները բեռնվում են"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Հաղորդագրությունների բեռնում"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Տեսնել այլ զրույցներ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Դիտել ավելի շատ հաղորդագրություններ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Զրույցը ջնջված է"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Խոսակցությունը ջնջվել է: Հպեք՝ Հաղորդակցման մեջ այլ խոսակցություն դիտելու համար"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Արգելափակված է"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Ապաարգելափակված է"</string>
+    <string name="db_full" msgid="8459265782521418031">"Ազատ տարածքը բավարար չէ: Որոշ տվյալներ չեն պահվի:"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Ընտրել կցորդներ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Հաստատել ընտրությունը"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ընտրված"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Հեռացրեք մեկ կամ ավելի կցորդ, ապա նորից փորձեք:"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Կարող եք փորձել ուղարկել հաղորդագրությունը, սակայն այն չի կարող առաքվել, եթե չհեռացնեք մեկ կամ ավելի կցորդ:"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Ամեն մի հաղորդագրության համար կարող եք միայն մեկ տեսանյութ ուղարկել: Հեռացրեք ավելորդ տեսանյութերը և նորից փորձեք:"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Կցորդը չբեռնվեց:"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Ուղարկել ամեն դեպքում"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Չհաջողվեց սկսել խոսակցությունը"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Ընտրված է <xliff:g id="SELECTED_SIM">%s</xliff:g> քարտը"</string>
+</resources>
diff --git a/res/values-in/arrays.xml b/res/values-in/arrays.xml
new file mode 100644
index 0000000..ce2892e
--- /dev/null
+++ b/res/values-in/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"tanpa subjek"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ya"</item>
+    <item msgid="6049132459802288033">"Tidak"</item>
+    <item msgid="3084376867445867895">"Oke"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Terima kasih"</item>
+    <item msgid="4881335087096496747">"Saya setuju"</item>
+    <item msgid="2422296858597420738">"Bagus"</item>
+    <item msgid="4805581752819452687">"Dalam perjalanan"</item>
+    <item msgid="4746700499431366214">"Oke, saya akan menghubungi Anda nanti"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
new file mode 100644
index 0000000..3b65bb2
--- /dev/null
+++ b/res/values-in/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Perpesanan"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Perpesanan"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Pilih percakapan"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Setelan"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Kirim Pesan"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Tambahkan lampiran"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Bantuan"</string>
+    <string name="welcome" msgid="2857560951820802321">"Selamat Datang"</string>
+    <string name="skip" msgid="7238879696319945853">"Lewati"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Berikutnya &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Berikutnya"</string>
+    <string name="exit" msgid="1905187380359981199">"Keluar"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Setelan &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Setelan"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Perpesanan perlu izin ke SMS, Telepon, dan Kontak"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Anda dapat mengubah izin di Setelan &gt; Aplikasi &gt; Perpesanan &gt; Izin."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Anda dapat mengubah izin di Setelan, Aplikasi, Messaging, Permissions."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Sering"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Semua kontak"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Kirim ke <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Jepret gambar atau rekam video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Pilih gambar dari perangkat ini"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Rekam audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Pilih foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Media ini dipilih."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Media ini batal dipilih."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> dipilih"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"gambar <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"gambar"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Rekam audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Bagikan"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Baru saja"</string>
+    <string name="posted_now" msgid="867560789350406701">"Sekarang"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> mnt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> mnt</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> jam</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> jam</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hari</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hari</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minggu</item>
+      <item quantity="one">seminggu</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> bulan</item>
+      <item quantity="one">sebulan</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tahun</item>
+      <item quantity="one">setahun</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Pesan kelas 0"</string>
+    <string name="save" msgid="5081141452059463572">"Simpan"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Perangkat hampir kehabisan ruang. Perpesanan akan secara otomatis menghapus pesan lama untuk mengosongkan ruang."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Ruang penyimpanan hampir habis"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Perpesanan tidak dapat mengirim atau menerima pesan hingga lebih banyak ruang tersedia di perangkat Anda."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Penyimpanan SMS tinggal sedikit. Anda perlu menghapus pesan."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Konfirmasi nomor telepon Anda"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Langkah satu kali ini akan memastikan bahwa Perpesanan mengirim pesan grup dengan tepat."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Nomor telepon"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Hapus semua pesan dengan media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Hapus pesan yang sudah lebih dari <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Hapus otomatis pesan yang sudah lebih dari <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Abaikan"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Hapus semua pesan dengan media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Hapus pesan yang sudah lebih dari <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Hapus pesan yang sudah lebih dari <xliff:g id="DURATION">%s</xliff:g> dan aktifkan fitur hapus otomatis?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> mengatakan"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Anda mengatakan"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Pesan dari <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Anda telah mengirim pesan"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Mengirim…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Tidak dikirim. Sentuh untuk mencoba lagi."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Tidak dikirim. Mencoba lagi..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Kirim ulang atau hapus"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Lakukan panggilan suara ke layanan darurat. SMS Anda tidak dapat dikirim saat ini."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Gagal"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Pesan MMS baru untuk diunduh"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Pesan MMS baru"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Tidak dapat mengunduh"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Sentuh untuk mencoba lagi"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Sentuh untuk mengunduh"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Unduh atau hapus"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Mengunduh..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Pesan sudah tidak berlaku atau tidak tersedia"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ukuran: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, waktu berakhir: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Tidak dapat mengirim. Penerima tidak valid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Layanan tidak diaktifkan pada jaringan"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Tidak dapat mengirim karena masalah jaringan"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Pesan sudah tidak berlaku atau tidak tersedia"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Tanpa subjek)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Pengirim tidak diketahui"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Telah Diantar"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Tidak dapat mengunduh pesan <xliff:g id="SUBJECT">%1$s</xliff:g> dari <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Tidak dapat menyelesaikan operasi basis data karena memori terlalu kecil"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Pesan tidak dikirim"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Beberapa pesan tidak terkirim di Perpesanan"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> pesan dalam <xliff:g id="CONVERSATIONS">%d</xliff:g> percakapan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> pesan dalam satu percakapan</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Pesan tidak diunduh"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Beberapa pesan tidak diunduh di Perpesanan"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> pesan dalam <xliff:g id="CONVERSATIONS">%d</xliff:g> percakapan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> pesan dalam satu percakapan</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Pesan ke <xliff:g id="NUMBER">%1$s</xliff:g> tidak terkirim"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Lakukan panggilan suara ke layanan darurat. SMS Anda ke <xliff:g id="NUMBER">%1$s</xliff:g> tidak dapat dikirim saat ini."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> pesan baru</item>
+      <item quantity="one">Pesan baru</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Mulai"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Tidak ada kamera"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Tidak ada kamera"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Tidak ada rekaman video"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Tidak dapat menyimpan media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Tidak dapat memfoto"</string>
+    <string name="back" msgid="1477626055115561645">"Kembali"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Diarsipkan"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Hapus"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arsipkan"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Batalkan pengarsipan"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Nonaktifkan pemberitahuan"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Aktifkan pemberitahuan"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Tambahkan kontak"</string>
+    <string name="action_download" msgid="7786338136368564146">"Unduh"</string>
+    <string name="action_send" msgid="377635240181672039">"Kirim"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Hapus"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Hapus pesan ini?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tindakan ini tidak dapat diurungkan."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Hapus"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Hapus percakapan ini?</item>
+      <item quantity="one">Hapus percakapan ini?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Hapus"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Batal"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kepada"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Pilih beberapa gambar"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Konfirmasi pilihan"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Tidak dapat merekam audio. Coba lagi."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Tidak dapat memutar audio. Coba lagi."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Tidak dapat menyimpan audio. Coba lagi."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Sentuh &amp; tahan"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Gambar"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Klip audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kartu kontak"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Unduh"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Balas via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Balas via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Balas"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> peserta</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> peserta</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Saya"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontak diblokir &amp; diarsipkan"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontak tidak diblokir lagi &amp; batal diarsipkan"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> diarsipkan"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> batal diarsipkan"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifikasi dinonaktifkan"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifikasi diaktifkan"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Semua siap. Sentuh Kirim lagi."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Perpesanan berhasil disetel sebagai aplikasi SMS default."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Buang lampiran</item>
+      <item quantity="one">Buang lampiran</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Lampiran audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Putar lampiran audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Jeda"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Pesan dari <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Pesan gagal dari <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Pesan dari <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Pesan yang tidak terkirim ke <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Mengirim pesan ke <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Pesan gagal ke <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Pesan ke <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Pesan gagal dari <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Pesan dari <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Pesan yang tidak terkirim ke <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Mengirim pesan ke <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Pesan gagal ke <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Pesan ke <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Waktu: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Pesan gagal. Sentuh untuk mencoba lagi."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Percakapan dengan <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Hapus subjek"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Ambil video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Ambil gambar diam"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Ambil gambar"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Mulai merekam video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Beralih ke kamera layar penuh"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Beralih antara kamera depan dan belakang"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Hentikan perekaman dan lampirkan video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Berhenti merekam video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto Perpesanan"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> lampiran disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> lampiran disimpan ke \"Unduhan\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan ke \"Unduhan\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> lampiran disimpan</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Tidak dapat menyimpan <xliff:g id="QUANTITY_1">%d</xliff:g> lampiran</item>
+      <item quantity="one">Tidak dapat menyimpan <xliff:g id="QUANTITY_0">%d</xliff:g> lampiran</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Lampiran MMS yang disimpan"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Setelan"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Diarsipkan"</string>
+    <string name="action_close" msgid="1840519376200478419">"Tutup"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Lanjutan"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifikasi"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Suara"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Senyap"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Getar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Diblokir"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Laporan pengiriman SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Minta laporan pengiriman dari setiap SMS yang Anda kirimkan"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Ambil otomatis"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Otomatis ambil pesan MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Ambil otomatis saat roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Otomatis ambil MMS saat roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Perpesanan grup"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Gunakan MMS untuk mengirimkan pesan tunggal saat ada beberapa penerima"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplikasi SMS default"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplikasi SMS default"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Nomor telepon Anda"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Tidak dikenal"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Pesan suara keluar"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Buang SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Buang data mentah SMS yang diterima ke dalam file penyimpanan eksternal"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Buang MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Buang data mentah MMS yang diterima ke file penyimpanan eksternal"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Lansiran nirkabel"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opsi pesan"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Salin teks"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Lihat detail"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Hapus"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Teruskan"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detail pesan"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Jenis: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Pesan teks"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Pesan multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"Dari: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kepada: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Dikirim: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Diterima: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subjek: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Ukuran: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritas: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Tinggi"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Rendah"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Alamat pengirim tersembunyi"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Tidak dapat mengirim pesan saat memuat lampiran."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Tidak dapat memuat lampiran. Coba lagi."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Jaringan tidak siap. Coba lagi."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Hapus teks"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Beralih antara memasukkan teks dan angka"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Tambahkan peserta lainnya"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Konfirmasi peserta"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Mulai percakapan baru"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Pilih item ini"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Putar video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Orang &amp; opsi"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Orang &amp; opsi"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Umum"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Orang dalam percakapan ini"</string>
+    <string name="action_call" msgid="6596167921517350362">"Lakukan panggilan telepon"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Kirim pesan"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Kirim pesan&lt;br/&gt;&lt;small&gt;dari <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Kirim foto</item>
+      <item quantity="one">Kirim foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Kirim audio</item>
+      <item quantity="one">Kirim audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Kirim video</item>
+      <item quantity="one">Kirim video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Kirim kartu kontak</item>
+      <item quantity="one">Kirim kartu kontak</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Kirim lampiran</item>
+      <item quantity="one">Kirim lampiran</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> lampiran siap dikirim</item>
+      <item quantity="one">Satu lampiran siap dikirim</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Kirim masukan"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Lihat di Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Info versi"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versi %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Lisensi sumber terbuka"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifikasi"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Batas lampiran tercapai"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Gagal memuat lampiran."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Tambahkan ke Kontak?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Tambahkan Kontak"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subjek"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subjek: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Memuat kartu kontak"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Tidak dapat memuat kartu kontak"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Lihat kartu kontak"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontak</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontak</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kartu kontak"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Ulang Tahun"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Catatan"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Teruskan pesan"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Balas"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS dinonaktifkan"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Untuk mengirim, setel Perpesanan sebagai aplikasi SMS default"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Setel Perpesanan sebagai aplikasi SMS default"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Ganti"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Untuk menerima pesan, setel Perpesanan sebagai aplikasi SMS default."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Tidak ada SIM yang dipilih untuk mengirim pesan SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Aplikasi ini tidak diizinkan oleh pemilik perangkat."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Oke"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Terlalu banyak peserta dalam percakapan"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Kontak tidak valid</item>
+      <item quantity="one">Kontak tidak valid</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Tidak dapat memuat gambar kamera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Anda: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draf"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Setelah memulai percakapan baru, Anda akan melihatnya tercantum di sini"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arsip percakapan muncul di sini"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Memuat percakapan..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Gambar"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Klip audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kartu kontak"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Urungkan"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Coba lagi"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Masukkan nama atau nomor telepon yang dapat dihubungi untuk memulai pesan baru"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokir"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokir <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Bebaskan <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokir <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Anda akan terus menerima pesan dari nomor ini, tetapi tidak akan diberi tahu lagi. Percakapan ini akan diarsipkan."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Kontak yang diblokir"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"BEBASKAN"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Kontak yang diblokir"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Pilih gambar dari perpustakaan dokumen"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Mengirim pesan"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Pesan terkirim"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Data seluler dinonaktifkan. Periksa setelan."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Tidak dapat mengirim pesan dalam mode Pesawat"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Pesan tidak dapat dikirim"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Pesan diunduh"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Data seluler dinonaktifkan. Periksa setelan."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Tidak dapat mengunduh pesan dalam mode Pesawat"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Pesan tidak dapat diunduh"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nol"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Satu"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dua"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tiga"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Empat"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Lima"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Enam"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Tujuh"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Delapan"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Sembilan"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Tidak dapat mengirim pesan dengan <xliff:g id="CARRIERNAME">%1$s</xliff:g>, kesalahan <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Tidak dapat mengirim pesan dengan operator tak dikenal, kesalahan <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Trs: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Pesan tidak terkirim: layanan tidak diaktifkan di jaringan"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Pesan tidak terkirim: alamat tujuan tidak valid"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Pesan tidak terkirim: pesan tidak valid"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Pesan tidak terkirim: konten tidak didukung"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Pesan tidak terkirim: pesan tidak didukung"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Pesan tidak terkirim: terlalu besar"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Pesan baru"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Lihat"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Gambar"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Aplikasi yang sesuai tidak dapat ditemukan"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Hapus penerima"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Pesan baru"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Batal"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit titik akses"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Belum disetel"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nama"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Jenis APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Hapus APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN baru"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Simpan"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Buang"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Bidang Nama wajib diisi."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN wajib diisi."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Bidang MCC harus terdiri dari 3 digit."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Bidang MNC harus 2 atau 3 digit."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Memulihkan setelan APN default."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Setel ulang ke default"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Penyetelan ulang setelan APN default selesai."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Tanpa judul"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nama Titik Akses"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN baru"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Setelan Nama Titik Akses tidak tersedia untuk pengguna ini"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Salin ke papan klip?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Salin"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"kepada <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Umum"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Lanjutan"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Setelan umum"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Setelan lanjutan"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Kirimkan pesan SMS individual ke semua penerima. Hanya Anda yang akan mendapatkan balasan"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Kirimkan satu MMS ke semua penerima"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nomor tidak dikenal"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Pesan baru"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Pesan baru."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Pemilih SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> dipilih, pemilih SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edit subjek"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Pilih SIM atau edit subjek"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Sentuh dan tahan untuk merekam audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Mulai percakapan baru"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Perpesanan"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Daftar Perpesanan"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Perpesanan"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Pesan baru"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Daftar percakapan"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Memuat percakapan"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Memuat pesan"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Lihat percakapan lain"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Lihat pesan lainnya"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Percakapan telah dihapus"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Percakapan dihapus. Sentuh untuk menampilkan percakapan Perpesanan yang berbeda"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Diblokir"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Dibebaskan"</string>
+    <string name="db_full" msgid="8459265782521418031">"Sedikit ruang penyimpanan. Beberapa data mungkin hilang."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Pilih lampiran"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Konfirmasi pilihan"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> dipilih"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Hapus satu atau beberapa lampiran dan coba lagi."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Anda dapat mencoba mengirim pesan, tetapi pesan tersebut mungkin tidak terkirim, kecuali Anda menghapus satu atau beberapa lampiran."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Anda hanya dapat mengirim satu video per pesan. Hapus video tambahan dan coba lagi."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Perpesanan gagal memuat lampiran."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Tetap kirim"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Tidak dapat memulai percakapan"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> dipilih"</string>
+</resources>
diff --git a/res/values-is/arrays.xml b/res/values-is/arrays.xml
new file mode 100644
index 0000000..f8d4803
--- /dev/null
+++ b/res/values-is/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ekkert efni"</item>
+    <item msgid="272485471009191934">"ekkertefni"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Já"</item>
+    <item msgid="6049132459802288033">"Nei"</item>
+    <item msgid="3084376867445867895">"Í lagi"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Takk"</item>
+    <item msgid="4881335087096496747">"Ég er sammála"</item>
+    <item msgid="2422296858597420738">"Flott"</item>
+    <item msgid="4805581752819452687">"Er á leiðinni"</item>
+    <item msgid="4746700499431366214">"Ókei, ég fæ að hafa samband síðar"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
new file mode 100644
index 0000000..f02a11c
--- /dev/null
+++ b/res/values-is/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Skilaboð"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Skilaboð"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Veldu samtal"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Stillingar"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Senda skilaboð"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Bæta viðhengi við"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hjálp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Komdu fagnandi"</string>
+    <string name="skip" msgid="7238879696319945853">"Sleppa"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Áfram &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Áfram"</string>
+    <string name="exit" msgid="1905187380359981199">"Hætta"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Stillingar &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Stillingar"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Skilaboð þurfa heimild til að fá aðgang að SMS-skilaboðum, síma og tengiliðum."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Þú getur breytt heimildum undir Stillingar &gt; Forrit &gt; Skilaboð &gt; Heimildir."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Þú getur breytt heimildum undir Stillingar, Forrit, Skilaboð, Heimildir."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Algengir"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Allir tengiliðir"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Senda í <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Taka myndir eða myndskeið"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Velja myndir úr þessu tæki"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Taka upp hljóð"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Velja mynd"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Efnið er valið."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Efnið er ekki valið."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> valin"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"mynd <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"mynd"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Taka upp hljóð"</string>
+    <string name="action_share" msgid="2143483844803153871">"Deila"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Rétt í þessu"</string>
+    <string name="posted_now" msgid="867560789350406701">"Núna"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> mín.</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> mín.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> klukkustund</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> klukkustundir</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dagur</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dagar</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> vika</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> vikur</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mánuður</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mánuðir</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ár</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ár</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Einnota skilaboð"</string>
+    <string name="save" msgid="5081141452059463572">"Vista"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Lítið pláss er í tækinu. Skilaboðaforritið mun sjálfkrafa eyða gömlum skilaboðum til að losa um pláss."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Geymslurýmið er senn á þrotum"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Ekki er víst að Skilaboð geti sent eða tekið á móti skilaboðum fyrr en meira pláss er til staðar í tækinu."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS-geymsla að fyllast. Þú gætir þurft að eyða skilaboðum."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Staðfestu símanúmerið þitt"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Þetta þarf að gera í eitt skipti til að tryggja að Skilaboð komi hópskilaboðunum þínum til skila á réttan hátt."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Símanúmer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Eyða öllum skilaboðum með margmiðlunarefni"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Eyða skilaboðum sem eru eldri en <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Eyða sjálfkrafa skilaboðum sem eru eldri en <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Hunsa"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Eyða öllum skilaboðum með margmiðlunarefni?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Eyða skilaboðum sem eru eldri en <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Eyða skilaboðum sem eru eldri en <xliff:g id="DURATION">%s</xliff:g> og kveikja á sjálfvirkri eyðingu?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sagði"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Þú sagðir"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Þú sendir skilaboð"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sendir…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ekki sent. Snertu til að reyna aftur."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ekki sent. Reynir aftur…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Endursenda eða eyða"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Hringdu í neyðarþjónustuna. Ekki tókst að senda textaskilaboðin þín á þessari stundu."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Mistókst"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Ný MMS-skilaboð til að sækja"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Ný MMS-skilaboð"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Ekki hægt að sækja"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Snertu til að reyna aftur"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Snertu til að sækja"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Sækja eða eyða"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Sækir…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Skilaboð útrunnin eða ekki aðgengileg"</string>
+    <string name="mms_info" msgid="3402311750134118165">"stærð: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, útrunnið: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Ekki er hægt að senda. Viðtakandinn er ekki gildur."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Símkerfið hefur ekki gert þjónustuna virka"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Sending mistókst vegna símkerfisvandamáls"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Skilaboð útrunnin eða ekki aðgengileg"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Ekkert efni)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Óþekktur sendandi"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Sent"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Ekki var hægt að sækja skilaboðin <xliff:g id="SUBJECT">%1$s</xliff:g> sem <xliff:g id="FROM">%2$s</xliff:g> sendi."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Lítið minni varð til þess að ekki var hægt að ljúka gagnagrunnsaðgerðinni"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Skilaboð ekki send"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Einhver skilaboð voru ekki send í Skilaboðum"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> skilaboð í <xliff:g id="CONVERSATIONS">%d</xliff:g> samtali</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> skilaboð í <xliff:g id="CONVERSATIONS">%d</xliff:g> samtölum</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Skilaboð ekki sótt"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Einhver skilaboð voru ekki sótt í Skilaboð"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> skilaboð í <xliff:g id="CONVERSATIONS">%d</xliff:g> samtali</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> skilaboð í <xliff:g id="CONVERSATIONS">%d</xliff:g> samtölum</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Skilaboð til <xliff:g id="NUMBER">%1$s</xliff:g> voru ekki send"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Hringdu í neyðarþjónustuna. Ekki tókst að senda textaskilaboðin þín í númerið <xliff:g id="NUMBER">%1$s</xliff:g> á þessari stundu."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> ný skilaboð</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ný skilaboð</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Byrja"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Myndavélin er ekki tiltæk"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Myndavélin er ekki tiltæk"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Upptaka myndskeiða er ekki tiltæk"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Ekki er hægt að vista efni"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Ekki er hægt að taka mynd"</string>
+    <string name="back" msgid="1477626055115561645">"Til baka"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Geymsla"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Eyða"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Setja í geymslu"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Taka úr geymslu"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Slökkva á tilkynningum"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Kveikja á tilkynningum"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Bæta tengilið við"</string>
+    <string name="action_download" msgid="7786338136368564146">"Sækja"</string>
+    <string name="action_send" msgid="377635240181672039">"Senda"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Eyða"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Eyða þessum skilaboðum?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ekki er hægt að afturkalla þessa aðgerð."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Eyða"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Eyða þessum samtölum?</item>
+      <item quantity="other">Eyða þessum samtölum?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Eyða"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Hætta við"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Til"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Velja margar myndir"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Staðfesta val"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Ekki er hægt að taka upp hljóð. Reyndu aftur."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Ekki er hægt að spila hljóð. Reyndu aftur."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Ekki var hægt að vista hljóð. Reyndu aftur."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Haltu inni"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Mynd"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Hljóðbútur"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Myndskeið"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Tengiliðaspjald"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Sækja"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Svara með SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Svara með MMS-skilaboðum"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Svara"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> þátttakandi</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> þátttakendur</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ég"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Tengiliður settur á bannlista og í geymslu"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Tengiliður tekinn af bannlista og úr geymslu"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> sett í geymslu"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> tekin úr geymslu"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Slökkt á tilkynningum"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Kveikt á tilkynningum"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Allt til reiðu. Snertu Senda aftur."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Skilaboð voru valin sem sjálfgefið SMS-forrit."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Fleygja viðhengjum</item>
+      <item quantity="other">Fleygja viðhengjum</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Hljóðviðhengi"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Spila hljóðviðhengi"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Hlé"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Misheppnuð skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ósend skilaboð til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sendir skilaboð til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Misheppnuð skilaboð til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Skilaboð til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Misheppnuð skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Skilaboð sem <xliff:g id="SENDER">%1$s</xliff:g> sendi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ósend skilaboð til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sendir skilaboð til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Misheppnuð skilaboð til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Skilaboð til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tími: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Misheppnuð skilaboð. Snertu til að reyna aftur."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Samtal við <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Eyða efni"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Taka upp myndskeið"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Taka kyrrmynd"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Taka mynd"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Byrja að taka upp myndskeið"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Skipta yfir í myndavél á öllum skjánum"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Skipt á milli fremri og aftari myndavélar"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stöðva upptöku og hengja myndskeið við"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Stöðva upptöku myndskeiðs"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Skilaboðamyndir"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> mynd vistuð í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> myndir vistaðar í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> myndskeið vistað í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> myndskeið vistuð í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> viðhengi vistað í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> viðhengi vistuð í „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“ möppu</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi vistað í „Niðurhal“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi vistuð í „Niðurhal“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi vistað</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi vistuð</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Ekki tókst að vista <xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi</item>
+      <item quantity="other">Ekki tókst að vista <xliff:g id="QUANTITY_1">%d</xliff:g> viðhengi</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS-viðhengi vistað"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Stillingar"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Geymsla"</string>
+    <string name="action_close" msgid="1840519376200478419">"Loka"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Ítarlegt"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Villuleita"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Tilkynningar"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Hljóð"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Hljóðlaust"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Titringur"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Á bannlista"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS-skilatilkynningar"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Óska eftir skilatilkynningu fyrir hver send SMS-skilaboð"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Sækja sjálfkrafa"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Sækja MMS-skilaboð sjálfkrafa"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Sækja sjálfkrafa í reiki"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Sækja MMS sjálfkrafa í reiki"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Hópskilaboð"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Nota MMS til að senda ein skilaboð þegar viðtakendur eru margir"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Sjálfgefið SMS-forrit"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Sjálfgefið SMS-forrit"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Símanúmerið þitt"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Óþekkt"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Hljóð fyrir send skilaboð"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Vista SMS-gögn"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Vista ósniðin SMS-gögn í ytri geymsluskrá"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Vista MMS-gögn"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Vista ósniðin MMS-gögn í ytri geymsluskrá"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Þráðlausar viðvaranir"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Skilaboðavalkostir"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Afrita texta"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Skoða upplýsingar"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Eyða"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Áframsenda"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Skilaboðaupplýsingar"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Gerð: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Textaskilaboð"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Margmiðlunarskilaboð"</string>
+    <string name="from_label" msgid="1947831848146564875">"Frá: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Til: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sent: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Móttekið: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Efni: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Stærð: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Forgangur: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-kort: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Hár"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Venjulegur"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Lágur"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-kort <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Falið netfang sendanda"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Ekki er hægt að senda skilaboð á meðan verið er að hlaða viðhengi."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Ekki er hægt að hlaða viðhengi. Reyndu aftur."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Netið er ekki tilbúið. Reyndu aftur."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Eyða texta"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Skipta á milli innsláttar texta og talna"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Bæta við fleiri þátttakendum"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Staðfesta þátttakendur"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Byrja nýtt samtal"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Velja þetta atriði"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Spila myndskeið"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Fólk og valkostir"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Villuleita"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Fólk og valkostir"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Almennt"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Fólk í þessu samtali"</string>
+    <string name="action_call" msgid="6596167921517350362">"Hringja símtal"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Senda skilaboð"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Senda skilaboð&lt;br/&gt;&lt;small&gt;úr <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Senda myndir</item>
+      <item quantity="other">Senda myndir</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Senda hljóð</item>
+      <item quantity="other">Senda hljóð</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Senda myndskeið</item>
+      <item quantity="other">Senda myndskeið</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Senda tengiliðaspjöld</item>
+      <item quantity="other">Senda tengiliðaspjöld</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Senda viðhengi</item>
+      <item quantity="other">Senda viðhengi</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> viðhengi tilbúið til sendingar</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> viðhengi tilbúin til sendingar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Senda ábendingu"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Skoða í Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Útgáfuupplýsingar"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Útgáfa %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Leyfi opins kóða"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Tilkynningar"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Hámarki viðhengja náð"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Mistókst að hlaða viðhengið."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Bæta við tengiliði?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Bæta tengilið við"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Efni"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Efni: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Hleður tengiliðaspjald"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Ekki var hægt að hlaða tengiliðaspjald"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Skoða tengiliðaspjald"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> tengiliður</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> tengiliðir</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Tengiliðaspjöld"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Fæðingardagur"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Athugasemdir"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Áframsenda skilaboð"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Svara"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Slökkt á SMS"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Til að senda skaltu velja Skilaboð sem sjálfgefið SMS-forrit"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Veldu Skilaboð sem sjálfgefið SMS-forrit"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Breyta"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Til að fá skilaboð skaltu velja Skilaboð sem sjálfgefið SMS-forrit"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ekkert SIM-kort valið fyrir sendingu SMS-skilaboða"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Eigandi tækisins leyfir ekki þetta forrit."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Í lagi"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Of margir þátttakendur í samtali"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Ógildir tengiliðir</item>
+      <item quantity="other">Ógildir tengiliðir</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Ekki var hægt að hlaða mynd frá myndavél"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Þú: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Drög"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Þegar þú hefur nýtt samtal birtist það hér"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Samtöl í geymslu birtast hér"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Hleður samtöl…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Mynd"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Hljóðbútur"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Myndskeið"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Tengiliðaspjald"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Afturkalla"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Reyna aftur"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Sláðu inn nafn eða símanúmer tengiliðar til að búa til ný skilaboð"</string>
+    <string name="action_block" msgid="9032076625645190136">"Setja á bannlista"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Útiloka <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Taka <xliff:g id="DESTINATION">%s</xliff:g> af bannlista"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Loka á <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Þú heldur áfram að fá skilaboð úr þessu númeri en færð ekki lengur tilkynningar. Þetta samtal verður sett í geymslu."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Útilokaðir tengiliðir"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"TAKA AF BANNLISTA"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Útilokaðir tengiliðir"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Velja mynd úr skjalasafni"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sendir skilaboð"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Skilaboð send"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Slökkt er á farsímagögnum. Athugaðu stillingarnar."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Ekki er hægt að senda skilaboð þegar flugstilling er virk"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Ekki var hægt að senda skilaboðin"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Skilaboð sótt"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Slökkt er á farsímagögnum. Athugaðu stillingarnar."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Ekki er hægt að sækja skilaboð þegar flugstilling er virk"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Ekki var hægt að sækja skilaboðin"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Núll"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Einn"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Tveir"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Þrír"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Fjórir"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Fimm"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sex"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sjö"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Átta"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Níu"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Ekki er hægt að senda skilaboð í gegnum <xliff:g id="CARRIERNAME">%1$s</xliff:g>, villa <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Ekki er hægt að senda skilaboð í gegnum óþekkt símafyrirtæki, villa <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Áfrs.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Skilaboðin voru ekki send. Símkerfið hefur ekki gert þjónustuna virka"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Skilaboðin voru ekki send: Ógildur áfangastaður"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Skilaboðin voru ekki send: Ógild skilaboð"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Skilaboðin voru ekki send: Óstutt innihald"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Skilaboðin voru ekki send: Óstudd skilaboð"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Skilaboðin voru ekki send: Of stór"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Ný skilaboð"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Skoða"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Mynd"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Viðeigandi forrit fannst ekki"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Fjarlægja viðtakanda"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Ný skilaboð"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Hætta við"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Breyta aðgangsstað"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ekki stillt"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Heiti"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Aðgangsstaður"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy-þjónn fyrir MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-gátt"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tegund aðgangsstaðar"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Eyða aðgangsstað"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nýr aðgangsstaður"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Vista"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Fleygja"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Reiturinn fyrir heiti má ekki vera auður."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Heiti aðgangsstaðar má ekki vera autt."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-reitur verður að innihalda 3 tölustafi."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-reitur verður að innihalda 2 eða 3 tölustafi."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Endurheimtir sjálfgefnar stillingar aðgangsstaðar."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Núllstilla"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Sjálfgefnar stillingar aðgangsstaðar endurheimtar."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Ónefnt"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Heiti aðgangsstaða"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Aðgangsstaðir"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nýr aðgangsstaður"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Stillingar fyrir heiti aðgangsstaðar eru ekki í boði fyrir þennan notanda"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Afrita á klippiborð?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Afrita"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"á <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Almennt"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Ítarlegt"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Almennar stillingar"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Ítarlegar stillingar"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM-kortið „<xliff:g id="SIM_NAME">%s</xliff:g>“"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Senda sérstök SMS-skilaboð til hvers viðtakanda fyrir sig. Svör verða aðeins send til þín"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Senda ein MMS-skilaboð til allra viðtakenda"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Óþekkt númer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Ný skilaboð"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Ný skilaboð."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Val á SIM-korti"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> valið, val á SIM-korti"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Breyta efni"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Velja SIM-kort eða breyta efni"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Haltu inni til að taka upp hljóð"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Hefja nýtt samtal"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Skilaboð"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Skilaboðalisti"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Skilaboð"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Ný skilaboð"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Samtalalisti"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Hleður samtöl"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Hleður skilaboð"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Skoða fleiri samtöl"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Skoða fleiri skilaboð"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Samtali eytt"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Samtali eytt. Snertu til að sýna annað samtal í Skilaboðum"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Á bannlista"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Tekin(n) af bannlista"</string>
+    <string name="db_full" msgid="8459265782521418031">"Geymslupláss er á þrotum. Einhver gögn kunna að glatast."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Veldu viðhengi"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Staðfesta val"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> valin"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Fjarlægðu eitt eða fleiri viðhengi og reyndu aftur."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Þú getur prófað að senda skilaboðin en þau komast ef til vill ekki til skila nema þú fjarlægir eitt eða fleiri viðhengi."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Þú getur aðeins sent eitt myndskeið með hverjum skilaboðum. Fjarlægðu myndskeiðin sem eru umfram og reyndu aftur."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Skilaboð gátu ekki hlaðið viðhengið."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Senda samt"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Ekki tókst að hefja samtal"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> valið"</string>
+</resources>
diff --git a/res/values-it/arrays.xml b/res/values-it/arrays.xml
new file mode 100644
index 0000000..16f7792
--- /dev/null
+++ b/res/values-it/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"nessun oggetto"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sì"</item>
+    <item msgid="6049132459802288033">"No"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"He he"</item>
+    <item msgid="2611328818571146775">"Grazie"</item>
+    <item msgid="4881335087096496747">"Accetto"</item>
+    <item msgid="2422296858597420738">"Bene"</item>
+    <item msgid="4805581752819452687">"Sto arrivando"</item>
+    <item msgid="4746700499431366214">"OK, ti ricontatto più tardi"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
new file mode 100644
index 0000000..f041793
--- /dev/null
+++ b/res/values-it/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messaggi"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messaggi"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Seleziona conversazione"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Impostazioni"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Invia messaggio"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Aggiungi un allegato"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Guida"</string>
+    <string name="welcome" msgid="2857560951820802321">"Benvenuto"</string>
+    <string name="skip" msgid="7238879696319945853">"Ignora"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Avanti &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Avanti"</string>
+    <string name="exit" msgid="1905187380359981199">"Esci"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Impostazioni &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Impostazioni"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaggi richiede l\'autorizzazione per SMS, Telefono e Contatti."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Puoi modificare le autorizzazioni in Impostazioni &gt; Applicazioni &gt; Messaggi &gt; Autorizzazioni."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Puoi modificare le autorizzazioni in Impostazioni &gt; Applicazioni &gt; Messaggi &gt; Autorizzazioni."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequenti"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tutti i contatti"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Invia a <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Scatta foto o registra video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Scegli immagini su questo dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Registra audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Scegli foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Il contenuto multimediale è selezionato."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Il contenuto multimediale è deselezionato."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selezionati"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"immagine: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"immagine"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Registrazione audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Condividi"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Adesso"</string>
+    <string name="posted_now" msgid="867560789350406701">"Ora"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ore</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> giorni</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> giorno</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> settimane</item>
+      <item quantity="one">una settimana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mesi</item>
+      <item quantity="one">un mese</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> anni</item>
+      <item quantity="one">un anno</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Messaggio classe 0"</string>
+    <string name="save" msgid="5081141452059463572">"Salva"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Spazio insufficiente sul dispositivo. Messaggi eliminerà automaticamente i messaggi meno recenti per liberare spazio."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Spazio di archiviazione in esaurimento"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaggi potrebbe non inviare o ricevere messaggi finché non si libererà spazio sul dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Memoria per gli SMS scarsa. Potresti dover eliminare alcuni messaggi."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Conferma il tuo numero di telefono"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Con questo passaggio da eseguire una sola volta, puoi assicurarti che Messaggi invii correttamente i messaggi di gruppo."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numero di telefono"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Elimina tutti i messaggi con contenuti multimediali"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Elimina messaggi più vecchi di <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Elimina automaticamente messaggi più vecchi di <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignora"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Eliminare tutti i messaggi con contenuti multimediali?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Eliminare i messaggi più vecchi di <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Eliminare i messaggi più vecchi di <xliff:g id="DURATION">%s</xliff:g> e attivare l\'eliminazione automatica?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"Messaggio di <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Il tuo messaggio"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Messaggio di <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Hai inviato un messaggio"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Invio…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Non inviato. Tocca per riprovare."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Non inviato. Nuovo tentativo…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Invia di nuovo o elimina"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Effettua una chiamata vocale al numero di emergenza. Al momento non è possibile recapitare l\'SMS."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Operazione non riuscita"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nuovo messaggio MMS da scaricare"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nuovo messaggio MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Download non riuscito"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tocca per riprovare"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Tocca per scaricare"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Scarica o elimina"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Download..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Messaggio scaduto o non disponibile"</string>
+    <string name="mms_info" msgid="3402311750134118165">"dimensioni: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, scadenza: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Impossibile inviare. Destinatario non valido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Servizio non attivato sulla rete"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Invio non riuscito a causa di problemi di rete"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Messaggio scaduto o non disponibile"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Nessun oggetto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Mittente sconosciuto"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Recapitato"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Download del messaggio <xliff:g id="SUBJECT">%1$s</xliff:g> inviato da <xliff:g id="FROM">%2$s</xliff:g> non riuscito."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Completamento dell\'operazione nel database non riuscito a causa di memoria insufficiente"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Messaggio non inviato"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Alcuni messaggi non inviati in Messaggi"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messaggi in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversazioni</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messaggi in una conversazione</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Messaggio non scaricato"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Alcuni messaggi non scaricati in Messaggi"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> messaggi in <xliff:g id="CONVERSATIONS">%d</xliff:g> conversazioni</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> messaggi in una conversazione</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Messaggio al numero <xliff:g id="NUMBER">%1$s</xliff:g> non inviato"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Effettua una chiamata vocale al numero di emergenza. Al momento non è possibile recapitare l\'SMS al numero <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nuovi messaggi</item>
+      <item quantity="one">Nuovo messaggio</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Avvia"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotocamera non disponibile"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotocamera non disponibile"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Acquisizione video non disponibile"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Impossibile salvare i contenuti multimediali"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Impossibile scattare una foto"</string>
+    <string name="back" msgid="1477626055115561645">"Indietro"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archiviate"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Elimina"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivio"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Annulla archiviazione"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Disattiva notifiche"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Attiva notifiche"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Aggiungi contatto"</string>
+    <string name="action_download" msgid="7786338136368564146">"Scarica"</string>
+    <string name="action_send" msgid="377635240181672039">"Invia"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Elimina"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Eliminare questo messaggio?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"L\'operazione non può essere annullata."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Elimina"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Eliminare queste conversazioni?</item>
+      <item quantity="one">Eliminare questa conversazione?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Elimina"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Annulla"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"A"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Seleziona diverse immagini"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Conferma selezione"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"e altri <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Impossibile registrare l\'audio. Riprova."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Impossibile riprodurre l\'audio. Riprova."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Impossibile salvare l\'audio. Riprova."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Tocca e tieni premuto"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Immagine"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Scheda contatto"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Scarica"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Rispondi tramite SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Rispondi con MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Rispondi"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> partecipanti</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participante</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Io"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contatto bloccato e archiviato"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contatto sbloccato e non archiviato"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> archiviate"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> rimosse dall\'archivio"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notifiche disattivate"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notifiche attivate"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Fatto. Tocca di nuovo Invia."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaggi impostato correttamente come app predefinita per gli SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Elimina allegati</item>
+      <item quantity="one">Elimina allegato</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Allegato audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Riproduci allegato audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Metti in pausa"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Messaggio da <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Messaggio di <xliff:g id="SENDER">%1$s</xliff:g> non recapitato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Messaggio di <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Messaggio per <xliff:g id="CONTACT">%1$s</xliff:g> non inviato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Invio del messaggio a <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Messaggio per <xliff:g id="CONTACT">%1$s</xliff:g> non recapitato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Messaggio per <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Messaggio di <xliff:g id="SENDER">%1$s</xliff:g> non recapitato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Messaggio di <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Messaggio per <xliff:g id="GROUP">%1$s</xliff:g> non inviato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Invio del messaggio a <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Messaggio per <xliff:g id="GROUP">%1$s</xliff:g> non recapitato: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Messaggio per <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Data/ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Messaggio non recapitato. Tocca per riprovare."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversazione con <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Elimina oggetto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Registra video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Scatta una foto in posa"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Scatta una foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Inizia a registrare il video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Passa alla fotocamera a schermo intero"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Passa dalla fotocamera frontale a quella posteriore e viceversa"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Interrompi registrazione e aggiungi video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Interrompi registrazione video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto in Messaggi"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto salvate nell\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto salvata nell\'album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video salvati nell\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video salvato nell\'album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> allegati salvati nell\'album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> allegato salvato nell\'album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> allegati salvati in \"Download\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> allegato salvato in \"Download\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> allegati salvati</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> allegato salvato</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Impossibile salvare <xliff:g id="QUANTITY_1">%d</xliff:g> allegati</item>
+      <item quantity="one">Impossibile salvare <xliff:g id="QUANTITY_0">%d</xliff:g> allegato</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Allegato MMS salvato"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Impostazioni"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archiviate"</string>
+    <string name="action_close" msgid="1840519376200478419">"Chiudi"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avanzate"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notifiche"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Suono"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silenzioso"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrazione"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloccato"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Rapporti di consegna SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Richiedi conferma di recapito per ogni SMS inviato"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recupero automatico"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recupera messaggi MMS automaticamente"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recupero automatico in roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recupero automatico di MMS in roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Messaggi di gruppo"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utilizza gli MMS per inviare un unico messaggio a più destinatari"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"App SMS predefinita"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"App SMS predefinita"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Il tuo numero di telefono"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Sconosciuto"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Riproduzione audio per messaggi in uscita"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Scarica SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Scarica dati non elaborati SMS ricevuti in file di archiviazione esterna"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Scarica MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Scarica dati non elaborati MMS ricevuti in file di archiviazione esterna"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Avvisi wireless"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opzioni messaggio"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copia testo"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Visualizza dettagli"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Elimina"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Inoltra"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Dettagli messaggio"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Messaggio multimediale"</string>
+    <string name="from_label" msgid="1947831848146564875">"Da: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"A: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Inviato: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Ricevuto in data: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Oggetto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Dimensioni: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorità: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normale"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Bassa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Indirizzo mittente nascosto"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Impossibile inviare il messaggio durante il caricamento degli allegati."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Impossibile caricare l\'allegato. Riprova."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"La rete non è pronta. Riprova."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Elimina testo"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Passa tra immissione testo e numeri"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Aggiungi altri partecipanti"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Conferma partecipanti"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Inizia nuova conversazione"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Seleziona questo elemento"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Riproduci video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Persone e opzioni"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Persone e opzioni"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Generali"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Persone presenti nella conversazione"</string>
+    <string name="action_call" msgid="6596167921517350362">"Fai una chiamata"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Invia messaggio"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Invia messaggio&lt;br/&gt;&lt;small&gt;da <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Invia foto</item>
+      <item quantity="one">Invia foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Invia audio</item>
+      <item quantity="one">Invia audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Invia video</item>
+      <item quantity="one">Invia video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Invia schede contatti</item>
+      <item quantity="one">Invia scheda contatto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Invia allegati</item>
+      <item quantity="one">Invia allegato</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> allegati pronti da inviare</item>
+      <item quantity="one">Un allegato pronto da inviare</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Invia feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Visualizza nel Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Info versione"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versione %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenze open source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notifiche"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Limite di allegati raggiunto"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Impossibile caricare l\'allegato."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Aggiungere a Contatti?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Aggiungi contatto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Oggetto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Oggetto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Caricamento scheda contatto in corso"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Impossibile caricare la scheda del contatto"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Visualizza scheda contatto"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contatti</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contatto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Schede contatti"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Compleanno"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Note"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Inoltra messaggio"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Rispondi"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS disattivati"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Per inviare messaggi, imposta Messaggi come app predefinita per gli SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Imposta Messaggi come app predefinita per gli SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Modifica"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Per ricevere messaggi, imposta Messaggi come app predefinita per gli SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nessuna SIM preferita selezionata per l\'invio di messaggi SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Questa app non è consentita dal proprietario del dispositivo."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Troppi partecipanti alla conversazione"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Contatti non validi</item>
+      <item quantity="one">Contatto non valido</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Impossibile caricare l\'immagine della fotocamera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Tu: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Bozza"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Le nuove conversazioni che inizi verranno elencate qui"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Le conversazioni archiviate vengono visualizzate qui"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Caricamento conversazioni in corso..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Immagine"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Scheda contatto"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Annulla"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Riprova"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Inserisci il nome o il numero di telefono di un contatto per iniziare un nuovo messaggio"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blocca"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blocca <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Sblocca <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Bloccare <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Continuerai a ricevere messaggi da questo numero ma non riceverai più notifiche. Questa conversazione verrà archiviata."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contatti bloccati"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"SBLOCCA"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contatti bloccati"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Scegli immagine da raccolta documenti"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Invio messaggio"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Messaggio inviato"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Dati mobili non attivi. Controlla le impostazioni."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Impossibile inviare messaggi in modalità Aereo"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Messaggio non inviato"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Messaggio scaricato"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Dati mobili non attivi. Controlla le impostazioni."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Impossibile scaricare messaggi in modalità aereo"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Impossibile scaricare il messaggio"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Uno"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Due"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tre"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quattro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinque"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sei"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sette"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Otto"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nove"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Impossibile inviare il messaggio tramite <xliff:g id="CARRIERNAME">%1$s</xliff:g>. Errore <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Impossibile inviare il messaggio tramite un operatore sconosciuto. Errore <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Messaggio non inviato: servizio non attivato nella rete"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Messaggio non inviato: indirizzo di destinazione non valido"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Messaggio non inviato: messaggio non valido"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Messaggio non inviato: contenuti non supportati"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Messaggio non inviato: messaggio non supportato"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Messaggio non inviato: troppo grande"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nuovo messaggio"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Visualizza"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Immagine"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Impossibile trovare un\'applicazione adeguata"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Rimuovi destinatario"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nuovo messaggio"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Annulla"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Modifica punto di accesso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Non impostato"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nome"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Porta MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Elimina APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nuovo APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Salva"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Elimina"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Il campo Nome non può essere vuoto."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Il campo APN non può essere vuoto."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Il campo MCC deve contenere 3 cifre."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Il campo MNC deve contenere 2 o 3 cifre."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Ripristino delle impostazioni APN predefinite."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Ripristina impostazioni predefinite"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Ripristino delle impostazioni APN predefinite completato."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Senza titolo"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nomi punti di accesso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nuovo APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Le impostazioni del nome punto di accesso non sono disponibili per questo utente"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copiare negli appunti?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copia"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"a <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Generali"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avanzate"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Impostazioni generali"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Impostazioni avanzate"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Invia SMS singoli a tutti i destinatari. Soltanto tu riceverai le risposte"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Invia un singolo MMS a tutti i destinatari"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Numero sconosciuto"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nuovo messaggio"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nuovo messaggio."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selettore SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Scheda <xliff:g id="SIM_0">%1$s</xliff:g> selezionata, selettore SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Modifica oggetto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Seleziona la SIM o modifica l\'oggetto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Tocca e tieni premuto per registrare l\'audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Inizia nuova conversazione"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaggi"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Elenco messaggi"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaggi"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nuovo messaggio"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Elenco conversazioni"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Caricamento conversazioni..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Caricamento dei messaggi in corso"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Visualizza altre conversazioni"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Mostra altri messaggi"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversazione eliminata"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversazione eliminata. Tocca per vedere un\'altra conversazione di Messaggi"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloccato"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Sbloccato"</string>
+    <string name="db_full" msgid="8459265782521418031">"Lo spazio di archiviazione è quasi esaurito. Alcuni dati potrebbero andare perduti."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Seleziona allegati"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Conferma selezione"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selezionati"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Rimuovi uno o più allegati e riprova."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Puoi provare a inviare il messaggio, che però potrebbe non essere recapitato se non rimuovi uno o più allegati."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Puoi inviare un solo video per messaggio. Rimuovi i video aggiuntivi e riprova."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaggi non ha potuto caricare l\'allegato."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Invia comunque"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Impossibile avviare la conversazione"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"SIM selezionata: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-iw/arrays.xml b/res/values-iw/arrays.xml
new file mode 100644
index 0000000..91bd7db
--- /dev/null
+++ b/res/values-iw/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ללא נושא"</item>
+    <item msgid="272485471009191934">"ללא נושא"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"כן"</item>
+    <item msgid="6049132459802288033">"לא"</item>
+    <item msgid="3084376867445867895">"אישור"</item>
+    <item msgid="3155097332660174689">"חחח"</item>
+    <item msgid="2611328818571146775">"תודה"</item>
+    <item msgid="4881335087096496747">"אני מסכים"</item>
+    <item msgid="2422296858597420738">"נחמד"</item>
+    <item msgid="4805581752819452687">"אני בדרך"</item>
+    <item msgid="4746700499431366214">"אוקיי, נדבר מאוחר יותר"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
new file mode 100644
index 0000000..3f80e3c
--- /dev/null
+++ b/res/values-iw/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"העברת הודעות"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"העברת הודעות"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"בחר שיחה"</string>
+    <string name="action_settings" msgid="1329008122345201684">"הגדרות"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"שלח הודעה"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"הוסף קובץ מצורף"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"עזרה"</string>
+    <string name="welcome" msgid="2857560951820802321">"ברוכים הבאים!"</string>
+    <string name="skip" msgid="7238879696319945853">"דלג"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"‏הבא &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"הבא"</string>
+    <string name="exit" msgid="1905187380359981199">"צא"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"‏הגדרות &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"הגדרות"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"‏\'העברת הודעות\' זקוק להרשאות SMS, טלפון ואנשי קשר."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"‏תוכל לשנות את ההרשאות ב\'הגדרות\' &gt; \'אפליקציות\' &gt;‏ \'העברת הודעות\' ‏&gt; \'הרשאות\'."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"תוכל לשנות את ההרשאות ב\'הגדרות\', \'אפליקציות\', \'העברת הודעות\', \'הרשאות\'."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"בתדירות גבוהה"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"כל אנשי הקשר"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"שלח אל <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"צלם תמונות או סרטון"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"בחר תמונות ממכשיר זה"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"הקלט אודיו"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"בחר תמונה"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"בחרת במדיה."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ביטלת את הבחירה במדיה."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> נבחרו"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"תמונה <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"תמונה"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"הקלט אודיו"</string>
+    <string name="action_share" msgid="2143483844803153871">"שיתוף"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ממש עכשיו"</string>
+    <string name="posted_now" msgid="867560789350406701">"עכשיו"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> דקות</item>
+      <item quantity="one">דקה <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> שעות</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> שעות</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> שעות</item>
+      <item quantity="one">שעה <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> ימים</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> ימים</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ימים</item>
+      <item quantity="one">יום <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="two"> שבועות</item>
+      <item quantity="many"> שבועות<xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="other"> שבועות</item>
+      <item quantity="one">שבוע</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> חודשים</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> חודשים</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> חודשים</item>
+      <item quantity="one">חודש</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="two"> שנים</item>
+      <item quantity="many"> שנים<xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="other"> שנים</item>
+      <item quantity="one">שנה</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"הודעה ברמה 0"</string>
+    <string name="save" msgid="5081141452059463572">"שמור"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"נותר מעט שטח פנוי במכשיר. \'העברת הודעות\' ימחק הודעות ישנות באופן אוטומטי כדי לפנות שטח."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"שטח האחסון אוזל"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"לא תוכל לשלוח או לקבל הודעות ב\'העברת הודעות\' עד שתפנה שטח במכשיר."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"‏אין מספיק שטח אחסון להודעות SMS. ייתכן שתצטרך למחוק הודעות."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"אשר את מספר הטלפון שלך"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"שלב חד-פעמי זה יבטיח שהאפליקציה \'העברת הודעות\' תעביר כראוי את ההודעות הקבוצתיות שלך."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"מספר טלפון"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"מחק את כל ההודעות עם מדיה"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"מחק הודעות בנות יותר מ-<xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"מחק אוטומטית הודעות שגילן עולה על <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"התעלם"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"למחוק את כל ההודעות עם המדיה?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"למחוק הודעות שגילן עולה על <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"למחוק הודעות שגילן עולה על <xliff:g id="DURATION">%s</xliff:g> ולהפעיל מחיקה אוטומטית?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> אמר"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"אמרת"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"הודעה מאת <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"שלחת הודעה"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"שולח..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ההודעה לא נשלחה. גע כדי לנסות שוב."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ההודעה לא נשלחה. מנסה שוב…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"שלח שוב או מחק"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"בצע שיחה קולית לשירותי חירום. לא ניתן היה לשלוח את הודעת הטקסט."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"נכשל"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"‏הודעת MMS חדשה להורדה"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"‏הודעת MMS חדשה"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"לא ניתן לבצע את ההורדה"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"גע כדי לנסות שוב"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"גע כדי להוריד"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"הורד או מחק"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"מוריד…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"תוקף ההודעה פג או שהיא לא זמינה"</string>
+    <string name="mms_info" msgid="3402311750134118165">"גודל: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, תפוגה: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"לא ניתן לשלוח. הנמען אינו חוקי."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"השירות לא הופעל ברשת"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"לא ניתן לשלוח בגלל בעיה ברשת"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"התוקף של ההודעה פג או שהיא לא זמינה"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ללא נושא)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"שולח לא ידוע"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"נמסר"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"לא ניתן היה להוריד את ההודעה <xliff:g id="SUBJECT">%1$s</xliff:g> מ-<xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"לא ניתן היה להשלים את הפעולה של מסד הנתונים עקב זיכרון לא מספיק"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"ההודעה לא נשלחה"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"\'העברת הודעות\' לא שלח חלק מההודעות"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> הודעות בשיחה אחת</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"ההודעה לא הורדה"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"\'העברת הודעות\' לא הוריד חלק מההודעות"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> הודעות ב-<xliff:g id="CONVERSATIONS">%d</xliff:g> שיחות</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> הודעות בשיחה אחת</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"ההודעה אל <xliff:g id="NUMBER">%1$s</xliff:g> לא נשלחה"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"התקשר לשירותי חירום. לא ניתן היה לשלוח את הודעת הטקסט אל <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="two"><xliff:g id="MESSAGES">%d</xliff:g> הודעות חדשות</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> הודעות חדשות</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> הודעות חדשות</item>
+      <item quantity="one">הודעה חדשה</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"התחל"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"המצלמה לא זמינה"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"המצלמה לא זמינה"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"לכידת וידאו אינה זמינה"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"לא ניתן לשמור מדיה"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"לא ניתן לצלם את התמונה"</string>
+    <string name="back" msgid="1477626055115561645">"הקודם"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"הועברו לארכיון"</string>
+    <string name="action_delete" msgid="4076795795307486019">"מחק"</string>
+    <string name="action_archive" msgid="5437034800324083170">"העבר לארכיון"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"הוצאה מארכיון"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"כבה התראות"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"הפעל התראות"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"הוסף איש קשר"</string>
+    <string name="action_download" msgid="7786338136368564146">"הורד"</string>
+    <string name="action_send" msgid="377635240181672039">"שלח"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"מחק"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"למחוק הודעה זו?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"פעולה זו אינה הפיכה."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"מחק"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="two">האם למחוק את השיחות האלו?</item>
+      <item quantity="many">האם למחוק את השיחות האלו?</item>
+      <item quantity="other">האם למחוק את השיחות האלו?</item>
+      <item quantity="one">האם למחוק את השיחה הזו?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"מחק"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"בטל"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"אל"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"בחר תמונות מרובות"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"אשר את הבחירה"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"לא ניתן להקליט אודיו. נסה שוב."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"לא ניתן להפעיל אודיו. נסה שוב."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"לא ניתן לשמור אודיו. נסה שוב."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"גע והחזק"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"תמונה"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"קטע אודיו"</string>
+    <string name="notification_video" msgid="4331423498662606204">"סרטון"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"כרטיס איש קשר"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"הורד"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"‏השב באמצעות SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"‏השב באמצעות MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"השב"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> משתתפים</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> משתתפים</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> משתתפים</item>
+      <item quantity="one">משתתף <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"אני"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"איש הקשר נחסם והועבר לארכיון"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"חסימת איש הקשר בוטלה והוא הוצא מהארכיון"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> הועברו לארכיון"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> הוצאו מהארכיון"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ההודעות כבויות"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"ההודעות פועלות"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"הכל מוכן. גע באפשרות \'שלח שוב\'."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"‏האפליקציה \'העברת הודעות\' הוגדרה בהצלחה כאפליקציית ברירת המחדל ל-SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="two">מחק את הקבצים המצורפים</item>
+      <item quantity="many">מחק את הקבצים המצורפים</item>
+      <item quantity="other">מחק את הקבצים המצורפים</item>
+      <item quantity="one">מחק את הקובץ המצורף</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"קובץ אודיו מצורף"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"הפעל את קובץ האודיו המצורף"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"השהה"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"הודעה מאת <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"הודעה מאת <xliff:g id="SENDER">%1$s</xliff:g> שנכשלה: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"הודעה מאת <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"הודעה אל <xliff:g id="CONTACT">%1$s</xliff:g> שלא נשלחה: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"שולח הודעה אל <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"הודעה אל <xliff:g id="CONTACT">%1$s</xliff:g> שנכשלה: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"הודעה אל <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"הודעה שנכשלה מאת <xliff:g id="SENDER">%1$s</xliff:g>‏: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"הודעה מאת <xliff:g id="SENDER">%1$s</xliff:g>‏: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"הודעה אל <xliff:g id="GROUP">%1$s</xliff:g> שלא נשלחה: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"שולח הודעה אל <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"הודעה אל <xliff:g id="GROUP">%1$s</xliff:g> שנכשלה: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"הודעה אל <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. שעה: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ההודעה נכשלה. גע כדי לנסות שוב."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"שיחה עם <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"מחק נושא"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"צלם סרטון"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"צלם תמונת סטילס"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"צלם תמונה"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"התחל הקלטת סרטון"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"עבור למצלמה במסך מלא"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"החלף בין המצלמה הקדמית לאחורית"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"הפסק להקליט וצרף סרטון"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"עצור הקלטת וידאו"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"תמונות ב\'העברת הודעות\'"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> תמונות נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> תמונות נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> תמונות נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">תמונה <xliff:g id="QUANTITY_0">%d</xliff:g> נשמרה באלבום \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> סרטונים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> סרטונים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> סרטונים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">סרטון <xliff:g id="QUANTITY_0">%d</xliff:g> נשמר באלבום \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> קבצים מצורפים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> קבצים מצורפים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> קבצים מצורפים נשמרו באלבום \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">קובץ מצורף <xliff:g id="QUANTITY_0">%d</xliff:g> נשמר באלבום \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="two"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו ב\"הורדות\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו ב\"הורדות\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו ב\"הורדות\"</item>
+      <item quantity="one">קובץ מצורף <xliff:g id="QUANTITY_0">%d</xliff:g> נשמר ב\"הורדות\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="two"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים נשמרו</item>
+      <item quantity="one">קובץ מצורף <xliff:g id="QUANTITY_0">%d</xliff:g> נשמר</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="two">לא ניתן היה לשמור <xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים</item>
+      <item quantity="many">לא ניתן היה לשמור <xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים</item>
+      <item quantity="other">לא ניתן היה לשמור <xliff:g id="QUANTITY_1">%d</xliff:g> קבצים מצורפים</item>
+      <item quantity="one">לא ניתן היה לשמור קובץ מצורף <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"‏קובץ ה-MMS המצורף נשמר"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"הגדרות"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"הועברו לארכיון"</string>
+    <string name="action_close" msgid="1840519376200478419">"סגור"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"מתקדם"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ניפוי באגים"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"הודעות"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"צליל"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"מצב שקט"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"רטט"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"חסום"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"‏דוחות מסירת SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"‏בקש דוח מסירה לכל SMS שאתה שולח"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"אחזור אוטומטי"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"‏אחזור אוטומטי של הודעות MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"אחזור אוטומטי בנדידה"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"‏אחזר הודעות MMS באופן אוטומטי בזמן נדידה"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"העברת הודעות לקבוצה"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"‏השתמש ב-MMS לשליחת הודעה אחת לנמענים מרובים"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"‏אפליקציית SMS המוגדרת כברירת מחדל"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"‏אפליקציית SMS המוגדרת כברירת מחדל"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"מספר הטלפון שלך"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"לא ידוע"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"צלילים של הודעות יוצאות"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"‏צור Dump של SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"‏צור Dump בקובץ אחסון חיצוני עבור נתוני SMS גולמיים שהתקבלו"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"‏צור Dump של MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"‏צור Dump בקובץ אחסון חיצוני עבור נתוני MMS גולמיים שהתקבלו"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"התראות אלחוטיות"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"אפשרויות הודעה"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"העתק טקסט"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"הצגת פרטים"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"מחיקה"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"העבר"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"פרטי הודעה"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"סוג: "</string>
+    <string name="text_message" msgid="7415419755252205721">"הודעת טקסט"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"הודעת מולטימדיה"</string>
+    <string name="from_label" msgid="1947831848146564875">"מאת: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"אל: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"נשלחה ב: "</string>
+    <string name="received_label" msgid="4442494712757995203">"התקבלה ב: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"נושא: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"גודל: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"עדיפות: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"גבוהה"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"רגילה"</string>
+    <string name="priority_low" msgid="7398724779026801851">"נמוכה"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"‏SIM‏ <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"כתובת שולח מוסתרת"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"לא ניתן לשלוח הודעה בעת טעינת קבצים מצורפים."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"לא ניתן לטעון קובץ מצורף. נסה שוב."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"הרשת לא מוכנה. נסה שוב."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"מחק טקסט"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"עבור בין הזנה של אותיות וספרות"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"הוסף עוד משתמשים"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"אשר משתתפים"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"התחל שיחה חדשה"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"בחר בפריט הזה"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"הפעל סרטון"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"אנשים ואפשרויות"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ניפוי באגים"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"אנשים ואפשרויות"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"כללי"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"אנשים בשיחה הזו"</string>
+    <string name="action_call" msgid="6596167921517350362">"התקשר"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"שלח הודעה"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"‏שלח הודעה&lt;br/&gt;&lt;small&gt;מ-<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="two">שלח את התמונות</item>
+      <item quantity="many">שלח את התמונות</item>
+      <item quantity="other">שלח את התמונות</item>
+      <item quantity="one">שלח את התמונה</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="two">שלח את הקלטות האודיו</item>
+      <item quantity="many">שלח את הקלטות האודיו</item>
+      <item quantity="other">שלח את הקלטות האודיו</item>
+      <item quantity="one">שלח את הקלטת האודיו</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="two">שלח את הסרטונים</item>
+      <item quantity="many">שלח את הסרטונים</item>
+      <item quantity="other">שלח את הסרטונים</item>
+      <item quantity="one">שלח את הסרטון</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="two">שלח את כרטיסי אנשי הקשר</item>
+      <item quantity="many">שלח את כרטיסי אנשי הקשר</item>
+      <item quantity="other">שלח את כרטיסי אנשי הקשר</item>
+      <item quantity="one">שלח את כרטיס איש הקשר</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="two">שלח את הקבצים המצורפים</item>
+      <item quantity="many">שלח את הקבצים המצורפים</item>
+      <item quantity="other">שלח את הקבצים המצורפים</item>
+      <item quantity="one">שלח את הקובץ המצורף</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="two">יש <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> קבצים מצורפים המוכנים לשליחה</item>
+      <item quantity="many">יש <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> קבצים מצורפים המוכנים לשליחה</item>
+      <item quantity="other">יש <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> קבצים מצורפים המוכנים לשליחה</item>
+      <item quantity="one">יש קובץ מצורף אחד המוכן לשליחה</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"שלח משוב"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"‏הצג בחנות Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"פרטי גרסה"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"‏גרסה %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"רישיונות קוד פתוח"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"הודעות"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"צירפת את מספר הקבצים המקסימלי"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"טעינת הקובץ המצורף נכשלה."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"האם להוסיף לאנשי הקשר?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"הוסף איש קשר"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"נושא"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"נושא: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"טוען את כרטיס איש הקשר"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"לא ניתן לטעון כרטיס איש קשר"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"הצג את כרטיס איש הקשר"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> אנשי קשר</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> אנשי קשר</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> אנשי קשר</item>
+      <item quantity="one">איש קשר <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"כרטיסי אנשי קשר"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"יום הולדת"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"הערות"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"העבר הודעה"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"השב"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"‏SMS מושבת"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"‏כדי לשלוח, הגדר את האפליקציה \'העברת הודעות\' כאפליקציית ברירת המחדל ל-SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"‏הגדר את האפליקציה \'העברת הודעות\' כאפליקציית ברירת המחדל ל-SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"שנה"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"‏כדי לקבל הודעות, הגדר את \'העברת הודעות\' כאפליקציית ברירת המחדל ל-SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"‏לא נבחר SIM מועדף עבור שליחה של הודעות SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"אפליקציה זו אינה מורשית על ידי בעל המכשיר."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"אישור"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"משתתפים רבים מדי בשיחה"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="two">אנשי קשר לא חוקיים</item>
+      <item quantity="many">אנשי קשר לא חוקיים</item>
+      <item quantity="other">אנשי קשר לא חוקיים</item>
+      <item quantity="one">איש קשר לא חוקי</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"לא ניתן לטעון תמונת מצלמה"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"אתה: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"טיוטה"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"כשתתחיל שיחה חדשה, תראה אותה ברשימה כאן"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"שיחות שהועברו לארכיון מופיעות כאן"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"טוען שיחות..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"תמונה"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"קטע אודיו"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"סרטון"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"כרטיס איש קשר"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"בטל"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"נסה שוב"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"הזן שם איש קשר או מספר טלפון כדי להתחיל הודעה חדשה"</string>
+    <string name="action_block" msgid="9032076625645190136">"חסום"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"חסום את <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"בטל חסימה של <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"לחסום את <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"תמשיך לקבל הודעות ממספר זה אך לא יוצגו לך עוד דיווחים. שיחה זו תועבר לארכיון."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"אנשי קשר חסומים"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"אפשר"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"אנשי קשר חסומים"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"בחר תמונה מספריית המסמכים"</string>
+    <string name="sending_message" msgid="6363584950085384929">"שולח את ההודעה"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"ההודעה נשלחה"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"נתונים סלולריים כבויים. בדוק את ההגדרות."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"לא ניתן לשלוח הודעות במצב טיסה"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"לא ניתן היה לשלוח את ההודעה"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"הורדת ההודעה בוצעה"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"נתונים סלולריים כבויים. בדוק את ההגדרות."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"לא ניתן להוריד הודעות במצב טיסה"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"לא ניתן היה להוריד את ההודעה"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"אפס"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"אחת"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"שתיים"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"שלוש"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"ארבע"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"חמש"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"שש"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"שבע"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"שמונה"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"תשע"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"לא ניתן לשלוח הודעה דרך <xliff:g id="CARRIERNAME">%1$s</xliff:g>, שגיאה <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"לא ניתן לשלוח הודעה דרך ספק לא ידוע, שגיאה <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"העבר: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"ההודעה לא נשלחה: השירות לא הופעל ברשת."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"ההודעה לא נשלחה: כתובת היעד לא חוקית"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"ההודעה לא נשלחה: הודעה לא חוקית"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"ההודעה לא נשלחה: תוכן לא נתמך"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"ההודעה לא נשלחה: הודעה לא נתמכת"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"ההודעה לא נשלחה מפני שהיא גדולה מדי"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"הודעה חדשה"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"הצג"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"תמונה"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"לא נמצא יישום מתאים"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"הסר נמען"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"הודעה חדשה"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"בטל"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ערוך נקודת גישה"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"לא מוגדרת"</string>
+    <string name="apn_name" msgid="1572691851070894985">"שם"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"‏שרת Proxy של MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"‏יציאת MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"‏סוג APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"‏מחק APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"‏APN חדש"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"שמור"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"מחק"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"השדה \'שם\' לא יכול להיות ריק."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"‏ה-APN לא יכול להיות ריק."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"‏שדה MCC חייב להכיל 3 ספרות."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"‏שדה MNC חייב להכיל 2 או 3 ספרות."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"‏משחזר את הגדרות ברירת המחדל של APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"אפס לברירת מחדל"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"‏איפוס ההגדרות עבור ברירת המחדל של APN הושלם."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ללא שם"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"שמות של נקודות גישה"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"‏APN חדש"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"‏הגדרות עבור שם נקודת גישה (APN) אינן זמינות עבור המשתמש הזה"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"האם להעתיק אל לוח העריכה?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"העתק"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"אל <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"כללי"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"מתקדם"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"הגדרות כלליות"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"הגדרות מתקדמות"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"‏שלח הודעות SMS אישיות לכל הנמענים. רק אתה תקבל תשובות"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"‏שלח הודעת MMS אחת לכל הנמענים"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"מספר לא ידוע"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"הודעה חדשה"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"הודעה חדשה."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"‏בורר כרטיסי SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"‏<xliff:g id="SIM_0">%1$s</xliff:g> נבחר, בוחר כרטיסי SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ערוך נושא"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"‏בחר כרטיס SIM או ערוך את הנושא"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"גע נגיעה ממושכת כדי להקליט אודיו"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"התחל שיחה חדשה"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"\'העברת הודעות\'"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"רשימת \'העברת הודעות\'"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"\'העברת הודעות\'"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"הודעה חדשה"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"רשימת שיחות"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"טוען שיחות"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"טוען הודעות"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"הצג שיחות נוספות"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"הצג עוד הודעות"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"השיחה נמחקה"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"השיחה נמחקה. גע כדי להציג שיחה אחרת ב\'העברת הודעות\'"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"חסום"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"חסימה בוטלה"</string>
+    <string name="db_full" msgid="8459265782521418031">"אין מספיק שטח אחסון. ייתכן שתאבד חלק מהנתונים."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"בחר קבצים מצורפים"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"אשר את הבחירה"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"בחרת <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"הסר קובץ מצורף אחד או יותר ונסה שוב."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"תוכל לנסות לשלוח את ההודעה, אך ייתכן שהיא לא תימסר אלא אם תסיר קובץ מצורף אחד או יותר."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ניתן לשלוח רק סרטון אחד בכל הודעה. הסר סרטונים נוספים ונסה שוב."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"טעינת הקובץ המצורף נכשלה ב\'העברת הודעות\'."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"שלח בכל זאת"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"לא ניתן היה להתחיל את השיחה"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> נבחר"</string>
+</resources>
diff --git a/res/values-ja/arrays.xml b/res/values-ja/arrays.xml
new file mode 100644
index 0000000..cf9e1a6
--- /dev/null
+++ b/res/values-ja/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"件名なし"</item>
+    <item msgid="272485471009191934">"件名なし"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"はい"</item>
+    <item msgid="6049132459802288033">"いいえ"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"笑"</item>
+    <item msgid="2611328818571146775">"ありがとう"</item>
+    <item msgid="4881335087096496747">"賛成"</item>
+    <item msgid="2422296858597420738">"ナイス"</item>
+    <item msgid="4805581752819452687">"すぐに連絡します"</item>
+    <item msgid="4746700499431366214">"後で連絡します"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 0000000..a3a513e
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"メッセージ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"メッセージ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"会話の選択"</string>
+    <string name="action_settings" msgid="1329008122345201684">"設定"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"メッセージを送信"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"添付ファイルを追加"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"ヘルプ"</string>
+    <string name="welcome" msgid="2857560951820802321">"ようこそ"</string>
+    <string name="skip" msgid="7238879696319945853">"スキップ"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"次へ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"次へ"</string>
+    <string name="exit" msgid="1905187380359981199">"終了"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"設定 &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"設定"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"SMSには、SMS、電話、連絡先に対する許可が必要です。"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"許可の変更は、[設定]&gt;[アプリ]&gt;[SMS]&gt;[許可]で行えます。"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"許可の変更は、[設定]、[アプリ]、[SMS]、[許可]で行えます。"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"よく使う連絡先"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"すべての連絡先"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g>に送信"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"写真や動画を撮影"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"この端末から画像を選択"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"音声の録音"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"写真を選択"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"メディアを選択しました。"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"メディアの選択を解除しました。"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g>件選択済み"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"画像<xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"画像"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"音声の録音"</string>
+    <string name="action_share" msgid="2143483844803153871">"共有"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"たった今"</string>
+    <string name="posted_now" msgid="867560789350406701">"今"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>分</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>分</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>時間</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>時間</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>日</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>日</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>週間</item>
+      <item quantity="one">1週間</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>か月</item>
+      <item quantity="one">1か月</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>年</item>
+      <item quantity="one">1年</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"クラス0メッセージ"</string>
+    <string name="save" msgid="5081141452059463572">"保存"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"端末の空き容量が少なくなっています。SMSでは空き容量を確保するため古いメッセージが自動的に削除されます。"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"空き容量が少なくなっています"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"端末上の空き容量が増えるまで、SMSでメッセージの送受信ができない場合があります。"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMSの空き容量が少なくなっています。メッセージの削除が必要な場合があります。"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"電話番号の確認"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"この1回の手順で、SMSはグループにメッセージを確実に配信します。"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"電話番号"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"メディア付きのメッセージをすべて削除"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g>より前のメッセージを削除"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g>より前のメッセージを自動削除"</string>
+    <string name="ignore" msgid="7063392681130898793">"無視"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"メディア付きのメッセージをすべて削除しますか?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g>より前のメッセージを削除しますか?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g>より前のメッセージを削除し、自動削除をONにしますか?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>さんからのメッセージ"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"メッセージ内容"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g>さんからのメッセージ"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"メッセージを送信しました"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"送信しています…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"送信されていません。タップしてもう一度お試しください。"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"送信されていません。もう一度送信しています…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"再送信または削除"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"緊急通報には音声通話を使用してください。テキストメッセージを配信できませんでした。"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"失敗しました"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ダウンロードする新しいMMSメッセージ"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"新しいMMSメッセージ"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ダウンロードできませんでした"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"再試行するにはタップしてください"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ダウンロードするにはタップしてください"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ダウンロードまたは削除"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ダウンロードしています…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"メッセージが期限切れか参照できなくなっています"</string>
+    <string name="mms_info" msgid="3402311750134118165">"サイズ: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>、期限: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"送信できません。受信者が無効です。"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"サービスがネットワークで有効になっていません"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ネットワークに問題があるため送信できませんでした"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"メッセージが期限切れか参照できなくなっています"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(無題)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"送信者不明"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"配信済み"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"件名「<xliff:g id="SUBJECT">%1$s</xliff:g>」、送信者「<xliff:g id="FROM">%2$s</xliff:g>」のメッセージをダウンロードできませんでした。"</string>
+    <string name="low_memory" msgid="5300743415198486619">"メモリ不足のためデータベース操作を完了できませんでした"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"メッセージが送信されていません"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"SMSの一部のメッセージが送信されていません"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>件のスレッドのメッセージ<xliff:g id="MESSAGES_1">%d</xliff:g>件</item>
+      <item quantity="one">1件のスレッドのメッセージ<xliff:g id="MESSAGES_0">%d</xliff:g>件</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"メッセージがダウンロードされていません"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"SMSの一部のメッセージがダウンロードされていません"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>件のスレッドのメッセージ<xliff:g id="MESSAGES_1">%d</xliff:g>件</item>
+      <item quantity="one">1件のスレッドのメッセージ<xliff:g id="MESSAGES_0">%d</xliff:g>件</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g>へのメッセージは送信されませんでした"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"緊急通報には音声通話を使用してください。<xliff:g id="NUMBER">%1$s</xliff:g>へのテキストメッセージを配信できませんでした。"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g>件の新しいメッセージ</item>
+      <item quantity="one">新しいメッセージ</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"開始"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"カメラは利用できません"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"カメラは利用できません"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"動画撮影は利用できません"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"メディアを保存できません"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"写真を撮ることはできません"</string>
+    <string name="back" msgid="1477626055115561645">"戻る"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"アーカイブ済み"</string>
+    <string name="action_delete" msgid="4076795795307486019">"削除"</string>
+    <string name="action_archive" msgid="5437034800324083170">"アーカイブ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"アーカイブ解除"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"通知を無効化"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"通知を有効化"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"連絡先を追加"</string>
+    <string name="action_download" msgid="7786338136368564146">"ダウンロード"</string>
+    <string name="action_send" msgid="377635240181672039">"送信"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"削除"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"このメッセージを削除しますか?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"この操作は元に戻せません。"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"削除"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">これらのスレッドを削除しますか?</item>
+      <item quantity="one">このスレッドを削除しますか?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"削除"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"キャンセル"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"宛先"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"複数の画像を選択"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"選択の確認"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"音声を録音できません。もう一度お試しください。"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"音声を再生できません。もう一度お試しください。"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"音声を保存できませんでした。もう一度お試しください。"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"長押し"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"、 "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"写真"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"音声クリップ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"動画"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"連絡先カード"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ダウンロード"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMSで返信"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMSで返信"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"返信"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other">参加者<xliff:g id="COUNT_1">%d</xliff:g>人</item>
+      <item quantity="one">参加者<xliff:g id="COUNT_0">%d</xliff:g>人</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"自分"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"連絡先がブロックされ、アーカイブされました"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"連絡先をブロック解除し、アーカイブを解除しました"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g>件をアーカイブしました"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g>件のアーカイブを解除しました"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"通知をオフにしました"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"通知をオンにしました"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"すべて設定されました。もう一度[送信]をタップしてください。"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"SMSを既定のSMSアプリとして設定しました。"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">添付ファイルを破棄</item>
+      <item quantity="one">添付ファイルを破棄</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"音声添付ファイル"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"音声添付ファイルの再生"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"一時停止"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g>さんからのメッセージは「<xliff:g id="MESSAGE">%2$s</xliff:g>」です。"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>からのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を受信できませんでした(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>からのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を受信しました(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」が送信されていません(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信しています(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信できませんでした(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信しました(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>からのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を受信できませんでした(時間: <xliff:g id="TIME">%3$s</xliff:g>、<xliff:g id="GROUPINFO">%4$s</xliff:g>)。"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>からのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を受信しました(時間: <xliff:g id="TIME">%3$s</xliff:g>、<xliff:g id="GROUPINFO">%4$s</xliff:g>)。"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」が送信されていません(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信しています(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信できませんでした(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>へのメッセージ「<xliff:g id="MESSAGE">%2$s</xliff:g>」を送信しました(時間: <xliff:g id="TIME">%3$s</xliff:g>)。"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"失敗したメッセージ。再試行するにはタップしてください。"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g>とのスレッド"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"件名を削除"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"動画を撮影"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"静止画を撮影"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"画像を撮影"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"動画の録画を開始"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"全画面カメラに切り替える"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"前面カメラと背面カメラを切り替える"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"録画を停止し、動画を添付する"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"動画の録画を停止"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"SMSの写真"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>枚の写真を「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」アルバムに保存しました</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>枚の写真を「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」アルバムに保存しました</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>本の動画を「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」アルバムに保存しました</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>本の動画を「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」アルバムに保存しました</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g>個の添付ファイルを「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」アルバムに保存しました</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>個の添付ファイルを「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」アルバムに保存しました</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>個の添付ファイルを「ダウンロード」に保存しました</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>個の添付ファイルを「ダウンロード」に保存しました</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>個の添付ファイルを保存しました</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>個の添付ファイルを保存しました</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>個の添付ファイルを保存できませんでした</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g>個の添付ファイルを保存できませんでした</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS添付ファイルを保存しました"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"設定"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"アーカイブ済み"</string>
+    <string name="action_close" msgid="1840519376200478419">"閉じる"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"詳細設定"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"デバッグ"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"通知"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"通知音"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"マナーモード"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"バイブレーション"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ブロック済み"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS受取確認通知"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"送信するSMSの配信レポートを毎回リクエストする"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"自動取得"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMSメッセージを自動的に取得する"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ローミング時に自動取得"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ローミング時にMMSを自動取得"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"グループメッセージング"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"宛先が複数ある場合にMMSを使用して1通のメッセージとして送信する"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"既定のSMSアプリ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"既定のSMSアプリ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"電話番号"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"不明"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"メッセージ送信音"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMSのダンプ"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"受信したSMS生データを外部ストレージファイルにダンプする"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMSのダンプ"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"受信したMMS生データを外部ストレージファイルにダンプする"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"無線警報"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"メッセージオプション"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"テキストをコピー"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"詳細を表示"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"削除"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"転送"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"メッセージの詳細"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"形式: "</string>
+    <string name="text_message" msgid="7415419755252205721">"テキストメッセージ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"マルチメディアメッセージ"</string>
+    <string name="from_label" msgid="1947831848146564875">"From: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"To: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"送信: "</string>
+    <string name="received_label" msgid="4442494712757995203">"受信: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"件名: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"サイズ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"優先度: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"高"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"標準"</string>
+    <string name="priority_low" msgid="7398724779026801851">"低"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"差出人アドレスは非表示"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"添付ファイルの読み込み中はメッセージを送信できません。"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"添付ファイルを読み込めません。もう一度お試しください。"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ネットワークの準備ができていません。もう一度お試しください。"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"テキストを削除"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"文字と数字の入力を切り替える"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"参加者を追加"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"参加者を確認"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"新しいスレッドを開始"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"この項目を選択する"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"動画を再生"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ユーザーとオプション"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"デバッグ"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ユーザーとオプション"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"全般"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"このスレッドのユーザー"</string>
+    <string name="action_call" msgid="6596167921517350362">"発信"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"メッセージの送信"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>から&lt;/small&gt;&amp;lt:br/&gt;メッセージを送信"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">写真を送信します</item>
+      <item quantity="one">写真を送信します</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">音声を送信します</item>
+      <item quantity="one">音声を送信します</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">動画を送信します</item>
+      <item quantity="one">動画を送信します</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">連絡先カードを送信します</item>
+      <item quantity="one">連絡先カードを送信します</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">添付ファイルを送信します</item>
+      <item quantity="one">添付ファイルを送信します</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>個の添付ファイルを送信する準備ができました</item>
+      <item quantity="one">1個の添付ファイルを送信する準備ができました</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"フィードバックを送信"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Playストアで表示"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"バージョン情報"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"バージョン%1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"オープンソースライセンス"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"通知"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"添付ファイルの上限に達しました"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"添付ファイルを読み込めませんでした。"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"連絡先に追加しますか?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"連絡先を追加"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"件名"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"件名: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"連絡先カードを読み込んでいます"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"連絡先カードを読み込めませんでした"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"連絡先カードを表示"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>件の連絡先</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>件の連絡先</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"連絡先カード"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"誕生日"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"メモ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"メールを転送"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"返信"</string>
+    <string name="plus_one" msgid="9010288417554932581">"、他1人"</string>
+    <string name="plus_n" msgid="8961547034116059566">"、他%d人"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMSは無効になっています"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"送信するには、SMSを既定のSMSアプリとして設定してください"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"SMSを既定のSMSアプリとして設定してください"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"変更"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"メッセージを受信するには、SMSを既定のSMSアプリとして設定してください"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMSメッセージ送信用の優先SIMが選択されていません"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"このアプリは端末の所有者によって許可されていません。"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"スレッドへの参加者が多すぎます"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">連絡先が無効です</item>
+      <item quantity="one">連絡先が無効です</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"カメラ画像を読み込めませんでした"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"あなた: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"下書き"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"新しいスレッドを開始すると、ここにリストが表示されます"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"アーカイブされたスレットがここに表示されます"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"スレッドを読み込んでいます…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"画像"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"音声クリップ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"動画"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"連絡先カード"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"元に戻す"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"再試行"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"新しいメッセージを開始するには連絡先の名前か電話番号を入力してください"</string>
+    <string name="action_block" msgid="9032076625645190136">"ブロック"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>さんをブロック"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g>さんのブロックを解除"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>をブロックしますか?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"この番号からのメッセージは引き続き受信しますが、通知は表示されなくなります。このスレッドはアーカイブされます。"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"ブロック中の連絡先"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ブロックを解除"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"ブロック中の連絡先"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ドキュメントライブラリから画像を選択"</string>
+    <string name="sending_message" msgid="6363584950085384929">"メールを送信しています"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"メッセージを送信しました"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"モバイルデータがOFFになっています。設定を確認してください。"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"機内モードではメッセージを送信できません"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"メッセージを送信できませんでした"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"メッセージをダウンロードしました"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"モバイルデータがOFFになっています。設定を確認してください。"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"機内モードではメッセージをダウンロードできません"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"メッセージをダウンロードできませんでした"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"0"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"1"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"2"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"3"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"4"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"5"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"6"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"7"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"8"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"9"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"メッセージを送信できません(<xliff:g id="CARRIERNAME">%1$s</xliff:g>)、エラー<xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"メッセージを送信できません(不明な携帯通信会社)、エラー<xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"メッセージの送信失敗: サービスがネットワークで有効になっていません"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"メッセージの送信失敗: 無効な宛先アドレスです"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"メッセージの送信失敗: 無効なメッセージです"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"メッセージの送信失敗: サポートされていないコンテンツです"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"メッセージの送信失敗: サポートされていないメッセージです"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"メッセージの送信失敗: 大きすぎます"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"新しいメッセージ"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"表示"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"画像"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"適切なアプリが見つかりませんでした"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"宛先を削除"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"新しいメッセージ"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"キャンセル"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"アクセスポイントの編集"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"未設定"</string>
+    <string name="apn_name" msgid="1572691851070894985">"名前"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMSプロキシ"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMSポート"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APNタイプ"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APNを削除"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"新しいAPN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"保存"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"破棄"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"[名前]欄は必須です。"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APNは必須です。"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC欄は3桁で指定してください。"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC欄は2桁か3桁で指定してください。"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"デフォルトのAPN設定を復元しています。"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"デフォルトにリセット"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"デフォルトのAPN設定にリセットしました。"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"無題"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"アクセスポイント名"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"新しいAPN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"このユーザーはアクセスポイント名設定を利用できません"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"クリップボードにコピーしますか?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"コピー"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"宛先: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"全般"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"詳細設定"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"全般設定"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"詳細設定"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"「<xliff:g id="SIM_NAME">%s</xliff:g>」SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"SMSメッセージを全員に個別に送信し、返信があなただけに返されるようにします"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"1つのMMSを全員に送信します"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"不明な番号"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"新しいメッセージ"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"新しいメッセージがあります。"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIMの切り替え"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"SIMの切り替え(<xliff:g id="SIM_0">%1$s</xliff:g>を選択済み)"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"件名を編集"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIMを選択するか件名を編集します"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"録音するには押し続けます"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"新しいスレッドを開始"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"SMSリスト"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"新しいメッセージ"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"スレッドリスト"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"スレッドを読み込んでいます"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"メールを読み込んでいます"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"他のスレッドを見る"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"他のメールを見る"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"スレッドを削除しました"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"スレッドを削除しました。タップしてSMSの別のスレッドを表示します"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ブロックしました"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"ブロックを解除しました"</string>
+    <string name="db_full" msgid="8459265782521418031">"空き容量が少なくなっています。一部のデータが失われる可能性があります。"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"添付ファイルの選択"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"選択の確認"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g>件選択済み"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"添付ファイルを1つ以上削除してから、もう一度お試しください。"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"メッセージの送信を試すことはできますが、添付ファイルを1つ以上削除しないと配信されない可能性があります。"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"送信できる動画は1件のメッセージにつき1本までです。追加した動画を削除してもう一度お試しください。"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"SMSで添付ファイルを読み込めませんでした。"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"このまま送信"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"スレッドを開始できませんでした"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g>(<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g>が選択されています"</string>
+</resources>
diff --git a/res/values-ka/arrays.xml b/res/values-ka/arrays.xml
new file mode 100644
index 0000000..0f50610
--- /dev/null
+++ b/res/values-ka/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"უსათაურო"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"კი"</item>
+    <item msgid="6049132459802288033">"არა"</item>
+    <item msgid="3084376867445867895">"კარგი"</item>
+    <item msgid="3155097332660174689">"ჰე-ჰე"</item>
+    <item msgid="2611328818571146775">"დიდი მადლობა"</item>
+    <item msgid="4881335087096496747">"თანახმა ვარ"</item>
+    <item msgid="2422296858597420738">"მშვენიერია"</item>
+    <item msgid="4805581752819452687">"მოვდივარ"</item>
+    <item msgid="4746700499431366214">"კარგი, მოგვიანებით შეგეხმიანები"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
new file mode 100644
index 0000000..8a2cd5e
--- /dev/null
+++ b/res/values-ka/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"შეტყობინებები"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"შეტყობინებები"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"მიმოწერის არჩევა"</string>
+    <string name="action_settings" msgid="1329008122345201684">"პარამეტრები"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"წერილის გაგზავნა"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"დანართის დამატება"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"დახმარება"</string>
+    <string name="welcome" msgid="2857560951820802321">"მოგესალმებით"</string>
+    <string name="skip" msgid="7238879696319945853">"გამოტოვება"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"შემდეგი &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"შემდეგი"</string>
+    <string name="exit" msgid="1905187380359981199">"გასვლა"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"პარამეტრები &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"პარამეტრები"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"შეტყობინებები საჭიროებს ნებართვას SMS-ზე, ტელეფონზე და კონტაქტებზე."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ნებართვების შეცვლა შეგიძლიათ აქ: პარამეტრები &gt; აპები &gt; შეტყობინებები &gt; ნებართვები."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ნებართვების შეცვლა შეგიძლიათ აქ: პარამეტრები, აპები, შეტყობინებები, ნებართვები."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ხშირად გამოყენებული კონტაქტები"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ყველა კონტაქტი"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g>-ზე გაგზავნა"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"სურათების ან ვიდეოს გადაღება"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ამ მოწყობილობიდან სურათების არჩევა"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"აუდიოს ჩაწერა"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ფოტოს არჩევა"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"მედია შერჩეულია."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"მედია არ არის შერჩეული."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> შერჩეულია"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"სურათის <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"სურათი"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"აუდიოს ჩაწერა"</string>
+    <string name="action_share" msgid="2143483844803153871">"გაზიარება"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ახლახანს"</string>
+    <string name="posted_now" msgid="867560789350406701">"ახლა"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> წთ.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> წთ.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> საათის</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> საათის</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> დღის</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> დღის</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> კვირის</item>
+      <item quantity="one">კვირის</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> თვის</item>
+      <item quantity="one">თვის</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> წლის</item>
+      <item quantity="one">წლის</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 შეტყობინება"</string>
+    <string name="save" msgid="5081141452059463572">"შენახვა"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"მოწყობილობის მეხსიერებაში თავისუფალი სივრცე ცოტაა. შეტყობინებები ავტომატურად წაშლის ძველ შეტყობინებებს მეხსიერების გასათავისუფლებლად."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"თავისუფალი ადგილი იწურება"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"შეტყობინებებმა შესაძლოა ვერ მოახერხოს შეტყობინებების გაგზავნა ან მიღება მანამ, სანამ თქვენს მოწყობილობაზე ხელმისაწვდომი არ გახდება მეტი სივრცე."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS სივრცე იწურება. შესაძლოა, მოგიწიოთ ძველი შეტყობინებების წაშლა"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"დაადასტურეთ თქვენი ტელეფონის ნომერი"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ეს ერთჯერადი ნაბიჯი უზრუნველყოფს, რომ შეტყობინებებმა სწორად მოგაწოდოთ ჯგუფური შეტყობინებები."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ტელეფონის ნომერი"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ყველა შეტყობინების წაშლა, რომელსაც მედია აქვს"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g>-ზე ძველი შეტყობინებების წაშლა"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g>-ზე ძველი შეტყობინებების ავტომატური წაშლა"</string>
+    <string name="ignore" msgid="7063392681130898793">"იგნორირება"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"წაიშალოს ყველა შეტყობინება, რომელსაც მედია აქვს?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"წაიშალოს <xliff:g id="DURATION">%s</xliff:g>-ზე ძველი შეტყობინებები?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"გსურთ <xliff:g id="DURATION">%s</xliff:g>-ზე უფრო ძველი შეტყობინებების წაშლა და ავტომატური წაშლის ჩართვა?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> თქვა"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"თქვენ სთქვით,"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"შეტყობინება <xliff:g id="SENDER">%s</xliff:g> -საგან"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"თქვენ გააგზავნეთ შეტყობინება"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"იგზავნება..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"არ გაიგზავნა. შეეხეთ ისევ საცდელად."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"არ გაიგზავნა. მიმდინარეობს ხელახლა ცდა…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ხელახლა გაგზავნა ან წაშლა"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"გამოიძახეთ საგანგებო სამსახურები ხმოვანი ზარით. ტექსტური შეტყობინების გაგზავნა ამჟამად შეუძლებელია."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ვერ განხორციელდა"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ახალი ჩამოსატვირთი MMS შეტყობინება"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"ახალი MMS შეტ"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ჩამოტვირთვა ვერ მოხერხდა"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ხელახლა საცდელად შეეხეთ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"შეეხეთ ჩამოსატვირთად"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ჩამოტვირთვა ან წაშლა"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"მიმდინარეობს ჩამოტვირთვა…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"შეტყობინებას ვადა გაუვიდა ან მიუწვდომელია."</string>
+    <string name="mms_info" msgid="3402311750134118165">"ზომა: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, ვადა: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"გაგზავნა ვერ ხერხდება. მიმღები არასწორია."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"სერვისი არ გააქტიურებულა ქსელში"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ქსელის პრობლემის გამო ვერ გაიგზავნა"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"შეტყობინებას ვადა გაუვიდა ან მიუწვდომელია."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(თემის გარეშე)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"უცნობი გამგზავნი"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"მიწოდებულია"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="SUBJECT">%1$s</xliff:g> შეტყობინების ჩამოტვირთვა ვერ მოხერხდა <xliff:g id="FROM">%2$s</xliff:g>-დან."</string>
+    <string name="low_memory" msgid="5300743415198486619">"მცირე მეხსიერების გამო მონაცემთა ბაზასთან დაკავშირებული ოპერაციის დასრულება ვერ მოხერხდა"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"შეტყობინება ვერ გაიგზავნა"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"შეტყობინებებში ზოგიერთი შეტყობინება ვერ გაიგზავნა"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> შეტყობინება <xliff:g id="CONVERSATIONS">%d</xliff:g> მიმოწერაში</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> შეტყობინება ერთ მიმოწერაში</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"შეტყობინება არ ჩამოტვირთულა"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"შეტყობინებებში ზოგიერთი შეტყობინება ვერ ჩამოიტვირთა"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> შეტყობინება <xliff:g id="CONVERSATIONS">%d</xliff:g> მიმოწერაში</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> შეტყობინება ერთ მიმოწერაში</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"შეტყობინება ნომერზე <xliff:g id="NUMBER">%1$s</xliff:g> ვერ გაიგზავნა"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"გამოიძახეთ საგანგებო სამსახურები ხმოვანი ზარით. ტექსტური შეტყობინების გაგზავნა ნომერზე <xliff:g id="NUMBER">%1$s</xliff:g> ამჟამად შეუძლებელია."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ახალი შეტყობინება</item>
+      <item quantity="one">ახალი შეტყობინება</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"დაწყება"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"კამერა მიუწვდომელია"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"კამერა მიუწვდომელია"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ვიდეო ჩაწერა მიუწვდომელია"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"მედიას შენახვა ვერ ვერხდება"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ვერ ხორციელდება სურათის გადაღება"</string>
+    <string name="back" msgid="1477626055115561645">"უკან"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"დაარქივებული"</string>
+    <string name="action_delete" msgid="4076795795307486019">"წაშლა"</string>
+    <string name="action_archive" msgid="5437034800324083170">"დაარქივება"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"დეარქივაცია"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"შეტყობინებების გამორთვა"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"შეტყობინებების ჩართვა"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"კონტაქტის დამატება"</string>
+    <string name="action_download" msgid="7786338136368564146">"ჩამოტვირთვა"</string>
+    <string name="action_send" msgid="377635240181672039">"გაგზავნა"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"წაშლა"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"წავშალო ეს შეტყობინება?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ამ ქმედებას ვერ გააუქმებთ."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"წაშლა"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">წაიშალოს ეს მიმოწერები?</item>
+      <item quantity="one">წაიშალოს ეს მიმოწერა?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"წაშლა"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"გაუქმება"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"მიმღები:"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"მრავალი სურათის არჩევა"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"არჩევანის დადასტურება"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ხმის ჩაწერა ვერ ხერხდენა. სცადეთ ისევ."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ხმის დაკვრა ვერ ხერხდება. სცადეთ ისევ."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ხმის ჩაწერა ვერ მოხერხდა. სცადეთ ისევ."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"შეეხეთ &amp; დააყოვნეთ"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"სურათი"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"აუდიო კლიპი"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ვიდეო"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"კონტაქტის ბარათი"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ჩამოტვირთვა"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS-ით პასუხი"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS-ით პასუხი"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"პასუხი"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> მონაწილე</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> მონაწილე</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"მე"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"კონტაქტი დაბლოკილია &amp; დაარქივებულია"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"კონტაქტი განბლოკილია &amp; amp; დაუარქივებელი"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> დაარქივებული"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> დაუარქივებელი"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"შეტყობინებები გამორთულია"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"შეტყობინებები ჩართულია"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"მზად არის. შეეხეთ ხელახლა გაგზავნას."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"შეტყობინებები წარმატებით დაყენებულია ნაგულისხმევ SMS აპად."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">დანართების გაუქმება</item>
+      <item quantity="one">დანართის გაუქმება</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"აუდიო დანართი"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"აუდიო დანართის ჩართვა"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"პაუზა"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"შეტყობინება <xliff:g id="SENDER">%1$s</xliff:g>-საგან: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>-საგან შეტყობინების შეცდომა: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"შეტყობინება <xliff:g id="SENDER">%1$s</xliff:g>-საგან: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>-სთვის გაუგზავნელი შეტყობინება: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"იგზავნება შეტყობინება <xliff:g id="CONTACT">%1$s</xliff:g>-სთვის: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>-სთვის შეტყობინების შეცდომა: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"შეტყობინება <xliff:g id="CONTACT">%1$s</xliff:g>-სთვის: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>-საგან შეტყობინების შეცდომა: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"შეტყობინება <xliff:g id="SENDER">%1$s</xliff:g>-საგან: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"გაუგზავნელი შეტყობინება <xliff:g id="GROUP">%1$s</xliff:g>-სთვის: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"იგზავნება შეტყობინება <xliff:g id="GROUP">%1$s</xliff:g>-სთვის: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>-სთვის შეტყობინების შეცდომა: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"შეტყობინება <xliff:g id="GROUP">%1$s</xliff:g>-სთვის: <xliff:g id="MESSAGE">%2$s</xliff:g>. დრო: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"შეტყობინების შეცდომა. შეეხეთ, რათა ხელახლა სცადოთ."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"საუბარი <xliff:g id="PARTICIPANTS">%s</xliff:g> -სთან"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"თემის წაშლა"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ვიდეოს გადაღება"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ფოტოსურათის აღბეჭდვა"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"სურათის გადაღება"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ვიდეოს ჩაწერის დაწყება"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"სრულეკრანიან კამერაზე გადართვა"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"წინა და უკანა კამერებს შორის გადართვა"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"ჩაწერის შეჩერება და ვიდეოს მიბმა"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ვიდეოს ჩაწერის შეჩერება"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"შეტყობინებების ფოტოები"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ფოტო შენახულია ალბომში „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ფოტო შენახულია ალბომში „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ვიდეო შენახულია ალბომში „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ვიდეო შენახულია ალბომში „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> მიმაგრებული ფაილი შენახულია ალბომში „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> მიმაგრებული ფაილი შენახულია ალბომში „<xliff:g id="ALBUMNAME_1">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> მიმაგრებული ფაილი შენახულია „ჩამოტვირთვებში“</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> მიმაგრებული ფაილი შენახულია „ჩამოტვირთვებში“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">შენახულია <xliff:g id="QUANTITY_1">%d</xliff:g> დანართი</item>
+      <item quantity="one">შენახულია <xliff:g id="QUANTITY_0">%d</xliff:g> დანართი</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> დანართის შენახვა ვერ მოხერხდა</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> დანართის შენახვა ვერ მოხერხდა</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS დანართი შენახულია"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"პარამეტრები"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"დაარქივებული"</string>
+    <string name="action_close" msgid="1840519376200478419">"დახურვა"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"გაფართოებული"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"გამართვა"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"შეტყობინებები"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ხმა"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"დადუმებული"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ვიბრაცია"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"დაბლოკილი"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS მისვლის შეტყობინებები"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ყოველ გაგზავნილ SMS-ზე მიწოდების დადასტურების მოთხოვნა"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"ავტო-მოძიება"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS შეტყობინებების ავტომატურად ჩამოტვირთვა"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ავტო ჩამოტვირთვა როუმინგში"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"როუმინგის დროს MMS-ის ავტომატური ჩამოტვირთვა"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ჯგუფური შეტყობინება"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"მრავალი მიმღების შემთხვევაში ერთიანი შეტყობინების გასაგზავნად MMS-ის გამოყენება"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ნაგულისხმევი SMS აპლიკაცია"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ნაგულისხმევი SMS აპლიკაცია"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"თქვენი ტელეფონის ნომერი"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"უცნობი"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"გამავალი შეტყობინების ჟღერადობები"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS-ის ჩაწერა"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"მიღებული SMS-ის დაუმუშავებელი მონაცემების გარე საცავის ფაილში ჩაწერა"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS-ის ჩაწერა"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"მიღებული MMS-ის დაუმუშავებელი მონაცემების გარე საცავის ფაილში ჩაწერა"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"უსადენო გაფრთხილებები"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"შეტყობინების პარამეტრები"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ტექსტის კოპირება"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"დეტალების ნახვა"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"წაშლა"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"გადაგზავნა"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"შეტყობინების მონაცემები"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ტიპი: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ტექსტური შეტყობინება"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"მულტიმედია შეტყობინება"</string>
+    <string name="from_label" msgid="1947831848146564875">"გამგზავნი: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"მიმღები: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"გაიგზავნა: "</string>
+    <string name="received_label" msgid="4442494712757995203">"მიღებულია: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"თემა: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ზომა: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"პრიორიტეტი: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"მაღალი"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ჩვეულებრივი"</string>
+    <string name="priority_low" msgid="7398724779026801851">"დაბალი"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"გამგზავნის მისამართი დამალულია"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"დანართების ჩატვირთვისას შეტყობინება ვერ გაიგზავნება."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"დანართი ვერ იტვირთება. სცადეთ ისევ."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ქსელი მზად არ არის. ისევ სცადეთ."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"შემდეგის წაშლა"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ტექსტისა და რიცხვების შეყვანას შორის გადართვა"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"მეტი მონაწილის დამატება"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"მონაწილეების დადასტურება"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"ახალი მიმოწერის დაწყება"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ამ ერთეულის არჩევა"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ვიდეოს დაკვრა"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ხალხი &amp; ვარიანტები"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"გამართვა"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ხალხი &amp; ვარიანტები"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ზოგადი"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ამ საუბრის მონაწილეები"</string>
+    <string name="action_call" msgid="6596167921517350362">"დარეკვა"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"შეტყობინების გაგზავნა"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"შეტყობინების გაგზავნა&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>-დან&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ფოტოების გაგზავნა</item>
+      <item quantity="one">ფოტოს გაგზავნა</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">აუდიო ჩანაწერების გაგზავნა</item>
+      <item quantity="one">აუდიო ჩანაწერის გაგზავნა</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ვიდეოების გაგზავნა</item>
+      <item quantity="one">ვიდეოს გაგზავნა</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">კონტაქტის ბარათების გაგზავნა</item>
+      <item quantity="one">კონტაქტის ბარათის გაგზავნა</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">დანართების გაგზავნა</item>
+      <item quantity="one">დანართის გაგზავნა</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> დანართი მზად არის გასაგზავნად</item>
+      <item quantity="one">გასაგზავნად მზად არის ერთი დანართი</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"უკუკავშირის გაგზავნა"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store-ში ნახვა"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ვერსიის ინფორმაცია"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ვერსია %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ღია კოდის ლიცენზიები"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"შეტყობინებები"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"მიღწეულია დანართების ლიმიტი"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"დანართი ვერ ჩაიტვირთა."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"დაემატოს კონტაქტებში?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"კონტაქტის დამატება"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"თემა"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"თემა: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"იტვირთება კონტაქტის ბარათი"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"საკონტაქტო ბარათი ვერ იტვირთება"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"კონტაქტის ბარათის ნახვა"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> კონტაქტი</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> კონტაქტი</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"კონტაქტის ბარათები"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"დაბადების თარიღი"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ჩანიშვნები"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"შეტყობინების გადაგზავნა"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"პასუხი"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS გამორთულია"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"გასაგზავნად დააყენეთ შეტყობინებები ნაგულისხმევ SMS აპად"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"დააყენეთ შეტყობინებები ნაგულისხმევ SMS აპად"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"შეცვლა"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"შეტყობინებების მისაღებად დააყენეთ შეტყობინებები ნაგულისხმევ SMS აპად"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"მოკლე ტექსტური შეტყობინებების გაგზავნისათვის, არ არის არჩეული უპირატესი SIM ბარათი"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ეს აპი მოწყობილობის მფლობელის მიერ ნებადართული არ არის."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"კარგი"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"მიმოწერაში ძალიან ბევრი მონაწილეა"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">კონტაქტები არასწორია</item>
+      <item quantity="one">კონტაქტი არასწორია</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"კამერის სურათი ვერ ჩაიტვირთა"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"თქვენ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"მონახაზი"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"როდესაც საუბარს წამოიწყებთ, ისინი აქ გამოჩნდება"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"დაარქივებული მიმოწერები აქ გამოჩნდება"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"მიმოწერები იტვირთება…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"სურათი"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"აუდიო კლიპი"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ვიდეო"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"კონტაქტის ბარათი"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"დაბრუნება"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ხელახლა ცდა"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ახალი შეტყობინების დასაწყებად შეიყვანეთ საკონტაქტო სახელი ან ტელეფონის ნომერი"</string>
+    <string name="action_block" msgid="9032076625645190136">"დაბლოკვა"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>-ის დაბლოკვა"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g>-ის განბლოკვა"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>-ის დაბლოკვა?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ამ ნომრიდან შეტყობინებებს კვლავ მიიღებთ, თუმცა შეხსენებები აღარ გამოგეგზავნებათ. ეს მიმოწერა დაარქივდება."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"დაბლოკილი კონტაქტები"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"განბლოკვა"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"დაბლოკილი კონტაქტები"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"აირჩიეთ სურათი დოკუმენტების ბიბლიოთეკიდან"</string>
+    <string name="sending_message" msgid="6363584950085384929">"შეტყობინება იგზავნება"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"შეტყობინება გაიგზავნა"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"მობილური ინტერნეტი გამორთულია. გადაამოწმეთ პარამეტრები."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"თვითმფრინავის რეჟიმში შეტყობინებების გაგზავნა ვერ ხერხდება"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"შეტყობინება ვერ გაიგზავნა"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"შეტყობინება გადმოწერილია"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"მობილური ინტერნეტი გამორთულია. გადაამოწმეთ პარამეტრები."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"თვითმფრინავის რეჟიმში შეტყობინების ჩამოტვირთვა ვერ ხორციელდება"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"შეტყობინების ჩამოტვირთვა ვერ ხორციელდება"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"ნული"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ერთი"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"ორი"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"სამი"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"ოთხი"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ხუთი"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ექვსი"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"შვიდი"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"რვა"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ცხრა"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"შეტყობინება ვერ იგზავნება: <xliff:g id="CARRIERNAME">%1$s</xliff:g>-ის შეცდომა <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"შეტყობინება ვერ იგზავნება უცნობი ოპერატორით, შეცდომა <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"შეტყობინება ვერ გაიგზავნა: სერვისი ქსელში გააქტიურებელი არ არის"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"შეტყობინება ვერ გაიგზავნა: სამიზნე მისამართი არასწორია"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"შეტყობინება ვერ გაიგზავნა: შეტყობინება არასწორია"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"შეტყობინება ვერ გაიგზავნა: კონტენტი მხარდაჭერილი არ არის"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"შეტყობინება ვერ გაიგზავნა: შეტყობინება მხარდაჭერილი არ არის"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"შეტყობინება არ გაიგზავნა: ის ძალიან დიდია"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"ახალი შეტყობინება"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ნახვა"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"სურათი"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"შესაბამისი აპლიკაცია ვერ მოიძებნა"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"მიმღების ამოღება"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"ახალი შეტყობინება"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"გაუქმება"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"წვდომის წერტილის რედაქტირება"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"არ არის დაყენებული"</string>
+    <string name="apn_name" msgid="1572691851070894985">"სახელი"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS პროქსი-სერვერი"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS პორტი"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN ტიპი"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN-ის წაშლა"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"ახალი APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"შენახვა"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"გაუქმება"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"სახელის ველი არ შეიძლება იყოს ცარიელი."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN არ უნდა იყოს ცარიელი."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ველი უნდა შეიცავდეს 3 ციფრს."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ველი უნდა შეიცავდეს ორ ან სამ ციფრს."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ნაგულისხმევი APN პარამეტრების აღდგენა."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"საწყის პარამეტრებზე ჩამოყრა"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"ნაგულისხმევი APN პარამეტრების  აღდგენა დასრულებულია."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"უსათაურო"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"წვდომის წერტილის სახელები (APNs)"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-ები"</string>
+    <string name="menu_new" msgid="8286285392706532511">"ახალი APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"წვდომის წერტილის (APN) პარამეტრები ამ მომხმარებლისათვის მიუწვდომელია"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"გსურთ ბუფერში კოპირება?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"კოპირება"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g>-ზე"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ზოგადი"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"გაფართოებული"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"ძირითადი პარამეტრები"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"დამატებითი პარამეტრები"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"„<xliff:g id="SIM_NAME">%s</xliff:g>“ SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ყველა მიმღებთან ინდივიდუალური SMS შეტყობინების გაგზავნა. პასუხებს მხოლოდ თქვენ მიიღებთ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ყველა მიმღებთან ერთი MMS-ის გაგზავნა"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"უცნობი ნომერი"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"ახალი შეტყობინება"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"ახალი შეტყობინება."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM სელექტორი"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"არჩეულია <xliff:g id="SIM_0">%1$s</xliff:g>, SIM სელექტორი"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"თემის რედაქტირება"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"აირჩიეთ SIM ან შეცვალეთ სათაური"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"აუდიო ჩაწერისათვის შეეხეთ და დააყოვნეთ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"ახალი მიმოწერის დაწყება"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"შეტყობინებები"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"შეტყობინებების სია"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"შეტყობინებები"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"ახალი შეტყობინება"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"მიმოწერათა სია"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"მიმოწერები იტვირთება…"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"მიმდინარეობს შეტყობინებების ჩატვირთვა"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"მეტი მიმოწერის ნახვა"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"იხილეთ სხვა შეტყობინებები"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"მიმოწერა წაშლილია"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"მიმოწერა წაშლილია. შეეხეთ შეტყობინებების სხვა მიმოწერის საჩვენებლად"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"დაბლოკილი"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"განბლოკილი"</string>
+    <string name="db_full" msgid="8459265782521418031">"შენახვის სივრცეში შემცირებულია. ზოგიერთი მონაცემი შეიძლება დაიკარგოს."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"დანართის არჩევა"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"არჩევანის დადასტურება"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> შერჩეულია"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"წაშალეთ ერთი ან რამდენიმე დანართი და ხელახლა სცადეთ."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"შეგიძლიათ სცადოთ შეტყობინების გაგზავნა, მაგრამ შეიძლება მისი მიწოდება ვერ მოხერხდეს, თუ არ წაშლით ერთ ან რამდენიმე დანართს."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"შეტყობინებით თქვენ შეგიძლიათ გააგზავნოთ მხოლოდ ერთი ვიდეო. გთხოვთ ამოშალეთ დამატებითი ვიდეოები და სცადეთ კიდევ ერთხელ."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"შეტყობინებებში დანართის ჩატვირთვა ვერ მოხერხდა."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"მაინც გაგზავნა"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"საუბრის დაწყება ვერ მოხერხდა"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"შერჩეულია <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-kk/arrays.xml b/res/values-kk/arrays.xml
new file mode 100644
index 0000000..b49d0cc
--- /dev/null
+++ b/res/values-kk/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"тақырыпсыз"</item>
+    <item msgid="272485471009191934">"тақырып жоқ"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Иә"</item>
+    <item msgid="6049132459802288033">"Жоқ"</item>
+    <item msgid="3084376867445867895">"Жарайды"</item>
+    <item msgid="3155097332660174689">"Хехе"</item>
+    <item msgid="2611328818571146775">"Рақмет"</item>
+    <item msgid="4881335087096496747">"Келісемін"</item>
+    <item msgid="2422296858597420738">"Жақсы"</item>
+    <item msgid="4805581752819452687">"Жолдамын"</item>
+    <item msgid="4746700499431366214">"Жарайды, кейінірек хабарласамын"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
new file mode 100644
index 0000000..386e8ef
--- /dev/null
+++ b/res/values-kk/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Хабар алмасу"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Хабар алмасу"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Сөйлесуді таңдау"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Параметрлер"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Хабар жіберу"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Тіркеме қосу"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Анықтама"</string>
+    <string name="welcome" msgid="2857560951820802321">"Қош келдіңіз"</string>
+    <string name="skip" msgid="7238879696319945853">"Өткізіп жіберу"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Келесі &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Келесі"</string>
+    <string name="exit" msgid="1905187380359981199">"Шығу"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Параметрлер &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Параметрлер"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging қолданбасына SMS, \"Телефон\" және \"Контактілер\" қолданбаларына рұқсат қажет."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Рұқсаттарды \"Параметрлер\" &gt; \"Қолданбалар\" &gt; \"Messaging\" &gt; \"Рұқсаттар\" тармағында өзгертуге болады."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Рұқсаттарды \"Параметрлер\", \"Қолданбалар\", \"Messaging\", \"Рұқсаттар\" тармағында өзгерте аласыз."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Жиі қолданылатын"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Барлық контактілер"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> орнына жіберу"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Суреттер немесе бейне түсіру"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Осы құрылғыдан кескіндерді таңдау"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Аудио жазу"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Фотосуретті таңдау"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медиа таңдалды."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Медиадан таңдау алынды."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> таңдалды"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"кескін <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"кескін"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Аудио жазу"</string>
+    <string name="action_share" msgid="2143483844803153871">"Бөлісу"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Қазір ғана"</string>
+    <string name="posted_now" msgid="867560789350406701">"Қазір"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> мин.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> мин.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> сағат</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> сағат</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> күн</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> күн</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> апта</item>
+      <item quantity="one">апта</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ай</item>
+      <item quantity="one">ай</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> жыл</item>
+      <item quantity="one">жыл</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0 сыныпты хабар"</string>
+    <string name="save" msgid="5081141452059463572">"Сақтау"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Құрылғыдағы бос орын аз. \"Хабар алмасу\" орын босату үшін ескі хабарларды автоматты түрде жояды."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Жадта бос орын бітуде"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"\"Хабар алмасу\" қолданбасы құрылғыда көбірек бос орын қол жетімді болғанша хабарлар жібере немесе ала алмауы мүмкін."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS жадында орын аз. Хабарларды жою керек болуы мүмкін."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Телефон нөміріңізді растау"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Бұл бір реттік қадам Messaging қолданбасының топтық хабарларды тиісті түрде жеткізуін қамтамасыз етеді."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Телефон нөмірі"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Тасушы арқылы барлық хабарларды жою"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> уақыттан асқан хабарларды жою"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> ескірек хабарларды автоматты түрде жою"</string>
+    <string name="ignore" msgid="7063392681130898793">"Елемеу"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Медиа бар барлық хабарларды жою керек пе?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> ескірек хабарларды жою керек пе?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> ескірек хабарларды жою және автоматты түрде жоюды қосу керек пе?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> айтты"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Сіз айттыңыз"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Хабар, кімнен: <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Сіз хабар жібердіңіз"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Жіберілуде…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Жіберілмеді. Әрекетті қайталау үшін түртіңіз."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Жіберілмеді. Әрекет қайталануда…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Қайта жіберу немесе жою"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Жедел қызметтерге дауыстық қоңырау соғыңыз. Бұл ретте мәтіндік хабарды жеткізу мүмкін болмады."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Сәтсіз аяқталды"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Жүктейтін жаңа MMS хабары бар"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Жаңа MMS хабары"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Жүктеу мүмкін болмады"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Әрекетті қайталау үшін түртіңіз"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Жүктеу үшін түртіңіз"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Жүктеу немесе жою"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Жүктелуде…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Хабар мерзімі бітті немесе ол қол жетімді емес"</string>
+    <string name="mms_info" msgid="3402311750134118165">"өлшемі: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, мерзімі бітетін уақыт: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Жіберу мүмкін емес. Алушы жарамсыз."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Қызмет желіде белсендірілмеген"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Желілік мәселеге байланысты жіберу мүмкін болмады"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Хабар мерзімі бітті немесе ол қол жетімді емес"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Тақырыпсыз)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Белгісіз хабар жіберуші"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Жеткізілді"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="SUBJECT">%1$s</xliff:g> хабарын <xliff:g id="FROM">%2$s</xliff:g> арқылы жүктеу мүмкін болмады."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Жад көлемінің аз болуына байланысты дерекқор әрекетін аяқтау мүмкін болмады"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Хабар жіберілмеді"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Messaging қолданбасында кейбір хабарлар жіберілмеген"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> сөйлесуде <xliff:g id="MESSAGES_1">%d</xliff:g> хабар</item>
+      <item quantity="one">бір сөйлесуде <xliff:g id="MESSAGES_0">%d</xliff:g> хабар</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Хабар жүктелмеген"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Messaging қолданбасында кейбір хабарлар жүктелмеген"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> сөйлесуде <xliff:g id="MESSAGES_1">%d</xliff:g> хабар</item>
+      <item quantity="one">бір сөйлесуде <xliff:g id="MESSAGES_0">%d</xliff:g> хабар</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> нөміріне хабар жіберілмеді"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Жедел қызметтерге дауыстық қоңырау соғыңыз. Бұл ретте <xliff:g id="NUMBER">%1$s</xliff:g> нөміріне мәтіндік хабарды жеткізу мүмкін болмады."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> жаңа хабар</item>
+      <item quantity="one">Жаңа хабар</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Бастау"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камера қол жетімді емес"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камера қол жетімді емес"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Бейне түсіру қол жетімді емес"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Медианы сақтау мүмкін емес"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Сурет түсіру мүмкін емес"</string>
+    <string name="back" msgid="1477626055115561645">"Артқа"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Мұрағатталды"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Жою"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Мұрағаттау"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Мұрағаттан шығару"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Хабарландыруларды өшіру"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Хабарландыруларды қосу"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Контакт қосу"</string>
+    <string name="action_download" msgid="7786338136368564146">"Жүктеу"</string>
+    <string name="action_send" msgid="377635240181672039">"Жіберу"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Жою"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Бұл хабарды жою қажет пе?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Бұл әрекетті болдырмау мүмкін емес."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Жою"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Осы сөйлесулерді жою қажет пе?</item>
+      <item quantity="one">Осы сөйлесуді жою қажет пе?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Жою"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Бас тарту"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Кімге"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Бірнеше кескінді таңдау"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Таңдауды растау"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Аудионы жазу мүмкін емес. Әрекетті қайталаңыз."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Аудионы ойнату мүмкін емес. Әрекетті қайталаңыз."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Аудионы сақтау мүмкін болмады. Әрекетті қайталаңыз."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Түрту және ұстап тұру"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Фотосурет"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудиоклип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Бейне"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Контакт карточкасы"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Жүктеу"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS арқылы жауап беру"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS ар. жау. б."</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Жауап беру"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> қатысушы</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> қатысушы</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Мен"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Контакт бөгелді және мұрағатталды"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Контакт құлыптан босатылды және мұрағаттан шығарылды"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> мұрағатталды"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> мұрағаттан шығарылды"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Хабарландырулар өшірілген"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Хабарландырулар қосылған"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Бәрі орнатылды. «Қайта жіберу» пәрменін түртіңіз."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"\"Хабар алмасу\" қолданбасы әдепкі SMS қолданбасы ретінде сәтті орнатылды."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Тіркемелерді алып тастау</item>
+      <item quantity="one">Тіркемені алып тастау</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудио тіркеме"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Аудио тіркемені ойнату"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Кідірту"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> хабары: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> сәтсіз хабары: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> хабары: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> тобына жіберілмеген хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> тобына хабар жіберілуде: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> тобына сәтсіз хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> тобына хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> сәтсіз хабары: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> хабары: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> тобына жіберілмеген хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> тобына хабар жіберілуде: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> тобына сәтсіз хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> тобына хабар: <xliff:g id="MESSAGE">%2$s</xliff:g>. Уақыт: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Сәтсіз хабар. Қайталау үшін түртіңіз."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> адаммен сөйлесу"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Тақырыпты жою"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Бейне түсіру"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Фотосурет түсіру"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Сурет түсіру"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Бейне жазуды бастау"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Толық экранды камераға ауысу"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Алдыңғы және артқы камера арасында ауысу"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Жазуды тоқтату және бейне тіркеу"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Бейне жазуды тоқтату"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging фотосуреттері"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> фотосурет «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» альбомына сақталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> фотосурет «<xliff:g id="ALBUMNAME_1">%s</xliff:g>» альбомына сақталды</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> бейне «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» альбомына сақталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> бейне «<xliff:g id="ALBUMNAME_1">%s</xliff:g>» альбомына сақталды</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> тіркеме «<xliff:g id="ALBUMNAME_3">%s</xliff:g>» альбомына сақталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тіркеме «<xliff:g id="ALBUMNAME_1">%s</xliff:g>» альбомына сақталды</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тіркеме «Жүктеулер» ішіне сақталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тіркеме «Жүктеулер» ішіне сақталды</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тіркеме сақталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тіркеме сақталды</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тіркемені сақтау мүмкін болмады</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тіркемені сақтау мүмкін болмады</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS тіркемесі сақталды"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Параметрлер"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Мұрағатталды"</string>
+    <string name="action_close" msgid="1840519376200478419">"Жабу"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Кеңейтілген"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Күйін келтіру"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Хабарландырулар"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Дыбыс"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Үнсіз"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Дірілдеу"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Бөгелген"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS жеткізу туралы есептер"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Әр жіберілген SMS үшін жеткізу туралы есепті сұрау"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Авто шығарып алу"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS хабарларын автоматты түрде шығарып алу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Роуминг кезінде авто-шығарып алу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Роумингте MMS автоматты түрде шығарып алу"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Топтық хабар алмасу"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Бірнеше алушыға бір хабар жіберу үшін MMS пайдалану"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Әдепкі SMS қолданбасы"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Әдепкі SMS қолданбасы"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Телефон нөміріңіз"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Белгісіз"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Шығыс хабар дыбыстары"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS дампын сақтау"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Алынған SMS өңделмеген деректерінің дампын сыртқы қойма файлына сақтау"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS дампын сақтау"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Алынған MMS өңделмеген деректерінің дампын сыртқы қойма файлына сақтау"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Сымсыз дабылдар"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Хабар опциялары"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Мәтінді көшіру"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Мәліметтерді көру"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Жою"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Қайта жіберу"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Хабар мәліметтері"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tүрі: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Мәтіндік-хабар"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mультимедиалық хабар"</string>
+    <string name="from_label" msgid="1947831848146564875">"Кімнен: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Кімге: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Жіберілді: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Қабылданды: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Тақырып: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Өлшем: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Басымдық: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Жоғары"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Қалыпты"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Төмен"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Жіберуші мекенжайы жасырын"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Тіркемелерді жүктеу кезінде хабар жіберу мүмкін емес."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Тіркемені жүктеу мүмкін емес. Әрекетті қайталаңыз."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Желі дайын емес. Әрекетті қайталаңыз."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Мәтінді жою"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Мәтінді және сандарды енгізу арасында ауысу"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Қосымша қатысушыларды қосу"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Қатысушыларды растау"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Жаңа сөйлесуді бастау"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Осы элементті таңдау"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Бейнені ойнату"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Адамдар және опциялар"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Күйін келтіру"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Адамдар және опциялар"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Жалпы"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Осы сөйлесудегі адамдар"</string>
+    <string name="action_call" msgid="6596167921517350362">"Қоңырау шалу"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Хабарды жіберу"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; картасынан хабар жіберу"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Фотосуреттер жіберу</item>
+      <item quantity="one">Фотосурет жіберу</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Аудиолар жіберу</item>
+      <item quantity="one">Аудио жіберу</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Бейнелер жіберу</item>
+      <item quantity="one">Бейне жіберу</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Контакті карточкаларын жіберу</item>
+      <item quantity="one">Контакті карточкасын жіберу</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Тіркемелер жіберу</item>
+      <item quantity="one">Тіркеме жіберу</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> тіркеме жіберуге дайын</item>
+      <item quantity="one">Бір тіркеме жіберуге дайын</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Пікір жіберу"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store дүкенінде көру"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Нұсқа туралы ақпарат"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Нұсқа: %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Ашық бастапқы код лицензиялары"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Хабарландырулар"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Тіркеме шегіне жеттіңіз"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Тіркемені жүктеу сәтсіз аяқталды."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Контактілерге қосу керек пе?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Контакт қосу"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Тақырып"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Тақырып: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Контакт карточкасы жүктелуде"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Контакт картасын жүктеу мүмкін болмады"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Контакт карточкасын көру"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контакт</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> контакт</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Контакт карталары"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Туған күн"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Ескертпелер"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Хабарды қайта жіберу"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Жауап беру"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS өшірілген"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Жіберу үшін \"Хабар алмасу\" қолданбасын әдепкі SMS қолданбасы ретінде орнатыңыз"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"\"Хабар алмасу\" қолданбасын әдепкі SMS қолданбасы ретінде орнату"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Өзгерту"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Хабарлар алу үшін Messaging қолданбасын әдепкі SMS қолданбасы ретінде орнатыңыз"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS хабарларын жіберу үшін таңдаулы SIM таңдалмаған"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Құрылғы иесі бұл қолданбаға рұқсат етпеген."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Жарайды"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Сөйлесуде қатысушылар тым көп"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Жарамсыз контактілер</item>
+      <item quantity="one">Жарамсыз контакті</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Камера кескінін жүктеу мүмкін болмады"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Сіз: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Жоба"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Басталған жаңа сөйлесуді осы жерде тізімнен көресіз"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Мұнда мұрағатталған сөйлесулер көрсетіледі"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Сөйлесулер жүктелуде…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Сурет"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудиоклип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Бейне"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Контакт карточкасы"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Болдырмау"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Қайталау"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Жаңа хабарды бастау үшін контакт атын немесе телефон нөмірін енгізіңіз"</string>
+    <string name="action_block" msgid="9032076625645190136">"Бөгеу"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> бөгеу"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> бөгеуден шығару"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> бөгеу керек пе?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Сіз осы нөмірден хабарлар алуды жалғастырасыз, бірақ енді хабардар етілмейсіз. Бұл сөйлесу мұрағатталады."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Бөгелген контактілер"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"БӨГЕУДЕН ШЫҒАРУ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Бөгелген контактілер"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Құжаттар кітапханасынан кескінді таңдау"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Хабар жіберілуде"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Хабар жіберілді"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Ұялы деректер өшірілген. Параметрлерді тексеріңіз."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Ұшақ режимінде хабарлар жіберу мүмкін емес"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Хабарды жіберу мүмкін болмады"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Хабар жүктелді"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Ұялы деректер өшірілген. Параметрлерді тексеріңіз."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Ұшақ режимінде хабарларды жүктеу мүмкін емес"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Хабарды жүктеу мүмкін болмады"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Нөл"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Бір"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Екі"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Үш"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Төрт"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Бес"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Алты"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Жеті"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Сегіз"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Тоғыз"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> арқылы хабар жіберілмейді, <xliff:g id="ERRORCODE">%2$d</xliff:g> қатесі"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Белгісіз оператормен хабар жіберілмейді, <xliff:g id="ERRORCODE">%1$d</xliff:g> қатесі"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Қайта жіберілген: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Хабар жіберілмеді, желіде қызмет белсендірілмеген"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Хабар жіберілмеді: жарамсыз межелі мекенжай"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Хабар жіберілмеді: жарамсыз хабар"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Хабар жіберілмеді: қолдау көрсетілмейтін мазмұн"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Хабар жіберілмеді: қолдау көрсетілмейтін хабар"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Хабар жіберілмеді: тым үлкен"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Жаңа хабар"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Көру"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Кескін"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Тиісті қолданбаны табу мүмкін болмады"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Алушыны жою"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Жаңа хабар"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Бас тарту"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Кіру нүктесін өңдеу"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Орнатылмаған"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Аты"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS прокси"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS порты"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN түрі"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN жою"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Жаңа APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Сақтау"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Алып тастау"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Атау өрісі бос болмауы тиіс."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN бос болмауы тиіс."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC өрісі 3 цифрдан тұруы тиіс."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC өрісі 2 немесе 3 цифрдан тұруы тиіс."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Әдепкі APN параметрлерін қалпына келтіру."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Әдепкі параметрлерге қалпына келтіру"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Әдепкі APN параметрлерін қалпына келтіру аяқталды."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Атаусыз"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Кіру нүктесі атаулары"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs (Кіру нүктесі атаулары)"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Жаңа APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Кіру нүктесі атауының параметрлері осы пайдаланушы үшін қол жетімді емес"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Аралық сақтағышқа көшіру керек пе?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Көшіру"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> картасына"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Жалпы"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Кеңейтілген"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Жалпы параметрлер"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Қосымша параметрлер"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"«<xliff:g id="SIM_NAME">%s</xliff:g>» SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Барлық алушыларға SMS хабарларын жіберіңіз. Жауаптарды тек сіз аласыз"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Барлық алушыларға бір MMS жіберу"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Белгісіз нөмір"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Жаңа хабар"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Жаңа хабар"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM таңдағыш"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> таңдалды, SIM таңдағыш"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Тақырыпты өңдеу"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM картасын таңдау немесе тақырыпты өңдеу"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Аудио жазу үшін түртіп, ұстап тұрыңыз"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Жаңа сөйлесуді бастау"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Хабар алмасу"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Хабар алмасу тізімі"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Хабар алмасу"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Жаңа хабар"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Сөйлесімдер тізімі"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Сөйлесулер жүктелуде"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Хабарлар жүктелуде"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Көбірек сөйлесулерді көру"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Қосымша хабарларды көру"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Сөйлесу жойылды"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Сөйлесу жойылды. Басқа \"Хабар алмасу\" сөйлесуін көрсету үшін түртіңіз"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Бөгелген"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Бөгеуден шығарылған"</string>
+    <string name="db_full" msgid="8459265782521418031">"Жадтағы бос орын аз. Кейбір деректер жоғалуы мүмкін."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Тіркемелерді таңдау"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Таңдауды растау"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> таңдалды"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Бір немесе бірнеше тіркемені жойып, әрекетті қайталаңыз."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Хабарды жіберіп көре аласыз, бірақ бір немесе бірнеше тіркемені жоймасаңыз, ол жеткізілмеуі мүмкін."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Әр хабарламада бір ғана бейне жіберуге болады. Қосымша бейнелерді жойып, әрекетті қайталаңыз."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging тіркемені жүктей алмады."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Бәрібір жіберу"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Сөйлесуді бастау мүмкін болмады"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> таңдалған"</string>
+</resources>
diff --git a/res/values-km/arrays.xml b/res/values-km/arrays.xml
new file mode 100644
index 0000000..69f6e0d
--- /dev/null
+++ b/res/values-km/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"គ្មាន​ប្រធានបទ"</item>
+    <item msgid="272485471009191934">"គ្មាន​ប្រធាន​បទ"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"បាទ/ចាស"</item>
+    <item msgid="6049132459802288033">"ទេ"</item>
+    <item msgid="3084376867445867895">"យល់ព្រម"</item>
+    <item msgid="3155097332660174689">"ហេហេ"</item>
+    <item msgid="2611328818571146775">"អរគុណ"</item>
+    <item msgid="4881335087096496747">"ខ្ញុំ​យល់​ព្រម"</item>
+    <item msgid="2422296858597420738">"ល្អ"</item>
+    <item msgid="4805581752819452687">"នៅ​តាម​ផ្លូវ​"</item>
+    <item msgid="4746700499431366214">"យល់ព្រម ខ្ញុំ​នឹង​ទាក់ទង​អ្នក​ពេល​ក្រោយ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
new file mode 100644
index 0000000..fba58e2
--- /dev/null
+++ b/res/values-km/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"​ការ​ផ្ញើ​សារ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"ការ​​ផ្ញើ​សារ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"ជ្រើសរើសការសន្ទនា"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ការកំណត់"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"ផ្ញើ​សារ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"បន្ថែម​ឯកសារ​ភ្ជាប់"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"ជំនួយ"</string>
+    <string name="welcome" msgid="2857560951820802321">"សូមស្វាគមន៍"</string>
+    <string name="skip" msgid="7238879696319945853">"រំលង"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"បន្ទាប់ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"បន្ទាប់"</string>
+    <string name="exit" msgid="1905187380359981199">"ចេញ"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ការកំណត់ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ការកំណត់"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"ការផ្ញើសារត្រូវការសិទ្ធិអនុញ្ញាតដើម្បីប្រើសារ SMS, ទូរស័ព្ទ និងទំនាក់ទំនង។"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"អ្នកអាចប្តូរសិទ្ធិអនុញ្ញាតនៅក្នុង ការកំណត់ &gt; កម្មវិធី &gt; ការផ្ញើសារ &gt; សិទិ្ធអនុញ្ញាត។"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"អ្នកអាចប្តូរសិទ្ធិអនុញ្ញាតនៅក្នុង ការកំណត់ , កម្មវិធី, ការផ្ញើសារ, សិទ្ធិអនុញ្ញាត។"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ញឹកញាប់"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ទំនាក់ទំនងទាំងអស់"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"ផ្ញើ​ទៅ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ថត​រូបភាព ឬ​វីដេអូ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ជ្រើស​រូបភាព​ពី​ឧបករណ៍​នេះ"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ថត​សំឡេង"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ជ្រើស​រូបថត"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"បានជ្រើសឯកសារកំសាន្ត។"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"បានលុបការជ្រើសឯកសារកំសាន្ត។"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"បាន​ជ្រើស <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"រូបភាព <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"រូបភាព"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ថត​សំឡេង"</string>
+    <string name="action_share" msgid="2143483844803153871">"ចែករំលែក​"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ថ្មីៗ​នេះ"</string>
+    <string name="posted_now" msgid="867560789350406701">"ឥឡូវ"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> នាទី</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> នាទី</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ម៉ោង</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ម៉ោង</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ថ្ងៃ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ថ្ងៃ</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> សប្តាហ៍</item>
+      <item quantity="one">មួយសប្តាហ៍</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ខែ</item>
+      <item quantity="one">មួយខែ</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ឆ្នាំ</item>
+      <item quantity="one">មួយឆ្នាំ</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"សារ​ថ្នាក់ ០"</string>
+    <string name="save" msgid="5081141452059463572">"រក្សាទុក"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ឧបករណ៍នៅសល់ទំហំផ្ទុកតិច។ ការផ្ញើសារនឹងលុបសារចាស់ៗដើម្បីធ្វើឲ្យមានទំហំផ្ទុកទំនេរ។"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"អស់​ទំហំ​ផ្ទុក"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"ការផ្ញើសារអាចនឹងមិនផ្ញើ ឬទទួលសារទេ រហូតដល់មានទំហំផ្ទុកបន្ថែមទៀតនៅលើឧបករណ៍របស់អ្នក។"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ជិត​អស់​ទំហំ​ផ្ទុក​សារ SMS ។ អ្នក​អាច​​​លុប​សារ​មួយ​ចំនួន។"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"បញ្ជាក់លេខទូរស័ព្ទរបស់អ្នក"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ជំហានមួយលើកនេះធានាថាការផ្ញើសារនឹងបញ្ជូនសារក្រុមរបស់អ្នកបានត្រឹមត្រូវ។"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"លេខទូរស័ព្ទ"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"លុប​សារ​​​​ដែល​មាន​មេឌៀ​ទាំងអស់"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"លុប​សារ​ចាស់​ជាង <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"លុប​សារ​ចាស់​ជាង <xliff:g id="DURATION">%s</xliff:g> ដោយ​ស្វ័យ​ប្រវត្តិ"</string>
+    <string name="ignore" msgid="7063392681130898793">"មិន​អើពើ"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"លុប​សារ​ទាំងអស់​មាន​ក្នុង​មេឌៀ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"លុប​សារ​ចាស់​ជាង <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"លុប​សារ​ចាស់​ជាង <xliff:g id="DURATION">%s</xliff:g> និង​បើក​ការ​លុប​ស្វ័យ​ប្រវត្តិ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> និយាយថា"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"អ្នកនិយាយថា"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"សារពី <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"អ្នកបានផ្ញើសារមួយ"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"កំពុង​ផ្ញើ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"មិន​បាន​ផ្ញើ។ ប៉ះ​ដើម្បី​ព្យាយាម​ម្ដងទៀត។"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"មិន​បាន​ផ្ញើ។ កំពុង​ព្យាយាម​ម្ដងទៀត..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ផ្ញើ​ម្ដង​ទៀត ឬ​លុប"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"សូមធ្វើការហៅជាសម្លេងទៅកាន់សេវាកម្មសង្គ្រោះបន្ទាន់។ សារជាអក្សររបស់អ្នកមិនអាចបញ្ជូនបានទេនៅពេលនេះ។"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"បាន​បរាជ័យ"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"សារ MMS ថ្មី​ត្រូវ​ទាញ​យក"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"សារ MMS ថ្មី"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"មិន​អាច​ទាញ​យក"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ប៉ះ​ ដើម្បី​ព្យាយាម​ម្តង​ទៀត"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ប៉ះ​ ដើម្បី​ទាញ​យក"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ទាញ​យក ​ឬ​លុប"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"កំពុង​ទាញ​យក..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"សារ​បាន​​ផុត​កំណត់​ ឬ​មិន​អាច​ប្រើ​បាន"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ទំហំ៖ <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, ផុត​កំណត់៖ <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"មិន​អាច​ផ្ញើ។ អ្នក​ទទួល​មិន​ត្រឹមត្រូវ។"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"សេវា​មិន​សកម្ម​នៅ​លើ​បណ្ដាញ"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"មិន​អាច​ផ្ញើ​ដោយសារ​បញ្ហា​បណ្ដាញ"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"សារ​បាន​​ផុត​កំណត់​ ឬ​មិន​អាច​ប្រើ​បាន"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(គ្មាន​ប្រធាន​បទ)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"មិន​ស្គាល់​អ្នក​ផ្ញើ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"បាន​បញ្ជូន"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"មិន​អាច​ទាញ​យក​សារ <xliff:g id="SUBJECT">%1$s</xliff:g> ពី <xliff:g id="FROM">%2$s</xliff:g> បាន​ទេ។"</string>
+    <string name="low_memory" msgid="5300743415198486619">"មិន​អាច​​បញ្ចប់​ប្រតិបត្តិការ​​មូលដ្ឋាន​ទិន្នន័យ​ដោយសារ​អង្គ​ចងចាំ​មិន​គ្រប់គ្រាន់​​"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"មិន​បាន​ផ្ញើ​សារ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"សារមួយចំនួនមិនបានផ្ញើនៅក្នុងការផ្ញើសារទេ"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other">សារ <xliff:g id="MESSAGES_1">%d</xliff:g> នៅក្នុងការសន្ទនា <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="one">សារ <xliff:g id="MESSAGES_0">%d</xliff:g> នៅក្នុងការសន្ទនាមួយ</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"មិនបានទាញយកសារ"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"សារមួយចំនួនមិនបានទាញយកនៅក្នុងការផ្ញើសារទេ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other">សារ <xliff:g id="MESSAGES_1">%d</xliff:g> នៅក្នុងការសន្ទនា <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="one">សារ <xliff:g id="MESSAGES_0">%d</xliff:g> នៅក្នុងការសន្ទនាមួយ</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"សារទៅកាន់ <xliff:g id="NUMBER">%1$s</xliff:g> មិនត្រូវបានផ្ញើទេ"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"សូមធ្វើការហៅជាសម្លេងទៅកាន់សេវាកម្មសង្គ្រោះបន្ទាន់។ សារជាអក្សររបស់អ្នកទៅ <xliff:g id="NUMBER">%1$s</xliff:g> មិនអាចបញ្ជូនបានទេនៅពេលនេះ។"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other">សារថ្មី <xliff:g id="MESSAGES">%d</xliff:g></item>
+      <item quantity="one">សារថ្មី</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ចាប់ផ្ដើម"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"មិន​អាច​ប្រើ​ម៉ាស៊ីន​ថត​បាន"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"មិន​អាច​ប្រើ​ម៉ាស៊ីន​ថត​បាន"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"មិន​អាច​ថត​វីដេអូ​បាន"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"មិន​អាច​រក្សាទុក​​មេឌៀ"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"មិនអាចថតរូបភាព"</string>
+    <string name="back" msgid="1477626055115561645">"ថយក្រោយ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ទុក​ក្នុង​ប័ណ្ណសារ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"លុប"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ប័ណ្ណសារ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"មិន​ទុក​ក្នុង​ប័ណ្ណសារ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"បិទ​ការ​ជូនដំណឹង"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"បើក​ការ​ជូនដំណឹង​"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"បន្ថែម​ទំនាក់ទំនង"</string>
+    <string name="action_download" msgid="7786338136368564146">"ទាញ​យក"</string>
+    <string name="action_send" msgid="377635240181672039">"ផ្ញើ"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"លុប"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"លុប​សារ​នេះ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"សកម្មភាព​នេះ​មិន​អាច​ធ្វើ​វិញ​បាន​ទេ។"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"លុប"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">លុបការសន្ទនាទាំងនេះ?</item>
+      <item quantity="one">លុបការសន្ទនានេះ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"លុប"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"បោះបង់"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ជូន​ចំពោះ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"ជ្រើស​រូបភាព​ច្រើន"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"បញ្ជាក់​​ការ​ជ្រើស"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"មិន​អាច​ថត​សំឡេង។ ព្យាយាម​ម្ដង​ទៀត។"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"មិន​អាច​ចាក់​សំឡេង។ ព្យាយាម​ម្ដងទៀត។"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"មិន​អាច​រក្សាទុក​សំឡេង។ ព្យាយាម​ម្ដងទៀត។"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ប៉ះ &amp; សង្កត់"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"រូបភាព"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ឈុត​សំឡេង"</string>
+    <string name="notification_video" msgid="4331423498662606204">"វីដេអូ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"កាត​ទំនាក់ទំនង"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ទាញ​យក"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"ឆ្លើយតប​តាម​សារ SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"ឆ្លើយតបតាម MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ឆ្លើយតប"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other">អ្នកចូលរួម <xliff:g id="COUNT_1">%d</xliff:g> នាក់</item>
+      <item quantity="one">អ្នកចូលរួម <xliff:g id="COUNT_0">%d</xliff:g> នាក់</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ខ្ញុំ"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"ទំនាក់ទំនង​ត្រូវ​បាន​ទប់ស្កាត់ &amp; ទុក​ក្នុង​ប័ណ្ណសារ"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"បានរារាំង និងបានដកទំនាក់ទំនងចេញពីបណ្ណ័សារ"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"បានទុកក្នុងបណ្ណសារចំនួន<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"មិនបានទុកក្នុងប័ណ្ណសារចំនួន <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"បានបិទការជូនដំណឹង"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"បានបើកការជូនដំណឹង"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"កំណត់​រួចរាល់។ ប៉ះ​ដើម្បី​ផ្ញើ​ម្ដងទៀត។"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"បានកំណត់ការផ្ញើសារជាកម្មវិធីសារ SMS លំនាំដើមដោយជោគជ័យ។"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">បោះបង់ឯកសារភ្ជាប់</item>
+      <item quantity="one">បោះបង់ឯកសារភ្ជាប់</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ឯកសារភ្ជាប់សម្លេង"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ឯកសារភ្ជាប់សម្លេង Play"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ផ្អាក"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"សារពី <xliff:g id="SENDER">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"សារបរាជ័យពី <xliff:g id="SENDER">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"សារពី <xliff:g id="SENDER">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"សារមិនបានផ្ញើទៅ <xliff:g id="CONTACT">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"កំពុងផ្ញើសារទៅ <xliff:g id="CONTACT">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"សារបរាជ័យទៅ <xliff:g id="CONTACT">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"សារទៅ <xliff:g id="CONTACT">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"សារបរាជ័យពី <xliff:g id="SENDER">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។ <xliff:g id="GROUPINFO">%4$s</xliff:g>។"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"សារពី <xliff:g id="SENDER">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។ <xliff:g id="GROUPINFO">%4$s</xliff:g>។"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"សារមិនបានផ្ញើទៅ <xliff:g id="GROUP">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"កំពុងផ្ញើសារទៅ <xliff:g id="GROUP">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"សារបរាជ័យទៅ <xliff:g id="GROUP">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"សារទៅ <xliff:g id="GROUP">%1$s</xliff:g>៖ <xliff:g id="MESSAGE">%2$s</xliff:g>។ ម៉ោង៖ <xliff:g id="TIME">%3$s</xliff:g>។"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"សារបរាជ័យ។ ប៉ះដើម្បីព្យាយាមម្តងទៀត។"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"ការសន្ទនាជាមួយ <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"លុប​ប្រធានបទ"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ថត​វីដេអូ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ថត​រូបភាព​ថេរ"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ថតរូប"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ចាប់ផ្ដើម​ថត​វីដេអូ"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"ប្ដូរ​ទៅ​ម៉ាស៊ីន​ថត​ពេញ​អេក្រង់"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ប្ដូរ​រវាង​ម៉ាស៊ីន​ថត​មុន និង​ក្រោយ"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"បញ្ឈប់​ការ​ថត និង​ភ្ជាប់​វីដេអូ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"បញ្ឈប់​ការ​ថត​វីដេអូ"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"រូបភាពសារ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">បានរក្សាទុករូបថត <xliff:g id="QUANTITY_2">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">បានរក្សាទុករូបថត <xliff:g id="QUANTITY_0">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">បានរក្សាទុកវីដេអូ <xliff:g id="QUANTITY_2">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">បានរក្សាទុកវីដេអូ <xliff:g id="QUANTITY_0">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_2">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_0">%d</xliff:g> ទៅក្នុងអាល់ប៊ុម \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_1">%d</xliff:g> ទៅក្នុង \"ទាញយក\"</item>
+      <item quantity="one">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_0">%d</xliff:g> ទៅក្នុង \"ទាញយក\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_1">%d</xliff:g></item>
+      <item quantity="one">បានរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">មិនអាចរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_1">%d</xliff:g></item>
+      <item quantity="one">មិនអាចរក្សាទុកឯកសារភ្ជាប់ <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"បាន​រក្សាទុក​ឯកសារ​ភ្ជាប់​ជា​សារ MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ការកំណត់"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ទុក​ក្នុង​ប័ណ្ណសារ"</string>
+    <string name="action_close" msgid="1840519376200478419">"បិទ"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"សារ MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"កម្រិត​ខ្ពស់"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"កែ​កំហុស"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"ការ​ជូនដំណឹង"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"សំឡេង"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"ស្ងាត់"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ញ័រ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"បាន​ទប់ស្កាត់"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"របាយការណ៍​បញ្ជូន​សារ SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ស្នើ​​​របាយ​ការណ៍​​បញ្ជូន​សម្រាប់​សារ SMS ​នីមួយៗ​ដែល​អ្នក​ផ្ញើ"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"​យក​ស្វ័យ​ប្រវត្តិ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"ទាញ​យក​សារ MMS ដោយ​ស្វ័យ​ប្រវត្តិ​"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ទាញ​យក​ដោយ​ស្វ័យប្រវត្តិ​ពេល​រ៉ូមីង"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ទាញសារ MMS ត្រឡប់មកវិញដោយស្វ័យប្រវត្តិនៅពេលរ៉ូមីង"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ការ​ផ្ញើ​សារ​​ជា​ក្រុម"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ប្រើ MMS ដើម្បី​ផ្ញើ​សារ នៅ​ពេល​មាន​អ្នក​ទទួល​ច្រើន"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"កម្មវិធី​ផ្ញើ​សារ SMS ​លំនាំ​ដើម"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"កម្មវិធី​ផ្ញើ​សារ SMS ​លំនាំ​ដើម"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"លេខ​ទូរសព្ទ​របស់​អ្នក"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"មិន​ស្គាល់"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"សម្លេងសារផ្ញើចេញ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"បោះបង់​សារ SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ដាក់​ទិន្នន័យ​ដើម​នៃ​សារ SMS បាន​ទទួល​ក្នុង​ឯកសារ​ឧបករណ៍​ផ្ទុក​ខាង​ក្រៅ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"បោះបង់​សារ MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ដាក់​ទិន្នន័យ​ដើម​នៃ​សារ MMS បាន​ទទួល​ក្នុង​ឯកសារ​ឧបករណ៍​ផ្ទុក​ខាង​ក្រៅ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ការ​ជូនដំណឹង​​ឥត​​​ខ្សែ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"ជម្រើស​សារ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ចម្លង​អត្ថបទ"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"មើល​​ព័ត៌មាន​លម្អិត"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"លុប"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"បញ្ជូន​បន្ត"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"ព័ត៌មាន​លម្អិត​សារ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ប្រភេទ៖ "</string>
+    <string name="text_message" msgid="7415419755252205721">"សារ​​អត្ថបទ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"សារ​ពហុ​​មេឌៀ"</string>
+    <string name="from_label" msgid="1947831848146564875">"ពី៖ "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ជូន​ចំពោះ៖ "</string>
+    <string name="sent_label" msgid="5186286057597137301">"បាន​ផ្ញើ៖ "</string>
+    <string name="received_label" msgid="4442494712757995203">"បាន​ទទួល៖ "</string>
+    <string name="subject_label" msgid="1887378451808609152">"ប្រធានបទ៖ "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ទំហំ៖ "</string>
+    <string name="priority_label" msgid="5029073794896222902">"អាទិភាព៖ "</string>
+    <string name="sim_label" msgid="2706003016582772108">"ស៊ីម៖ "</string>
+    <string name="priority_high" msgid="728836357310908368">"ខ្ពស់"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ធម្មតា"</string>
+    <string name="priority_low" msgid="7398724779026801851">"ទាប"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"ស៊ីម <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"​អាសយដ្ឋាន​​អ្នក​ផ្ញើ​ដែល​បាន​លាក់"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"មិន​អាច​ផ្ញើ​សារ​ខណៈ​ពេល​ផ្ទុក​ឯកសារ​ភ្ជាប់។"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"មិន​អាច​ផ្ទុក​ឯកសារ​ភ្ជាប់។ ព្យាយាម​ម្ដង​ទៀត។"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"បណ្តាញមិនទាន់រួចរាល់ទេ។ ព្យាយាមម្តងទៀត។"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"លុប​អត្ថបទ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ប្ដូរ​​រវាង​លេខ និង​អត្ថបទ​បញ្ចូល"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"បន្ថែម​អ្នក​ចូលរួម​ច្រើន​ទៀត"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"បញ្ជាក់​អ្នក​ចូលរួម"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"ចាប់ផ្ដើមការសន្ទនាថ្មី"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ជ្រើស​ធាតុ​នេះ"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ចាក់​វីដេអូ"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"មនុស្ស &amp; ជម្រើស"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"កែ​កំហុស"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"មនុស្ស &amp; ជម្រើស"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ទូទៅ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"មនុស្ស​ក្នុង​ការ​សន្ទនា​នេះ"</string>
+    <string name="action_call" msgid="6596167921517350362">"ហៅ"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ផ្ញើ​សារ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"ផ្ញើ​សារ&lt;br/&gt;&lt;small&gt;ពី <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ផ្ញើរូបថត</item>
+      <item quantity="one">ផ្ញើរូបថត</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">ផ្ញើសំឡេង</item>
+      <item quantity="one">ផ្ញើសំឡេង</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ផ្ញើវីដេអូ</item>
+      <item quantity="one">ផ្ញើវីដេអូ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">ផ្ញើកាតទំនាក់ទំនង</item>
+      <item quantity="one">ផ្ញើកាតទំនាក់ទំនង</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">ផ្ញើឯកសារភ្ជាប់</item>
+      <item quantity="one">ផ្ញើឯកសារភ្ជាប់</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">ឯកសារភ្ជាប់ <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ត្រៀមសម្រាប់ផ្ញើ</item>
+      <item quantity="one">ឯកសារភ្ជាប់មួយត្រៀមសម្រាប់ផ្ញើ</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ផ្ដល់​មតិ​ស្ថាបនា"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"មើល​នៅ​ក្នុង​​ Google ឃ្លាំង​កម្សាន្ត"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ព័ត៌មាន​កំណែ"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"កំណែ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"អាជ្ញាប័ណ្ណ​កម្មវិធី​ប្រភព​កូដ​ចំហ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"ការ​ជូនដំណឹង"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ឯកសារភ្ជាប់ឈានដល់កំណត់"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ការផ្ទុកឯកសារភ្ជាប់បានបរាជ័យ។"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"បន្ថែម​ទៅ​ទំនាក់ទំនង​?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"បន្ថែម​ទំនាក់ទំនង"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ប្រធានបទ"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"ប្រធានបទ៖ "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"ផ្ទុក​កាត​ទំនាក់ទំនង"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"មិន​អាច​ផ្ទុក​កាត​ទំនាក់ទំនង"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"មើល​កាត​ទំនាក់ទំនង"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other">ទំនាក់ទំនង <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">ទំនាក់ទំនង <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"កាត​ទំនាក់ទំនង"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"ថ្ងៃ​កំណើត"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ចំណាំ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"បញ្ជូន​សារ​បន្ត"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ឆ្លើយតប"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"បាន​បិទ​សារ SMS"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"សូមកំណត់ការផ្ញើសារជាកម្មវិធីសារ SMS លំនាំដើមដើម្បីផ្ញើ"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"កំណត់ការផ្ញើសារជាកម្មវិធីសារ SMS លំនាំដើម"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ផ្លាស់ប្ដូរ"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"សូមកំណត់ការផ្ញើសារជាកម្មវិធីសារ SMS លំនាំដើមដើម្បីទទួលសារ"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"គ្មានស៊ីមកាតដែលបានប្រើត្រូវបានជ្រើសរើសឲ្យផ្ញើសារ SMS ទេ"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"កម្មវិធី​នេះ​មិន​បាន​អនុញ្ញាត​ដោយ​ម្ចាស់​ឧបករណ៍។"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"យល់ព្រម"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"មាន​អ្នក​ចូលរួម​ច្រើន​ពេក​ក្នុង​ការ​សន្ទនា"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">ទំនាក់ទំនងមិនត្រឹមត្រូវ</item>
+      <item quantity="one">ទំនាក់ទំនងមិនត្រឹមត្រូវ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"មិន​អាច​ផ្ទុក​រូបភាព​ម៉ាស៊ីន​ថត"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"អ្នក​៖ "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"សេចក្ដី​ព្រាង"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"នៅ​ពេល​ដែល​អ្នក​ចាប់ផ្ដើម​​ការ​សន្ទនា​ថ្មី ​អ្នក​នឹង​ឃើញ​វា​​​បង្ហាញ​នៅ​ទីនេះ"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ការ​សន្ទនា​បាន​ទុក​ក្នុង​ប័ណ្ណសារ​បង្ហាញ​នៅ​ទីនេះ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"កំពុង​ផ្ទុក​ការ​សន្ទនា…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"រូបភាព"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ឃ្លីបសម្លេង"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"វីដេអូ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"កាត​ទំនាក់ទំនង"</string>
+    <string name="mms_text" msgid="1528791558806015806">"សារ MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"មិនធ្វើវិញ"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ព្យាយាមម្ដងទៀត"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"បញ្ចូល​ឈ្មោះ​ទំនាក់ទំនង​ ឬ​លេខ​ទូរសព្ទ​ដើម្បី​ចាប់ផ្ដើម​សារ​ថ្មី"</string>
+    <string name="action_block" msgid="9032076625645190136">"ទប់ស្កាត់"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"ទប់ស្កាត់ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"មិន​ទប់ស្កាត់ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"ទប់ស្កាត់ <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"អ្នក​នឹង​បន្ត​ទទួល​សារ​ពី​លេខ​នេះ ប៉ុន្តែ​នឹង​មិន​ត្រូវ​បាន​ជូន​ដំណឹង​ទៀត​ទេ។ ការ​សន្ទនា​នេះ​នឹង​ត្រូវ​បាន​ទុក​ក្នុង​ប័ណ្ណសារ។"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"បាន​ទប់ស្កាត់​ទំនាក់ទំនង"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"មិន​ទប់ស្កាត់"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"បាន​ទប់ស្កាត់​ទំនាក់ទំនង​"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ជ្រើស​រូបភាព​ពី​បណ្ណាល័យ​ឯកសារ"</string>
+    <string name="sending_message" msgid="6363584950085384929">"កំពុងផ្ញើសារ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"បានផ្ញើសារ"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ទិន្នន័យ​ចល័ត​ត្រូវ​បាន​បិទ។ ពិនិត្យ​ការ​កំណត់​របស់​អ្នក។"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"មិន​អាច​ផ្ញើ​សារ​ក្នុង​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"មិនអាចផ្ញើសារបានទេ"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"បានទាញយកសារ"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ទិន្នន័យចល័តត្រូវបានបិទ។ ពិនិត្យការកំណត់របស់អ្នក។"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"មិនអាចទាញយកសារនៅក្នុង របៀបយន្តហោះ ទេ។"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"មិនអាចទាញយកសារបានទេ"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"សូន្យ"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"មួយ"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"ពីរ"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"​បី"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"បួន"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ប្រាំ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ប្រាំមួយ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ប្រាំពីរ"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ប្រាំបី"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ប្រាំបួន"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"មិនអាចផ្ញើសារដោយប្រើ <xliff:g id="CARRIERNAME">%1$s</xliff:g> នេះបានទេ។ កំហុស <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"មិនអាចផ្ញើសារដោយប្រើក្រុមហ៊ុនផ្តល់សេវាដែលមិនស្គាល់បានទេ។ កំហុស <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"បញ្ជូន​បន្ត៖ <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"សារ​មិន​បាន​ផ្ញើ៖ សេវាកម្ម​មិន​សកម្ម​លើ​បណ្ដាញ"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"មិន​បាន​ផ្ញើសារ៖ អាសយដ្ឋាន​គោលដៅ​មិន​ត្រឹមត្រូវ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"មិន​បាន​ផ្ញើ​សារ៖ សារ​មិន​ត្រឹមត្រូវ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"មិន​បាន​ផ្ញើ​សារ៖ មិន​គាំទ្រ​មាតិកា"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"មិន​បាន​ផ្ញើសារ៖ មិន​គាំទ្រ​សារ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"មិនបានផ្ញើសារ៖ ធំពេក"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"សារ​ថ្មី"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"មើល"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"រូបភាព"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"មិន​អាច​រក​ឃើញ​កម្មវិធី​ដែល​សមរម្យ"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"លុប​អ្នក​ទទួល"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"សារ​ថ្មី"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"បោះបង់"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"កែ​ចំណុច​ចូល​ដំណើរការ"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"មិនបាន​កំណត់"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ឈ្មោះ"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"ប្រូកស៊ី MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"ច្រក MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"ប្រភេទ APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"លុប APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN ថ្មី"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"រក្សាទុក"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"បោះបង់"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"វាល​ឈ្មោះ​មិន​អាច​ទទេ។"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN មិន​អាច​ទទេ។"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"វាល MCC ត្រូវ​តែ​មាន​ ៣ តួ។"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"វាល MNC ត្រូវ​តែ​មាន​ពីរ ឬ​បី​តួ។"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ស្ដារ​ការ​កំណត់ APN លំនាំដើម​ឡើងវិញ។"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"កំណត់​ទៅ​លំនាំដើម​ឡើងវិញ"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"បាន​បញ្ចប់​ការ​កំណត់​នៃ​ការកំណត់​ APN លំនាំដើម។"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"គ្មាន​ចំណង​ជើង"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ឈ្មោះ​ចំណុច​ចូល​ដំណើរការ"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN ថ្មី"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ការ​កំណត់​ឈ្មោះ​ចូល​ដំណើរការ​មិន​អាច​ប្រើ​បាន​សម្រាប់​អ្នក​ប្រើ​​នេះ"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ចម្លង​ទៅ​ក្ដារ​តម្បៀត​ខ្ទាស់​?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ចម្លង"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ទៅ <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ទូទៅ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"កម្រិត​ខ្ពស់"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"ការ​កំណត់​ទូទៅ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"ការ​កំណត់​កម្រិត​ខ្ពស់"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" ស៊ីម"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ផ្ញើ​សារ SMS នីមួយៗ​ទៅ​អ្នក​ទទួល​ទាំង​អស់។ មាន​តែ​អ្នក​ប៉ុណ្ណោះ​​ទទួល​បាន​ការ​ឆ្លើយតប"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ផ្ញើ​សារ MMS មួយ​ទៅ​អ្នក​ទទួល"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"មិន​ស្គាល់​លេខ"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"សារថ្មី"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"សារថ្មី។"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"កម្មវិធីជ្រើសស៊ីម"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"បានជ្រើសរើស <xliff:g id="SIM_0">%1$s</xliff:g> កម្មវិធីជ្រើសស៊ីម"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"កែប្រធានបទ"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"ជ្រើសស៊ីម ឬកែប្រធានបទ"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ប៉ះ និងសង្កត់ដើម្បីថតសម្លេង"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"ចាប់ផ្ដើមការសន្ទនាថ្មី"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"ការផ្ញើសារ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"បញ្ជីសារ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"ការផ្ញើសារ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"សារថ្មី"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"បញ្ជីសន្ទនា"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"កំពុងផ្ទុកការសន្ទនា…"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"សារកំពុងដំណើរការ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"មើលការសន្ទនាច្រើនទៀត"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"មើលសារច្រើនទៀត"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"បានលុបការសន្ទនា"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"បានលុបការសន្ទនា។ សូមប៉ះដើម្បីបង្ហាញការសន្ទនាផ្សេងទៀតនៅក្នុងការផ្ញើសារ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"បាន​ទប់ស្កាត់"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"បានឈប់ទប់ស្កាត់"</string>
+    <string name="db_full" msgid="8459265782521418031">"ចន្លោះផ្ទុកមានកម្រិតទាប។ ទិន្នន័យមួយចំនួនអាចបាត់បង់។"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ជ្រើសឯកសារភ្ជាប់"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"បញ្ជាក់​​ការ​ជ្រើស"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"បានជ្រើស <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"សូមយកឯកសារភ្ជាប់មួយ ឬច្រើនចេញ ហើយព្យាយាមម្តងទៀត។"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"អ្នកអាចព្យាយាមផ្ញើសារបស់អ្នក ប៉ុន្តែវាប្រហែលជាមិនផ្ញើទៅទេ លុះត្រាតែអ្នកយកឯកសារភ្ជាប់មួយ ឬច្រើនចេញ។"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"អ្នកអាចផ្ញើវីដេអូតែមួយប៉ុណ្ណោះនៅក្នុងសារមួយ។ សូមយកវីដេអូដែលលើសពីនេះចេញ ហើយព្យាយាមម្តងទៀត។"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"ការផ្ញើសារបានបរាជ័យក្នុងដំណើរការផ្ទុកឯកសារភ្ជាប់។"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"អញ្ចឹង​ផ្ញើ​​តែម្ដង"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"មិនអាចចាប់ផ្តើមការសន្ទនាទេ"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"បានជ្រើស <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-kn/arrays.xml b/res/values-kn/arrays.xml
new file mode 100644
index 0000000..932fec1
--- /dev/null
+++ b/res/values-kn/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ಯಾವುದೇ ವಿಷಯವಿಲ್ಲ"</item>
+    <item msgid="272485471009191934">"ಯಾವುದೇ ವಿಷಯವಿಲ್ಲ"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ಹೌದು"</item>
+    <item msgid="6049132459802288033">"ಬೇಡ"</item>
+    <item msgid="3084376867445867895">"ಸರಿ"</item>
+    <item msgid="3155097332660174689">"ಹೆಹೆ"</item>
+    <item msgid="2611328818571146775">"ಧನ್ಯವಾದಗಳು"</item>
+    <item msgid="4881335087096496747">"ಒಪ್ಪುತ್ತೇನೆ"</item>
+    <item msgid="2422296858597420738">"ಉತ್ತಮ"</item>
+    <item msgid="4805581752819452687">"ನನ್ನ ಹಾದಿಯಲ್ಲಿದ್ದೇನೆ"</item>
+    <item msgid="4746700499431366214">"ಸರಿ, ನಾನು ಮತ್ತೆ ನಿಮಗೆ ತಿಳಿಸುತ್ತೇನೆ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
new file mode 100644
index 0000000..b484009
--- /dev/null
+++ b/res/values-kn/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"ಸಂಭಾಷಣೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"ಸಂದೇಶ ಕಳುಹಿಸು"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ಲಗತ್ತನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"ಸಹಾಯ"</string>
+    <string name="welcome" msgid="2857560951820802321">"ಸುಸ್ವಾಗತ"</string>
+    <string name="skip" msgid="7238879696319945853">"ಸ್ಕಿಪ್‌"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ಮುಂದೆ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"ಮುಂದೆ"</string>
+    <string name="exit" msgid="1905187380359981199">"ನಿರ್ಗಮಿಸು"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಗೆ SMS, ಫೋನ್ ಮತ್ತು ಸಂಪರ್ಕಗಳಿಗೆ ಅನುಮತಿ ಹೊಂದಿರುವ ಅಗತ್ಯವಿದೆ."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ನೀವು ಅನುಮತಿಗಳನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt; ಅಪ್ಲಿಕೇಶನ್‌ಗಳು &gt; ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ &gt; ಅನುಮತಿಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ನೀವು ಅನುಮತಿಗಳನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ, ಅನುಮತಿಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ಪುನರಾವರ್ತನೆಗಳು"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ಎಲ್ಲ ಸಂಪರ್ಕಗಳು"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> ಗೆ ಕಳುಹಿಸಿ"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ಚಿತ್ರಗಳು ಅಥವಾ ವೀಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ಈ ಸಾಧನದಿಂದ ಚಿತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಿ"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ಫೋಟೋ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"ಮಾಧ್ಯಮ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ಮಾಧ್ಯಮ ಆಯ್ಕೆ ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ಚಿತ್ರ <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ಚಿತ್ರ"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಿ"</string>
+    <string name="action_share" msgid="2143483844803153871">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ಈಗ ತಾನೇ"</string>
+    <string name="posted_now" msgid="867560789350406701">"ಇದೀಗ"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ನಿಮಿಷಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ನಿಮಿಷಗಳು</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ಗಂಟೆಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ಗಂಟೆಗಳು</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ದಿನಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ದಿನಗಳು</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ವಾರಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ವಾರಗಳು</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ತಿಂಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ತಿಂಗಳು</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ವರ್ಷಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ವರ್ಷಗಳು</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ವರ್ಗ 0 ಸಂದೇಶ"</string>
+    <string name="save" msgid="5081141452059463572">"ಉಳಿಸು"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ಸಾಧನದಲ್ಲಿ ಸ್ಥಳಾವಕಾಶವು ಕಡಿಮೆ ಇದೆ. ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯು ಸ್ಥಳಾವಕಾಶವನ್ನು ತೆರವುಗೊಳಿಸಲು ಹಳೆಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಅಳಿಸುತ್ತದೆ."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"ಸಂಗ್ರಹಣೆ ಸ್ಥಳವು ತುಂಬಿದೆ"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶ ಲಭ್ಯವಿರುವವರೆಗೆ ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸದಿರಬಹುದು ಅಥವಾ ಸ್ವೀಕರಿಸದಿರಬಹುದು."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ಕಡಿಮೆ SMS ಸಂಗ್ರಹಣೆ. ನೀವು ಸಂದೇಶಗಳನ್ನು ಅಳಿಸಬೇಕಾಗಬಹುದು."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ನಿಮ್ಮ ಫೋನ್ ಸಂಖ್ಯೆಯನ್ನು ಖಚಿತಪಡಿಸಿ"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ಈ ಒಂದು-ಬಾರಿ ಹಂತವು ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯು ನಿಮ್ಮ ಗುಂಪು ಸಂದೇಶಗಳನ್ನು ಸರಿಯಾಗಿ ಕಳುಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ಫೋನ್ ಸಂಖ್ಯೆ"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ಮೀಡಿಯಾದ ಎಲ್ಲಾ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸಿ"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> ಗಿಂತಲೂ ಹಳೆಯದಾದ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸಿ"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> ಗಿಂತಲೂ ಹಳೆಯದಾದ ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂ-ಅಳಿಸಿ"</string>
+    <string name="ignore" msgid="7063392681130898793">"ನಿರ್ಲಕ್ಷಿಸು"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"ಮಾಧ್ಯಮದ ಎಲ್ಲಾ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸುವುದೇ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> ಗಿಂತಲೂ ಹಳೆಯದಾದ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸುವುದೇ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> ಗಿಂತಲೂ ಹಳೆಯದಾದ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸಿ ಹಾಗೂ ಸ್ವಯಂ-ಅಳಿಸು ಆನ್‌ ಮಾಡಿ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ಹೇಳಿದ್ದಾರೆ"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"ನೀವು ಹೇಳಿದ್ದೀರಿ"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"ನೀವು ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಿರುವಿರಿ"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ಕಳುಹಿಸಲಾಗಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ಕಳುಹಿಸಲಾಗಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ಮರುಕಳುಹಿಸಿ ಅಥವಾ ಅಳಿಸಿ"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"ತುರ್ತು ಸೇವೆಗಳಿಗೆ ದಯವಿಟ್ಟು ಧ್ವನಿ ಕರೆಗಳನ್ನು ಮಾಡಿ. ಈ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ಪಠ್ಯ ಸಂದೇಶವನ್ನು ತಲುಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ವಿಫಲವಾಗಿದೆ"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲು ಹೊಸ MMS ಸಂದೇಶ"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"ಹೊಸ MMS ಸಂದೇಶ"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಿ ಇಲ್ಲವೇ ಅಳಿಸಿ"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"ಸಂದೇಶ ಅವಧಿ ಮೀರಿದೆ ಅಥವಾ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ಗಾತ್ರ: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, ಮುಕ್ತಾಯ: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"ಕಳುಹಿಸಲಾಗುವುದಿಲ್ಲ. ಸ್ವೀಕರಿಸುವವರು ಮಾನ್ಯವಾಗಿಲ್ಲ."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಸೇವೆಯು ಸಕ್ರಿಯಗೊಂಡಿಲ್ಲ"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ನೆಟ್‌ವರ್ಕ್‌ ಸಮಸ್ಯೆಯಿಂದಾಗಿ  ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"ಸಂದೇಶ ಅವಧಿ ಮೀರಿದೆ ಅಥವಾ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ವಿಷಯ ಇಲ್ಲ)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ಕಳುಹಿಸಿದವರು ತಿಳಿದಿಲ್ಲ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ತಲುಪಿಸಲಾಗಿದೆ"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> ರಿಂದ <xliff:g id="SUBJECT">%1$s</xliff:g> ಸಂದೇಶವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="low_memory" msgid="5300743415198486619">"ಕಡಿಮೆ ಮೆಮೊರಿಯ ಕಾರಣ ಡೇಟಾಬೇಸ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯಲ್ಲಿ ಕೆಲವು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲಾಗಿಲ್ಲ"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> ಸಂವಾದಗಳಲ್ಲಿ <xliff:g id="MESSAGES_1">%d</xliff:g> ಸಂದೇಶಗಳು</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> ಸಂವಾದಗಳಲ್ಲಿ <xliff:g id="MESSAGES_1">%d</xliff:g> ಸಂದೇಶಗಳು</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"ಸಂದೇಶವನ್ನು ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲಾಗಿಲ್ಲ"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯಲ್ಲಿ ಕೆಲವು ಸಂದೇಶಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> ಸಂವಾದಗಳಲ್ಲಿ <xliff:g id="MESSAGES_1">%d</xliff:g> ಸಂದೇಶಗಳು</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> ಸಂವಾದಗಳಲ್ಲಿ <xliff:g id="MESSAGES_1">%d</xliff:g> ಸಂದೇಶಗಳು</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> ಸಂಖ್ಯೆಗೆ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಿಲ್ಲ"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"ತುರ್ತು ಸೇವೆಗಳಿಗೆ ದಯವಿಟ್ಟು ಧ್ವನಿ ಕರೆಗಳನ್ನು ಮಾಡಿ. ಈ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ಪಠ್ಯ ಸಂದೇಶವನ್ನು <xliff:g id="NUMBER">%1$s</xliff:g>  ಸಂಖ್ಯೆಗೆ ತಲುಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> ಹೊಸ ಸಂದೇಶಗಳು</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ಹೊಸ ಸಂದೇಶಗಳು</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ಪ್ರಾರಂಭಿಸು"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ಕ್ಯಾಮರಾ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ಕ್ಯಾಮರಾ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ವಿಡಿಯೋ ಸೆರೆಹಿಡಿಯುವಿಕೆ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"ಮಾಧ್ಯಮ ಉಳಿಸಲಾಗಲಿಲ್ಲ"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="back" msgid="1477626055115561645">"ಹಿಂದೆ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ಅಳಿಸಿ"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ಆರ್ಕೈವ್ ಮಾಡಿ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ಅನ್‌ಆರ್ಕೈವ್ ಮಾಡು"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡು"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"ಸಂಪರ್ಕ ಸೇರಿಸು"</string>
+    <string name="action_download" msgid="7786338136368564146">"ಡೌನ್‌ಲೋಡ್‌"</string>
+    <string name="action_send" msgid="377635240181672039">"ಕಳುಹಿಸು"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ಅಳಿಸಿ"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ಈ ಸಂದೇಶವನ್ನು ಅಳಿಸುವುದೇ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ಈ ಕ್ರಿಯೆಯನ್ನು ರದ್ದುಪಡಿಸಲಾಗುವುದಿಲ್ಲ"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ಅಳಿಸಿ"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">ಈ ಸಂವಾದಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
+      <item quantity="other">ಈ ಸಂವಾದಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ಅಳಿಸಿ"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ರದ್ದುಮಾಡು"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ಇವರಿಗೆ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"ಬಹು ಚಿತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ಆಯ್ಕೆ ಖಚಿತಪಡಿಸಿ"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ಆಡಿಯೋವನ್ನು ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ಆಡಿಯೋವನ್ನು ಉಳಿಸಲಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ಸ್ಪರ್ಶಿಸಿ &amp; ಹೋಲ್ಡ್‌ ಮಾಡಿ"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ಚಿತ್ರ"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ಆಡಿಯೊ ಕ್ಲಿಪ್"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ವೀಡಿಯೊ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"ಸಂಪರ್ಕದ ಕಾರ್ಡ್"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ಡೌನ್‌ಲೋಡ್‌"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ಮೂಲಕ ಪ್ರತ್ಯುತ್ತರಿಸಿ"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS ಮೂಲಕ ಪ್ರತ್ಯುತ್ತರಿಸಿ"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ಪ್ರತ್ಯುತ್ತರಿಸು"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ಪಾಲ್ಗೊಳ್ಳುವವರು</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ಪಾಲ್ಗೊಳ್ಳುವವರು</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ನಾನು"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"ಸಂಪರ್ಕವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ &amp; ಆರ್ಕೈವ್‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"ಸಂಪರ್ಕವನ್ನು ಅನಿರ್ಬಂಧಿಸಲಾಗಿದೆ &amp; ಆರ್ಕೈವ್ ರದ್ದುಮಾಡಲಾಗಿದೆ"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ಆರ್ಕೈವ್‌‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ಅನ್‌ಆರ್ಕೈವ್‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"ಎಲ್ಲವನ್ನೂ ಹೊಂದಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಕಳುಹಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಹೊಂದಿಸಲಾಗಿದೆ."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">ಲಗತ್ತುಗಳನ್ನು ತಿರಸ್ಕರಿಸು</item>
+      <item quantity="other">ಲಗತ್ತುಗಳನ್ನು ತಿರಸ್ಕರಿಸು</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ಆಡಿಯೋ ಲಗತ್ತು"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ಆಡಿಯೊ ಲಗತ್ತನ್ನು ಪ್ಲೇ ಮಾಡಿ"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ವಿರಾಮಗೊಳಿಸು"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ ವಿಫಲವಾಗಿದೆ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> ಗೆ ಕಳುಹಿಸದಿರುವ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> ಗೆ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> ಗೆ ಸಂದೇಶ ವಿಫಲವಾಗಿದೆ : <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> ಗೆ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ ವಿಫಲವಾಗಿದೆ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> ಅವರಿಂದ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> ಗೆ ಕಳುಹಿಸದಿರುವ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> ಗೆ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> ಗೆ ಸಂದೇಶ ವಿಫಲವಾಗಿದೆ : <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> ಗೆ ಸಂದೇಶ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ಸಮಯ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ಸಂದೇಶ ವಿಫಲವಾಗಿದೆ. ಮರುಪ್ರಯತ್ನಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> ಅವರೊಂದಿಗೆ ಸಂಭಾಷಣೆ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"ವಿಷಯವನ್ನು ಅಳಿಸಿ"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ವೀಡಿಯೊ ಸೆರೆಹಿಡಿಯಿರಿ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ಸ್ಥಿರ ಚಿತ್ರವನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ಫೋಟೋ ತೆಗೆಯಿರಿ"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ವೀಡಿಯೊ ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"ಪೂರ್ಣ ಪರದೆ ಕ್ಯಾಮರಾಗೆ ಬದಲಿಸಿ"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ಮುಂದಿನ ಮತ್ತು ಹಿಂದಿನ ಕ್ಯಾಮರಾ ನಡುವೆ ಬದಲಾಯಿಸಿ"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸಿ ಮತ್ತು ವೀಡಿಯೊ ಲಗತ್ತಿಸಿ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ವೀಡಿಯೊ ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸಿ"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"ಫೋಟೋಗಳ ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ಫೋಟೋಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ಫೋಟೋಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ವೀಡಿಯೊಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ವೀಡಿಯೊಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+      <item quantity="other">\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ಆಲ್ಬಮ್‌ಗೆ <xliff:g id="QUANTITY_2">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one">\"ಡೌನ್‌ಲೋಡ್‌ಗಳಿಗೆ\" <xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+      <item quantity="other">\"ಡೌನ್‌ಲೋಡ್‌ಗಳಿಗೆ\" <xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ಲಗತ್ತುಗಳನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS ಲಗತ್ತನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="action_close" msgid="1840519376200478419">"ಮುಚ್ಚು"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"ಸುಧಾರಿತ"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ಡೀಬಗ್ ಮಾಡು"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"ಅಧಿಸೂಚನೆಗಳು"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ಶಬ್ದ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"ಶಾಂತ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ವೈಬ್ರೇಟ್‌‌"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS ವಿತರಣಾ ವರದಿಗಳು"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ನೀವು ಕಳುಹಿಸುವ ಪ್ರತಿ SMS ಗೂ ವಿತರಣೆ ವರದಿಯನ್ನು ವಿನಂತಿಸಿ"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"ಸ್ವಯಂ-ಹಿಂಪಡೆಯುವಿಕೆ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಹಿಂಪಡೆದುಕೊಳ್ಳಿ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ರೋಮಿಂಗ್‌‌ನಲ್ಲಿರುವಾಗ ಸ್ವಯಂ-ಹಿಂಪಡೆಯುವಿಕೆ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ರೋಮಿಂಗ್‌ನಲ್ಲಿರುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ MMS ಹಿಂಪಡೆಯಿರಿ"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ಗುಂಪು ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ಅನೇಕ ಸ್ವೀಕೃತದಾರರು ಇರುವಾಗ ಒಂದೇ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು MMS ಬಳಸಿ"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"ನಿಮ್ಮ ಫೋನ್‌ ಸಂಖ್ಯೆ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"ಅಪರಿಚಿತ"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"ಹೊರಹೋಗುವ ಸಂದೇಶಕ್ಕೆ ಧ್ವನಿಗಳು"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"ಡಂಪ್ SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ ಫೈಲ್‌ಗೆ SMS ಕಚ್ಛಾ ಡೇಟಾವನ್ನು ಡಂಪ್ ಸ್ವೀಕರಿಸಿದೆ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"ಡಂಪ್ MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ ಫೈಲ್‌ಗೆ MMS ಕಚ್ಛಾ ಡೇಟಾವನ್ನು ಡಂಪ್ ಸ್ವೀಕರಿಸಿದೆ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ವೈರ್‌ಲೆಸ್ ಎಚ್ಚರಿಕೆಗಳು"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"ಸಂದೇಶ ಆಯ್ಕೆಗಳು"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ಪಠ್ಯ ನಕಲಿಸು"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"ವಿವರಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ಅಳಿಸಿ"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ಫಾರ್ವರ್ಡ್ ಮಾಡು"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"ಸಂದೇಶ ವಿವರಗಳು"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ಪ್ರಕಾರ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ಪಠ್ಯ ಸಂದೇಶ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ಮಲ್ಟಿಮೀಡಿಯಾ ಸಂದೇಶ"</string>
+    <string name="from_label" msgid="1947831848146564875">"ಇಂದ: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ಗೆ: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ಕಳುಹಿಸಿದ್ದು: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ಸ್ವೀಕರಿಸಿದ್ದು: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"ವಿಷಯ: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ಗಾತ್ರ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ಆದ್ಯತೆ: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"ಅಧಿಕ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ಸಾಮಾನ್ಯ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"ಕಡಿಮೆ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"ಮರೆಮಾಡಲಾಗಿರುವ ಕಳುಹಿಸುವವರ ವಿಳಾಸ"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"ಲಗತ್ತುಗಳನ್ನು ಲೋಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ಲಗತ್ತನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ನೆಟ್‌ವರ್ಕ್ ಸಿದ್ಧವಾಗಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ಪಠ್ಯ ಅಳಿಸಿ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ಪಠ್ಯ ಮತ್ತು ಸಂಖ್ಯೆಗಳ ನಡುವೆ ನಮೂದಿಸುವುದನ್ನು ಬದಲಾಯಿಸಿ"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"ಇನ್ನಷ್ಟು ಪಾಲ್ಗೊಳ್ಳುವವರನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ಭಾಗವಹಿಸುವವರನ್ನು ಖಚಿತಪಡಿಸಿ"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"ಹೊಸ ಸಂವಾದವನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ಈ ಐಟಂ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ವೀಡಿಯೊ ಪ್ಲೇ ಮಾಡಿ"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ಜನರು &amp; ಆಯ್ಕೆಗಳು"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ಡೀಬಗ್ ಮಾಡು"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ಜನರು &amp; ಆಯ್ಕೆಗಳು"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ಸಾಮಾನ್ಯ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ಈ ಸಂವಾದದಲ್ಲಿರುವ ಜನರು"</string>
+    <string name="action_call" msgid="6596167921517350362">"ಕರೆ ಮಾಡಿ"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ಸಂದೇಶ ಕಳುಹಿಸಿ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; ನಿಂದ ಸಂದೇಶ ಕಳುಹಿಸಿ"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ಫೋಟೋಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+      <item quantity="other">ಫೋಟೋಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ಆಡಿಯೋಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+      <item quantity="other">ಆಡಿಯೋಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">ವೀಡಿಯೊಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+      <item quantity="other">ವೀಡಿಯೊಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">ಸಂಪರ್ಕ ಕಾರ್ಡ್‍ಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+      <item quantity="other">ಸಂಪರ್ಕ ಕಾರ್ಡ್‍ಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">ಲಗತ್ತುಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+      <item quantity="other">ಲಗತ್ತುಗಳನ್ನು ಕಳುಹಿಸಿ</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ಕಳುಹಿಸಲು ಲಗತ್ತುಗಳು ಸಿದ್ಧವಾಗಿವೆ</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ಕಳುಹಿಸಲು ಲಗತ್ತುಗಳು ಸಿದ್ಧವಾಗಿವೆ</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ಆವೃತ್ತಿ ಮಾಹಿತಿ"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ಆವೃತ್ತಿ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ಮುಕ್ತ ಮೂಲ ಪರವಾನಗಿಗಳು"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"ಅಧಿಸೂಚನೆಗಳು"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ಲಗತ್ತು ಮಿತಿಯನ್ನು ತಲುಪಿದೆ"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ಲಗತ್ತನ್ನು ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"ಸಂಪರ್ಕಗಳಿಗೆ ಸೇರಿಸುವುದೇ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"ಸಂಪರ್ಕ ಸೇರಿಸು"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ವಿಷಯ"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"ವಿಷಯ: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"ಸಂಪರ್ಕ ಕಾರ್ಡ್‌ ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"ಸಂಪರ್ಕ ಕಾರ್ಡ್ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"ಸಂಪರ್ಕ ಕಾರ್ಡ್ ವೀಕ್ಷಿಸಿ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ಸಂಪರ್ಕಗಳು</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ಸಂಪರ್ಕಗಳು</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"ಸಂಪರ್ಕ ಕಾರ್ಡ್‌ಗಳು"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"ಜನ್ಮದಿನ"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ಟಿಪ್ಪಣಿಗಳು"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"ಸಂದೇಶವನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡು"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ಪ್ರತ್ಯುತ್ತರ ನೀಡು"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ಕಳುಹಿಸಲು, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಹೊಂದಿಸಿ"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಹೊಂದಿಸಿ"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ಬದಲಾಯಿಸು"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಡೀಫಾಲ್ಟ್ SMS ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಹೊಂದಿಸಿ"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಯಾವುದೇ ಪ್ರಾಶಸ್ತ್ಯದ ಸಿಮ್ ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ಸಾಧನದ ಮಾಲೀಕರಿಂದ ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ಸರಿ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"ಸಂವಾದದಲ್ಲಿ ಹಲವಾರು ಸಹಭಾಗಿಗಳಿದ್ದಾರೆ"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">ಅಮಾನ್ಯ ಸಂಪರ್ಕಗಳು</item>
+      <item quantity="other">ಅಮಾನ್ಯ ಸಂಪರ್ಕಗಳು</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ಕ್ಯಾಮರಾ ಚಿತ್ರವನ್ನು ಲೋಡ್ ಮಾಡಲಾಗಲಿಲ್ಲ"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"ನೀವು: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ಡ್ರಾಫ್ಟ್‌"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"ನೀವು ಒಮ್ಮೆ ಹೊಸ ಸಂವಾದ ಪ್ರಾರಂಭಿಸಿದರೆ, ಅದು ಇಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಲಾಗಿರುವುದನ್ನು ನೋಡುತ್ತೀರಿ"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ಆರ್ಕೈವ್‌ ಮಾಡಲಾದ ಸಂವಾದಗಳು ಇಲ್ಲಿ ಗೋಚರಿಸುತ್ತವೆ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"ಸಂವಾದಗಳನ್ನು ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ಚಿತ್ರ"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ಆಡಿಯೊ ಕ್ಲಿಪ್"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ವೀಡಿಯೊ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"ಸಂಪರ್ಕದ ಕಾರ್ಡ್"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"ರದ್ದುಮಾಡು"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ಮರುಪ್ರಯತ್ನಿಸು"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ಹೊಸ ಸಂದೇಶವನ್ನು ಪ್ರಾರಂಭಿಸಲು ಸಂಪರ್ಕ ಹೆಸರು ಅಥವಾ ಫೊನ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ"</string>
+    <string name="action_block" msgid="9032076625645190136">"ನಿರ್ಬಂಧಿಸು"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> ಅನಿರ್ಬಂಧಿಸು"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> ನಿರ್ಬಂಧಿಸುವುದೇ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ಈ ಸಂಖ್ಯೆಯಿಂದ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಮುಂದುವರೆಸುತ್ತೀರಿ ಆದರೆ ಇನ್ನು ಮುಂದೆ ಸೂಚನೆ ನೀಡುವುದಿಲ್ಲ. ಈ ಸಂವಾದವನ್ನು ಆರ್ಕೈವ್‌ ಮಾಡಲಾಗುವುದು."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಪರ್ಕಗಳು"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ಅನಿರ್ಬಂಧಿಸು"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಪರ್ಕಗಳು"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ಡಾಕ್ಯುಮೆಂಟ್ ಲೈಬ್ರರಿಯಿಂದ ಚಿತ್ರವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="sending_message" msgid="6363584950085384929">"ಸಂದೇಶ ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿದೆ"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ಆಫ್ ಮಾಡಲಾಗಿದೆ. ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರೀಕ್ಷಿಸಿ."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"ಸಂದೇಶಗಳನ್ನು ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್‌ನಲ್ಲಿ ಕಳುಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"ಸಂದೇಶ ಕಳುಸಲು ಆಗುತ್ತಿಲ್ಲ"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"ಸಂದೇಶ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ಆಫ್ ಮಾಡಲಾಗಿದೆ. ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರೀಕ್ಷಿಸಿ."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್‌ನಲ್ಲಿ ಸಂದೇಶಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"ಸಂದೇಶವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"ಶೂನ್ಯ"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ಒಂದು"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"ಎರಡು"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"ಮೂರು"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"ನಾಲ್ಕು"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ಐದು"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ಆರು"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ಏಳು"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ಎಂಟು"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ಒಂದತ್ತು"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> ಮೂಲಕ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ, ದೋಷ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"ಅಜ್ಞಾತ ವಾಹಕದ ಮೂಲಕ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ದೋಷ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ಫಾರ್ವರ್ಡ್‌: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ: ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಸೇವೆಯು ಸಕ್ರಿಯಗೊಂಡಿಲ್ಲ"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ: ಅಮಾನ್ಯವಾದ ಗಮ್ಯಸ್ಥಾನ ವಿಳಾಸ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ: ಅಮಾನ್ಯವಾದ ಸಂದೇಶ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ: ಬೆಂಬಲವಿಲ್ಲದ ವಿಷಯ"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ: ಬೆಂಬಲವಿಲ್ಲದ ಸಂದೇಶ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲಾಗಿಲ್ಲ: ತುಂಬಾ ದೊಡ್ಡದಾಗಿದೆ"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"ಹೊಸ ಸಂದೇಶ"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ವೀಕ್ಷಿಸಿ"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ಚಿತ್ರ"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"ಸೂಕ್ತವಾದ ಅಪ್ಲಿಕೇಶನ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"ಸ್ವೀಕೃತಿದಾರರನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"ಹೊಸ ಸಂದೇಶ"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ರದ್ದುಮಾಡು"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ಪ್ರವೇಶ ಬಿಂದು ಸಂಪಾದನೆ"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"ಹೊಂದಿಸಿಲ್ಲ"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ಹೆಸರು"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ಪ್ರಾಕ್ಸಿ"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS ಪೋರ್ಟ್"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN ಪ್ರಕಾರ"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN ಅಳಿಸು"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"ಹೊಸ APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"ಉಳಿಸು"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ತಿರಸ್ಕರಿಸು"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"ಹೆಸರಿನ ಕ್ಷೇತ್ರವು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ಖಾಲಿ ಇರುವಂತಿಲ್ಲ."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ಕ್ಷೇತ್ರವು 3 ಅಂಕಿಗಳಾಗಿರಬೇಕು."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ಕ್ಷೇತ್ರವು 2 ಅಥವಾ 3 ಅಂಕಿಗಳಾಗಿರಬೇಕು."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ಡೀಫಾಲ್ಟ್ APN ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ಡೀಫಾಲ್ಟ್‌ಗೆ  ಮರುಹೊಂದಿಸು"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"ಡೀಫಾಲ್ಟ್ APN ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮರುಹೊಂದಿಕೆಯು ಪೂರ್ಣಗೊಂಡಿದೆ."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ಶೀರ್ಷಿಕೆರಹಿತ"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ಪ್ರವೇಶಿಸುವಿಕೆ ಕೇಂದ್ರದ ಹೆಸರುಗಳು"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN ಗಳು"</string>
+    <string name="menu_new" msgid="8286285392706532511">"ಹೊಸ APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ಪ್ರವೇಶ ಬಿಂದು ಹೆಸರಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಈ ಬಳಕೆದಾರರಿಗೆ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸುವುದೇ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ನಕಲಿಸು"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> ಗೆ"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ಸಾಮಾನ್ಯ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"ಸುಧಾರಿತ"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"ಸಾಮಾನ್ಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"ಸುಧಾರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" ಸಿಮ್‌"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ಎಲ್ಲಾ ಸ್ವೀಕೃತದಾರರಿಗೆ ಪ್ರತ್ಯೇಕ SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಿ. ಯಾವುದೇ ಪ್ರತ್ಯುತ್ತರಗಳು ನಿಮಗೆ ಮಾತ್ರ ಬರುತ್ತವೆ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ಎಲ್ಲಾ ಸ್ವೀಕೃತಿದಾರರಿಗೆ ಒಂದೇ MMS ಕಳುಹಿಸಿ"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"ಅಜ್ಞಾತ ಸಂಖ್ಯೆ"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"ಹೊಸ ಸಂದೇಶ"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"ಹೊಸ ಸಂದೇಶ."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"ಸಿಮ್ ಆಯ್ಕೆದಾರ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ, ಸಿಮ್ ಆಯ್ಕೆ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ವಿಷಯವನ್ನು ಸಂಪಾದಿಸಿ"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"ಸಿಮ್ ಆಯ್ಕೆ ಮಾಡಿ ಅಥವಾ ವಿಷಯ ಸಂಪಾದಿಸಿ"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ಆಡಿಯೋ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"ಹೊಸ ಸಂವಾದವನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ ಪಟ್ಟಿ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"ಹೊಸ ಸಂದೇಶ"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"ಸಂವಾದ ಪಟ್ಟಿ"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"ಸಂವಾದಗಳನ್ನು ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"ಸಂದೇಶಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"ಇನ್ನಷ್ಟು ಸಂವಾದಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"ಹೆಚ್ಚಿನ ಸಂದೇಶಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"ಸಂವಾದವನ್ನು ಅಳಿಸಲಾಗಿದೆ"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ಸಂಭಾಷಣೆಯನ್ನು ಅಳಿಸಲಾಗಿದೆ. ಬೇರೆ ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ ಸಂಭಾಷಣೆಯನ್ನು ತೋರಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"ಅನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="db_full" msgid="8459265782521418031">"ಸಂಗ್ರಹಣೆ ಸ್ಥಳಾವಕಾಶವು ಕಡಿಮೆ ಇದೆ. ಕೆಲವು ಡೇಟಾ ನಷ್ಟವಾಗಬಹುದು."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ಲಗತ್ತುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ಆಯ್ಕೆ ಖಚಿತಪಡಿಸಿ"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ದಯವಿಟ್ಟು ಒಂದು ಅಥವಾ ಒಂದಕ್ಕಿಂತ ಹೆಚ್ಚಿನ ಲಗತ್ತುಗಳನ್ನು ತೆಗೆದುಹಾಕಿ ಮತ್ತು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"ನಿಮ್ಮ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ನೀವು ಪ್ರಯತ್ನಿಸಬಹುದು, ಆದರೆ ನೀವು ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಲಗತ್ತುಗಳನ್ನು ತೆಗೆದುಹಾಕದ ಹೊರತು ಇದು ತಲುಪದಿರಬಹುದು."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ನೀವು ಪ್ರತಿ ಸಂದೇಶಕ್ಕೆ ಒಂದು ವೀಡಿಯೊ ಮಾತ್ರ ಕಳುಹಿಸಬಹುದು. ದಯವಿಟ್ಟು ಹೆಚ್ಚುವರಿ ವೀಡಿಯೊಗಳನ್ನು ತೆಗೆದುಹಾಕಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆಯು ಲಗತ್ತನ್ನು ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ಹೇಗಾದರೂ ಕಳುಹಿಸು"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"ಸಂವಾದವನ್ನು ಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
+</resources>
diff --git a/res/values-ko/arrays.xml b/res/values-ko/arrays.xml
new file mode 100644
index 0000000..876776b
--- /dev/null
+++ b/res/values-ko/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"제목 없음"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"예"</item>
+    <item msgid="6049132459802288033">"아니요"</item>
+    <item msgid="3084376867445867895">"알겠습니다"</item>
+    <item msgid="3155097332660174689">"하하"</item>
+    <item msgid="2611328818571146775">"감사합니다."</item>
+    <item msgid="4881335087096496747">"동의합니다"</item>
+    <item msgid="2422296858597420738">"좋습니다."</item>
+    <item msgid="4805581752819452687">"가는 중입니다"</item>
+    <item msgid="4746700499431366214">"나중에 연락드리겠습니다"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
new file mode 100644
index 0000000..1faec2a
--- /dev/null
+++ b/res/values-ko/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"메시지"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"메시지"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"대화 선택"</string>
+    <string name="action_settings" msgid="1329008122345201684">"설정"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"메시지 보내기"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"첨부파일 추가"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"도움말"</string>
+    <string name="welcome" msgid="2857560951820802321">"환영합니다."</string>
+    <string name="skip" msgid="7238879696319945853">"건너뛰기"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"다음 &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"다음"</string>
+    <string name="exit" msgid="1905187380359981199">"종료"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"설정 &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"설정"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"메시지를 사용하려면 SMS, 전화, 주소록에 대한 권한이 필요합니다."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"설정 &gt; 앱 &gt; 메시지 &gt; 권한에서 권한을 변경할 수 있습니다."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"설정, 앱, 메시지, 권한에서 권한을 변경할 수 있습니다."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"자주 연락하는 사람"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"모든 연락처"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"받는사람: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"사진 또는 동영상 캡처"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"이 기기에서 이미지 선택"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"오디오 녹음"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"사진 선택"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"미디어가 선택되었습니다."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"미디어가 선택 취소되었습니다."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g>개 선택됨"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"이미지 - <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"이미지"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"오디오 녹음"</string>
+    <string name="action_share" msgid="2143483844803153871">"공유"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"방금 전"</string>
+    <string name="posted_now" msgid="867560789350406701">"지금"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>분</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>분</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>시간</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>시간</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>일</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>일</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>주</item>
+      <item quantity="one">1주</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>개월</item>
+      <item quantity="one">1개월</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>년</item>
+      <item quantity="one">1년</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"클래스 0 메시지"</string>
+    <string name="save" msgid="5081141452059463572">"저장"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"기기의 저장공간이 부족합니다. 메시지에서 공간을 확보하기 위해 오래된 메시지를 삭제합니다."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"저장 공간이 부족함"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"기기 공간이 더 확보되어야 메시지 앱에서 메시지를 보내고 받을 수 있습니다."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS 저장공간이 부족합니다. 메시지를 삭제해야 합니다."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"전화번호 확인"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"이 단계를 한 번만 실행하면 메시지 앱에서 그룹 메시지를 정확히 전달할 수 있습니다."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"전화번호"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"미디어가 포함된 모든 메시지 삭제"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g>보다 오래된 메시지 삭제"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> 이상 된 메시지 자동 삭제"</string>
+    <string name="ignore" msgid="7063392681130898793">"무시"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"미디어가 포함된 모든 메시지를 삭제하시겠습니까?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> 이상 된 메시지를 삭제하시겠습니까?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> 이상 된 메시지를 삭제하고 자동 삭제를 사용하시겠습니까?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>님이 보낸 내용"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"보낸 내용"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g>님이 보낸 메시지"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"메시지 전송됨"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"보내는 중..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"전송되지 않았습니다. 다시 시도하려면 터치하세요."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"전송되지 않았습니다. 다시 시도하는 중…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"다시 보내기 또는 삭제"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"음성 통화로 응급 서비스에 연락하시기 바랍니다. 현재 SMS를 보낼 수 없습니다."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"실패"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"다운로드할 새 MMS 메시지"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"새 MMS 메시지"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"다운로드하지 못했습니다."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"다시 시도하려면 터치"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"터치하여 다운로드"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"다운로드 또는 삭제"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"다운로드 중..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"메시지가 만료되었거나 사용할 수 없음"</string>
+    <string name="mms_info" msgid="3402311750134118165">"크기: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, 만료: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"보낼 수 없습니다. 수신자가 올바르지 않습니다."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"네트워크에 서비스가 활성화되어 있지 않습니다."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"네트워크 문제로 인해 전송하지 못했습니다."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"메시지가 만료되었거나 사용할 수 없음"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(제목 없음)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"알 수 없는 발신자"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"전송 완료"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g>님이 보낸 메시지(<xliff:g id="SUBJECT">%1$s</xliff:g>)를 다운로드할 수 없습니다."</string>
+    <string name="low_memory" msgid="5300743415198486619">"메모리가 부족하여 데이터베이스 작업을 완료할 수 없습니다."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"메시지를 보내지 못함"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"일부 메시지가 전송되지 않았습니다."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other">대화 <xliff:g id="CONVERSATIONS">%d</xliff:g>개에 메시지 <xliff:g id="MESSAGES_1">%d</xliff:g>개</item>
+      <item quantity="one">대화 1개에 메시지 <xliff:g id="MESSAGES_0">%d</xliff:g>개</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"메시지를 다운로드하지 못했습니다."</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"일부 메시지가 다운로드되지 않았습니다."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other">대화 <xliff:g id="CONVERSATIONS">%d</xliff:g>개에 메시지 <xliff:g id="MESSAGES_1">%d</xliff:g>개</item>
+      <item quantity="one">대화 1개에 메시지 <xliff:g id="MESSAGES_0">%d</xliff:g>개</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g>에 메시지를 보내지 못했습니다."</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"음성 통화로 응급 서비스에 연락하시기 바랍니다. 현재 <xliff:g id="NUMBER">%1$s</xliff:g>번으로 SMS를 보낼 수 없습니다."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other">새 메시지 <xliff:g id="MESSAGES">%d</xliff:g>개</item>
+      <item quantity="one">새 메시지 1개</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"시작"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"카메라를 사용할 수 없습니다."</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"카메라를 사용할 수 없습니다."</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"동영상을 캡처할 수 없습니다."</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"미디어를 저장할 수 없습니다."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"사진을 찍을 수 없음"</string>
+    <string name="back" msgid="1477626055115561645">"뒤로"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"보관처리됨"</string>
+    <string name="action_delete" msgid="4076795795307486019">"삭제"</string>
+    <string name="action_archive" msgid="5437034800324083170">"보관처리"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"보관 취소"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"알림 사용 중지"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"알림 사용"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"연락처 추가"</string>
+    <string name="action_download" msgid="7786338136368564146">"다운로드"</string>
+    <string name="action_send" msgid="377635240181672039">"전송"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"삭제"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"이 메일을 삭제하시겠습니까?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"이 작업은 취소할 수 없습니다."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"삭제"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">대화를 삭제하시겠습니까?</item>
+      <item quantity="one">대화를 삭제하시겠습니까?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"삭제"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"취소"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"받는사람"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"여러 이미지 선택"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"선택항목 확인"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"오디오를 녹음할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"오디오를 재생할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"오디오를 저장할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"길게 터치"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"사진"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"오디오 클립"</string>
+    <string name="notification_video" msgid="4331423498662606204">"동영상"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"연락처 카드"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"다운로드"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS를 통해 답장"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS로 답장"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"답장"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other">참여자 <xliff:g id="COUNT_1">%d</xliff:g>명</item>
+      <item quantity="one">참여자 <xliff:g id="COUNT_0">%d</xliff:g>명</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"나"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"연락처가 차단 및 보관되었습니다."</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"연락처 차단 해제 및 보관 취소됨"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g>개 보관됨"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g>개 보관 취소됨"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"알림 사용 중지됨"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"알림 사용 설정됨"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"준비가 완료되었습니다. 전송을 다시 터치해 주세요."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"메시지가 기본 SMS 앱으로 설정되었습니다."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">첨부파일 삭제</item>
+      <item quantity="one">첨부파일 삭제</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"오디오 첨부파일"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"오디오 첨부파일 재생"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"일시중지"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g>님의 메시지입니다. <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"받지 못한 <xliff:g id="SENDER">%1$s</xliff:g>님의 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>님의 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>님에게 전송되지 않은 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>님에게 전송 중인 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>님에게 전송하지 못한 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>님에게 보내는 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"받지 못한 <xliff:g id="SENDER">%1$s</xliff:g>님의 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>님의 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> 그룹에 전송되지 않은 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> 그룹에 전송 중인 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> 그룹에 전송하지 못한 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> 그룹에 보내는 메시지: <xliff:g id="MESSAGE">%2$s</xliff:g>. 시간: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"메시지를 전달하지 못했습니다. 다시 시도하려면 터치하세요."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g>님과 대화"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"제목 삭제"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"동영상 촬영"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"정지 이미지 캡처"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"사진 촬영"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"동영상 녹화 시작"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"전체화면 카메라로 전환"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"전면 및 후면 카메라 전환"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"녹화 중지 및 비디오 첨부"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"동영상 녹화 중지"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"메시지 사진"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">사진 <xliff:g id="QUANTITY_2">%d</xliff:g>장이 \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" 앨범에 저장됨</item>
+      <item quantity="one">사진 <xliff:g id="QUANTITY_0">%d</xliff:g>장이 \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" 앨범에 저장됨</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">동영상 <xliff:g id="QUANTITY_2">%d</xliff:g>개가 \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" 앨범에 저장됨</item>
+      <item quantity="one">동영상 <xliff:g id="QUANTITY_0">%d</xliff:g>개가 \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" 앨범에 저장됨</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">첨부파일 <xliff:g id="QUANTITY_2">%d</xliff:g>개가 \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" 앨범에 저장됨</item>
+      <item quantity="one">첨부파일 <xliff:g id="QUANTITY_0">%d</xliff:g>개가 \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" 앨범에 저장됨</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">첨부파일 <xliff:g id="QUANTITY_1">%d</xliff:g>개가 \"다운로드\"에 저장됨</item>
+      <item quantity="one">첨부파일 <xliff:g id="QUANTITY_0">%d</xliff:g>개가 \"다운로드\"에 저장됨</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">첨부파일 <xliff:g id="QUANTITY_1">%d</xliff:g>개가 첨부되었습니다.</item>
+      <item quantity="one">첨부파일 <xliff:g id="QUANTITY_0">%d</xliff:g>개가 저장되었습니다.</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">첨부파일 <xliff:g id="QUANTITY_1">%d</xliff:g>개를 저장하지 못했습니다.</item>
+      <item quantity="one">첨부파일 <xliff:g id="QUANTITY_0">%d</xliff:g>개를 저장하지 못했습니다.</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"저장된 MMS 첨부파일"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"설정"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"보관처리됨"</string>
+    <string name="action_close" msgid="1840519376200478419">"닫기"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"고급"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"디버그"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"알림"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"소리"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"무음"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"진동"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"차단됨"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS 전송 보고"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"모든 SMS에 대해 전송 확인 요청"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"자동 검색"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS 메시지를 자동으로 수신"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"로밍 중 자동 수신"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"로밍 시 MMS 자동 검색"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"그룹 메시지"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"수신자가 여러 명일 때 MMS를 사용하여 한 개의 메시지를 전송합니다."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"기본 SMS 앱"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"기본 SMS 앱"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"전화번호"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"알 수 없음"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"발신 메시지 소리"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS 덤프"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"수신된 SMS 원시 데이터를 외부 저장소 파일에 덤프합니다."</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS 덤프"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"수신된 MSS 원시 데이터를 외부 저장소 파일에 덤프합니다."</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"긴급 무선 경보"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"메시지 옵션"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"텍스트 복사"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"세부정보 보기"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"삭제"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"전달"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"메시지 세부정보"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"유형: "</string>
+    <string name="text_message" msgid="7415419755252205721">"문자 메시지"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"멀티미디어 메시지"</string>
+    <string name="from_label" msgid="1947831848146564875">"보낸사람: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"받는사람: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"보낸 시간: "</string>
+    <string name="received_label" msgid="4442494712757995203">"받은 시간: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"제목: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"크기: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"중요도: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"높음"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"보통"</string>
+    <string name="priority_low" msgid="7398724779026801851">"낮음"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"숨긴 발신자 주소"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"파일을 로드하는 동안 메시지를 보낼 수 없습니다."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"첨부파일을 로드할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"네트워크가 준비되지 않았습니다. 다시 시도해 주세요."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"텍스트 삭제"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"텍스트 및 숫자 입력 간 전환"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"더 많은 참가자 추가"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"참가자 확인"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"새로운 대화 시작"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"이 항목을 선택합니다."</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Play 동영상"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"사용자 및 옵션"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"디버그"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"사용자 및 옵션"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"일반"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"이 대화에 참여하는 사용자"</string>
+    <string name="action_call" msgid="6596167921517350362">"전화 걸기"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"메시지 보내기"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;에서 메시지 보내기"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">사진 전송</item>
+      <item quantity="one">사진 전송</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">오디오 전송</item>
+      <item quantity="one">오디오 전송</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">동영상 전송</item>
+      <item quantity="one">동영상 전송</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">연락처 카드 전송</item>
+      <item quantity="one">연락처 카드 전송</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">첨부파일 전송</item>
+      <item quantity="one">첨부파일 전송</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">첨부파일 <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>개 전송 준비 완료</item>
+      <item quantity="one">첨부파일 1개 전송 준비 완료</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"의견 보내기"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play 스토어에서 보기"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"버전 정보"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"버전: %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"오픈소스 라이선스"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"알림"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"첨부파일 한도 도달"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"첨부파일을 로드하지 못했습니다."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"주소록에 추가하시겠습니까?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"연락처 추가"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"제목"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"제목: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"연락처 카드 로드 중"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"연락처 카드를 로드할 수 없습니다."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"연락처 카드 보기"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other">연락처 <xliff:g id="COUNT_1">%d</xliff:g>개</item>
+      <item quantity="one">연락처 <xliff:g id="COUNT_0">%d</xliff:g>개</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"연락처 카드"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"생일"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"메모"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"메시지 전달"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"답장"</string>
+    <string name="plus_one" msgid="9010288417554932581">"외 1명"</string>
+    <string name="plus_n" msgid="8961547034116059566">"외 %d명"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS 사용 중지됨"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"메시지를 전송하려면 메시지를 기본 SMS 앱으로 설정하세요."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"메시지를 기본 SMS 앱으로 설정하세요."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"변경"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"메시지를 수신하려면 메시지를 기본 SMS 앱으로 설정하세요."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS 메시지 보내기에 사용할 기본 앱이 선택되어 있지 않습니다."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"기기 소유자가 허용하지 않은 앱입니다."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"확인"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"대화 참가자가 너무 많습니다."</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">잘못된 연락처</item>
+      <item quantity="one">잘못된 연락처</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"카메라 이미지를 로드할 수 없습니다."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"나: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"임시보관"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"새 대화를 시작하면 여기에 표시됩니다."</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"보관처리된 대화는 여기에 표시됩니다."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"대화 로드 중..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"사진"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"오디오 클립"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"동영상"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"연락처 카드"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"실행취소"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"다시 시도"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"새로운 메시지를 시작하려면 연락처 이름 또는 전화번호를 입력하세요."</string>
+    <string name="action_block" msgid="9032076625645190136">"차단"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> 차단"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> 차단 해제"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>을(를) 차단하시겠습니까?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"앞으로 이 번호에서 보낸 메시지를 계속 받지만 알림은 더 이상 받지 않습니다. 이 대화는 보관처리됩니다."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"차단된 연락처"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"차단 해제"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"차단된 연락처"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"문서 라이브러리에서 이미지 선택"</string>
+    <string name="sending_message" msgid="6363584950085384929">"메시지를 전송하는 중입니다."</string>
+    <string name="send_message_success" msgid="4088006261869323324">"메시지가 전송되었습니다."</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"이동통신 데이터 사용이 중지되어 있습니다. 설정을 확인하세요."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"비행기 모드에서는 메시지를 보낼 수 없습니다."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"메시지를 보내지 못했습니다."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"메시지가 다운로드되었습니다."</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"이동통신 데이터 사용이 중지되어 있습니다. 설정을 확인하세요."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"비행기 모드에서 메시지를 다운로드할 수 없습니다."</string>
+    <string name="download_message_failure" msgid="635370887537738004">"메시지를 다운로드할 수 없습니다."</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"0"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"1"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"2"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"3"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"4"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"5"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"6"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"7"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"8"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"9"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g>을(를) 사용하여 메시지를 보낼 수 없습니다. 오류: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"알 수 없는 이동통신사를 사용하여 메시지를 보낼 수 없습니다. 오류: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"전달: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"서비스가 네트워크에서 활성화되지 않아 메시지가 전송되지 않았습니다."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"메시지가 전송되지 않음: 잘못된 수신 주소"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"메시지가 전송되지 않음: 잘못된 메시지"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"메시지가 전송되지 않음: 지원되지 않는 콘텐츠"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"메시지가 전송되지 않음: 지원되지 않는 메시지"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"메시지가 전송되지 않음: 용량 초과"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"새 메시지"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"보기"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"이미지"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"관련 애플리케이션을 찾을 수 없습니다."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"수신자 삭제"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"새 메시지"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"취소"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"액세스포인트 네임(APN) 수정"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"설정되지 않음"</string>
+    <string name="apn_name" msgid="1572691851070894985">"이름"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS 프록시"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS 포트"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN 유형"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN 삭제"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"새 APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"저장"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"취소"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"이름 입력란은 비워둘 수 없습니다."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN을 비워둘 수 없습니다."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC 입력란에는 3자리 숫자를 입력해야 합니다."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC 입력란에는 2~3자리 숫자를 입력해야 합니다."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"기본 APN 설정 복원 중"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"기본값으로 재설정"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"기본 APN 설정을 초기화했습니다."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"제목 없음"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"APN"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"새 APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"이 사용자는 액세스포인트 네임(APN) 설정을 수정할 수 없습니다."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"클립보드에 복사할까요?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"복사"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"전송 대상: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"일반"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"고급"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"일반 설정"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"고급 설정"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\'<xliff:g id="SIM_NAME">%s</xliff:g>\' SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"모든 수신자에게 개별 SMS 보내기(나만 답장을 받을 수 있음)"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"모든 수신자에게 하나의 MMS 보내기"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"알 수 없는 번호"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"새 메시지"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"새 메시지"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM 선택기"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> 선택됨. SIM 선택기"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"제목 수정"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM 선택 또는 제목 수정"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"길게 눌러 오디오 녹음"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"새로운 대화 시작"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"메시지"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"메시지 목록"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"메시지"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"새 메시지"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"대화 목록"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"대화 로드 중"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"메시지 로드 중"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"대화 더보기"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"메시지 더보기"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"대화를 삭제함"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"대화가 삭제되었습니다. 다른 메시지 대화를 표시하려면 터치하세요."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"차단됨"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"차단 해제됨"</string>
+    <string name="db_full" msgid="8459265782521418031">"저장공간이 충분하지 않아 일부 데이터가 저장되지 않을 수 있습니다."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"첨부파일 선택"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"선택항목 확인"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g>개 선택됨"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"하나 이상의 첨부파일을 삭제하고 다시 시도하세요."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"메시지 보내기를 시도할 수는 있지만 하나 이상의 첨부파일을 삭제하지 않으면 전송되지 않을 수 있습니다."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"메시지당 하나의 동영상만 보낼 수 있습니다. 추가 동영상을 삭제하고 다시 시도하세요."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"메시지에서 첨부파일이 로드되지 않았습니다."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"무시하고 보내기"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"대화를 시작할 수 없습니다."</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g>(<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> 선택됨"</string>
+</resources>
diff --git a/res/values-ky/arrays.xml b/res/values-ky/arrays.xml
new file mode 100644
index 0000000..0227144
--- /dev/null
+++ b/res/values-ky/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"темасы жок"</item>
+    <item msgid="272485471009191934">"темасыжок"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ооба"</item>
+    <item msgid="6049132459802288033">"Жок"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Хе-хе"</item>
+    <item msgid="2611328818571146775">"Рахмат"</item>
+    <item msgid="4881335087096496747">"Туура"</item>
+    <item msgid="2422296858597420738">"Сонун"</item>
+    <item msgid="4805581752819452687">"Жолдомун"</item>
+    <item msgid="4746700499431366214">"Макул, бир аздан кийин кайрылайынчы"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
new file mode 100644
index 0000000..96b6d86
--- /dev/null
+++ b/res/values-ky/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS/MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS/MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Маек тандаңыз"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Жөндөөлөр"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Билдирүү жөнөтүү"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Тиркеме кошуңуз"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Жардам"</string>
+    <string name="welcome" msgid="2857560951820802321">"Кош келиңиз"</string>
+    <string name="skip" msgid="7238879696319945853">"Өткөрүп жиберүү"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Кийинки &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Кийинки"</string>
+    <string name="exit" msgid="1905187380359981199">"Чыгуу"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Жөндөөлөр &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Жөндөөлөр"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"SMS/MMS\'ке SMS, телефон жана байланыштар уруксаты керек."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Уруксаттарды өзгөртүү үчүн Жөндөөлөр &gt; Колдонмолор &gt; SMS/MMS &gt; уруксаттарды басыңыз."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Уруксаттарды өзгөртүү үчүн Жөндөөлөр, Колдонмолор, SMS/MMS, уруксаттарды басыңыз."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Көп байланышкандар"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Бардык байланыштар"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Төмөнкүгө жөнөтүү <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Сүрөттөрдү же видео тартып алуу"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Бул түзмөктөн сүрөттөрдү тандаңыз"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Аудио жаздыруу"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Сүрөт тандаңыз"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медиа файл тандалды."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Медиа файл тандоодон чыгарылды."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> тандалды"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"сүрөт <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"сүрөт"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Аудио жаздыруу"</string>
+    <string name="action_share" msgid="2143483844803153871">"Бөлүшүү"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Жаңы эле"</string>
+    <string name="posted_now" msgid="867560789350406701">"Азыр"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> мүн</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> мүн</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> саат</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> саат</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> күн</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> күн</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> апта</item>
+      <item quantity="one">бир апта</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ай</item>
+      <item quantity="one">бир ай</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> жыл</item>
+      <item quantity="one">бир жыл</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0 классындагы билдирүү"</string>
+    <string name="save" msgid="5081141452059463572">"Сактоо"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Түзмөктө бош орун жетишпейт. Орун бошотуу үчүн, SMS/MMS эски SMS билдирүүлөрүн автоматтык түрдө жок кылат."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Сактагычта орун калбай баратат"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Түзмөгүңүздө көбүрөөк бош орун болмоюнча, SMS/MMS билдирүүлөрдү жөнөтүп же ала албашы мүмкүн."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS үчүн орун жетишпейт. Билдирүүлөрдү жок кылышыңыз керек окшойт."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Телефон номериңизди ырастаңыз"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Номер топтошкон SMS/MMS билдирүүлөрүн жөнөтүү үчүн талап кылынат. Аны бир гана жолу киргизүү керек."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Телефон номери"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Медиа файл камтылган бардык билдирүүлөрдү жок кылуу"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> ашкан билдирүүлөрдү жок кылуу"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> мурунку билдирүүлөр автоматтык түрдө жок кылынсын"</string>
+    <string name="ignore" msgid="7063392681130898793">"Көңүл бурбоо"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Медиа менен бардык файлдар жок кылынсынбы?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> мурунку файлдар жок кылынсынбы?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> мурунку билдирүүлөр жок кылынып, авто жок кылуу күйгүзүлсүнбү?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> айтты"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Сиз айттыңыз"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> дегенден билдирүү"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Билдирүү жөнөттүңүз"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Жөнөтүлүүдө…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Жөнөтүлгөн жок. Дагы аракет кылуу үчүн тийип коюңуз."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Жөнөтүлгөн жок. Кайра аракет жасалууда…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Кайра жөнөтүү же жок кылуу"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Өзгөчө кырдаал кызматтарына үн чалуу жасаңыз. Азыркы учурда текст билдирүүңүз жеткирилбей койду."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Болбой калды"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Жүктөлүп алынуучу жаңы MMS билдирүү"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Жаңы MMS билдирүү"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Жүктөлүп алынган жок"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Дагы аракет кылуу үчүн тийип коюңуз"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Жүктөп алуу үчүн тийип коюңуз"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Жүктөп алуу же жок кылуу"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Жүктөлүүдө…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Билдирүү мөөнөтү аяктады же жеткиликтүү эмес"</string>
+    <string name="mms_info" msgid="3402311750134118165">"өлчөмү: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, мөөнөтү бүтөт: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Жөнөтүлбөй жатат. Алуучу жарактуу эмес."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Тармакта кызмат жандырылган эмес"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Тармактагы көйгөйдөн улам жөнөтүлгөн жок"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Билдирүү мөөнөтү аяктады же жеткиликтүү эмес"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Темасы жок)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Белгисиз жөнөтүүчү"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Жеткирилди"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> келген <xliff:g id="SUBJECT">%1$s</xliff:g> билдирүүсү жүктөлүп алынган жок."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Сактагычта орун аз болгондуктан, дайындар базасы аяктабай калды"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Билдирүү жөнөтүлгөн жок"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Айрым SMS/MMS билдирүүлөрү жөнөтүлгөн жок"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> баарлашууда <xliff:g id="MESSAGES_1">%d</xliff:g> билдирүү</item>
+      <item quantity="one">Бир баарлашууда <xliff:g id="MESSAGES_0">%d</xliff:g> билдирүү</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Билдирүү жүктөлүп алынган жок"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Айрым SMS/MMS билдирүүлөрү жүктөлүп алынган жок"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> баарлашууда <xliff:g id="MESSAGES_1">%d</xliff:g> билдирүү</item>
+      <item quantity="one">Бир баарлашууда <xliff:g id="MESSAGES_0">%d</xliff:g> билдирүү</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> дегенге билдирүү жөнөтүлгөн жок"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Өзгөчө кырдаал кызматтарына үн чалуу жасаңыз. Азыркы учурда <xliff:g id="NUMBER">%1$s</xliff:g> номерине текст билдирүүңүз жеткирилбей койду."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> жаңы билдирүү</item>
+      <item quantity="one">Жаңы билдирүү</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Баштоо"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камера жеткиликтүү эмес"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камера жеткиликтүү эмес"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Видеону тартып алуу жеткиликтүү эмес"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Медиа сакталбай жатат"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Сүрөткө тарта албайт"</string>
+    <string name="back" msgid="1477626055115561645">"Артка"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архивделди"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Жок кылуу"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архивдөө"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Архивден чыгаруу"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Эскертмелерди өчүрүү"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Эскертмелерди күйгүзүү"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Байланыш кошуу"</string>
+    <string name="action_download" msgid="7786338136368564146">"Жүктөп алуу"</string>
+    <string name="action_send" msgid="377635240181672039">"Жөнөтүү"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Жок кылуу"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Бул билдирүү жок кылынсынбы?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Бул аракетти артка кайтаруу мүмкүн эмес."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Жок кылуу"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Бул баарлашуулөр жок кылынсынбы?</item>
+      <item quantity="one">Бул баарлашуу жок кылынсынбы?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Жок кылуу"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Жокко чыгаруу"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Кимге"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Бир нече сүрөт тандаңыз"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Тандалгандарды ырастаңыз"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Аудио жазылбай жатат. Дагы аракет кылыңыз."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Аудио ойнотулбай жатат. Дагы аракет кылыңыз."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Аудио сакталган жок. Дагы аракет кылыңыз."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Коё бербей amp; тийип туруу"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Сүрөт"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудио клип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Байланыш картасы"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Жүктөп алуу"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS аркылуу жооп берүү"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS аркылуу жооп берүү"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Жооп берүү"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> катышуучу</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> катышуучу</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Мен"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Байланыш бөгөттөлдү &amp; архивделди"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Байланыш бөгөттөн жана архивден чыгарылды"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> архивделди"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> архивден чыгарылды"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Эскертмелер өчүрүлгөн"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Эскертмелер күйгүзүлгөн"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Баары коюлду. Жөнөтүүнү кайра басыңыз."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"SMS/MMS демейки SMS колдонмосу катары коюлду."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Тиркемелерди жарактан чыгаруу</item>
+      <item quantity="one">Тиркемени жарактан чыгаруу</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудио тиркеме"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Аудио тиркемени ойнотуу"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Бир азга токтотуу"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> жөнөткөн билдирүү: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү бузулду. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Төмөнкүгө жиберилбеген билдирү <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Төмөнкүгө билдирүү жөнөтүлүүдө: <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү бузулду. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү бузулду. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Төмөнкүгө жиберилбеген билдирүү: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Төмөнкүгө билдирүү жөнөтүлүүдө: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү бузулду. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> билдирүүсү. Убакыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Билдирүү жөнөтүлбөй койду. Кайра аракет кылуу үчүн тийип коюңуз."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> менен сүйлөшүү"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Темасын жок кылуу"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Видео жаздыруу"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Кыймылдабаган сүрөттү тартып алуу"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Сүрөт тартуу"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Видео тартып баштоо"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Камераны толук экранга которуу"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Алдыңкы жана арткы камераны которуштуруу"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Тартылып жаткан видеону токтотуп, тиркеңиз"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Видео жаздырууну токтотуу"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"SMS/MMS сүрөттөрү"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> сүрөт \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" альбомуна сакталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> сүрөт \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" альбомуна сакталды</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> видео \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" альбомуна сакталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> видео \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" альбомуна сакталды</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> тиркеме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" альбомуна сакталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тиркеме \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" альбомуна сакталды</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тиркеме \"Жүктөлүп алынгандарга\" сакталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тиркеме \"Жүктөлүп алынгандарга\" сакталды</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тиркеме сакталды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тиркеме сакталды</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> тиркеме сакталбай калды</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> тиркеме сакталбай калды</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Сакталган MMS тиркемеси"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Жөндөөлөр"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архивделди"</string>
+    <string name="action_close" msgid="1840519376200478419">"Жабуу"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Өркүндөтүлгөн"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Мүчүлүштүктөрдү таап оңдоо"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Эскертмелер"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Үн"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Үнсүз"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Дирилдөө"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Бөгөттөлгөн"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS жеткирүү кабарлары"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Ар бир жөнөтүлгөн SMS билдирүүсүнүн алынгандыгын кабарлап коюну өтүнүү"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Авто-түшүрүү"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS билдирүүлөрүн автоматтык түрдө түшүрүп алуу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Роумингде авто-түшүрүп алуу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Роуминг учурунда MMS\'ти автоматтык түрдө чыгарып алуу"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Топтошуп билдирүү жазышуу"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Бир нече алуучуга бир билдирүү жөнөтүү үчүн MMS\'ти колдонуңуз"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Демейки SMS колдонмо"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Демейки SMS колдонмо"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Телефон номериңиз"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Белгисиз"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Билдирүү кеткенде добуш чыксын"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS\'ти ыргытуу"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Алынган SMS\'тин чийки дайындарын тышкы сактагычтагы файлга ыргытыңыз"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS\'ти ыргытуу"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Алынган MMS\'тин чийки дайындарын тышкы сактагычтагы файлга ыргытыңыз"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Зымсыз айгай кабарлар"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Билдирүүнүн параметрлери"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Текстти көчүрүү"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Дайындарды карап көрүү"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Жок кылуу"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Багыттоо"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Билдирүүнүн чоо-жайы"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Түрү: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS билдирүүсү"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мультимедиа билдирүүсү"</string>
+    <string name="from_label" msgid="1947831848146564875">"Кимден: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Кимге: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Жөнөтүлдү: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Алынды: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Темасы: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Өлчөмү: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Шашылыштыгы: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Жогору"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Орточо"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Төмөн"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Дареги жашырылган жөнөтүүчү"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Тиркемелер жүктөлүп жатканда билдирүү жөнөтүлбөйт."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Тиркеме жүктөлбөй жатат. Дагы аракет кылыңыз."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Тармак даяр эмес. Дагы аракет кылыңыз."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Текстти жок кылуу"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Текст жана сандарды киргизүү ыкмаларын которуштуруу"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Дагы катышуучуларды кошуу"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Катышуучуларды ырастоо"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Жаңы сүйлөшүү баштоо"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Бул нерсени тандоо"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Видео ойнотуу"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Адамдар &amp; параметрлер"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Мүчүлүштүктөрдү таап оңдоо"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Адамдар &amp; параметрлер"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Жалпы"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Бул маектеги адамдар"</string>
+    <string name="action_call" msgid="6596167921517350362">"Чалуу"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Билдирүү жөнөтүү"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt; <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; аркылуу билдирүү жөнөтүү"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Сүрөттөрдү жөнөтүү</item>
+      <item quantity="one">Сүрөт жөнөтүү</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Аудиолорду жөнөтүү</item>
+      <item quantity="one">Аудио жөнөтүү</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Видеолорду жөнөтүү</item>
+      <item quantity="one">Видео жөнөтүү</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Байланыш карталарын жөнөтүү</item>
+      <item quantity="one">Байланыш картасын жөнөтүү</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Тиркемелерди жөнөтүү</item>
+      <item quantity="one">Тиркемени жөнөтүү</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> тиркеме жөнөтүүгө даяр</item>
+      <item quantity="one">Бир тиркеме жөнөтүүгө даяр</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Жооп пикир жөнөтүү"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Дүкөнүндө карап көрүү"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Версия маалыматы"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"%1$s версиясы"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Ачык булак лицензиялары"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Эскертмелер"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Тиркеме чегине жетти"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Тиркеме жүктөлбөй койду."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Байланыштарга кошулсунбу?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Байланыш кошуу"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Тема"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Темасы: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Байланыш картасы жүктөлүүдө"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Байланыштын картасы жүктөлгөн жок"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Байланыш картасын карап көрүү"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> байланыш</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> байланыш</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Байланыш карталары"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Туулган күн"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Эскертүүлөр"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Билдирүүнү багыттоо"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Жооп берүү"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS өчүк"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Билдирүүлөрдү жөнөтүү үчүн, SMS/MMS\'ти демейки SMS колдонмосу катары коюңуз"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"SMS/MMS\'ти демейки SMS колдонмосу катары коюңуз"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Өзгөртүү"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Билдирүүлөрдү алуу үчүн, SMS/MMS\'ти демейки SMS колдонмосу катары коюңуз"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS билдирүүлөрдү жөнөтүү үчүн артыкчылыктуу SIM тандалган эмес"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Бул колдонмого түзмөк ээсинен уруксат жок."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Маекте катышуучулар өтө эле көп"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Жараксыз байланыштар</item>
+      <item quantity="one">Жараксыз байланыш</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Камера сүрөтү жүктөлгөн жок"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Сиз: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Сомо"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Жаңы маек башталганда, аны бул жердеги тизмеден көрөсүз"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Архивделген маектер бул жерден көрүнөт"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Маектер жүктөлүүдө…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Сүрөт"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудио клип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Байланыш картасы"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Кайтаруу"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Дагы аракет кылуу"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Жаңы билдирүүнү жазып баштоо үчүн байланыштын атын же телефон номерин киргизиңиз"</string>
+    <string name="action_block" msgid="9032076625645190136">"Бөгөттөө"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> дегенди бөгөттөө"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> дегенди бөгөттөн чыгаруу"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> бөгөттөлсүнбү?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Бул номерден билдирүүлөрдү ала бересиз, бирок мындан ары эскертмелерди албай каласыз. Бул маек архивделет."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Бөгөттөлгөн байланыштар"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"БӨГӨТТӨН ЧЫГАРУУ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Бөгөттөлгөн байланыштар"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Документтер китепканасынан сүрөт тандаңыз"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Билдирүү жөнөтүлүүдө…"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Билдирүү жөнөтүлдү"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Уюлдук дайындар өчүрүлгөн. Жөндөөлөрүңүздү текшериңиз."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Учак режиминде билдирүүлөр жөнөтүлбөйт"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Билдирүү жөнөтүлбөй жатат"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Билдирүү жүктөлүп алынды"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Уюлдук дайындар өчүрүлгөн. Жөндөөлөрүңүздү текшериңиз."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Учак режиминде билдирүүлөрдү жүктөп ала албайт"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Билдирүү жүктөлүп алынбай койду"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Ноль"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Бир"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Эки"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Үч"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Төрт"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Беш"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Алты"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Жети"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Сегиз"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Тогуз"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Билдирүүнү <xliff:g id="CARRIERNAME">%1$s</xliff:g> оператору аркылуу жөнөтүү мүмкүн эмес, ката <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Билдирүүнү белгисиз түзмөк аркылуу жөнөтүү мүмкүн эмес, ката <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Багыттоо: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Билдирүү жөнөтүлгөн жок: кызмат тармакта жандырылган эмес"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Билдирүү жөнөтүлгөн жок: жеткирүү дареги жараксыз"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Билдирүү жөнөтүлгөн жок: билдирүү жараксыз"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Билдирүү жөнөтүлгөн жок: мазмун колдоого алынбайт"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Билдирүү жөнөтүлгөн жок: билдирүү колдоого алынбайт"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Билдирүү жөнөтүлгөн жок: өтө чоң"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Жаңы билдирүү"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Карап көрүү"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Сүрөт"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Ылайыктуу колдонмо табылган жок"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Алуучуну чыгарып салуу"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Жаңы билдирүү"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Жокко чыгаруу"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Мүмкүнчүлүк алуу түйүнүн түзөтүү"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Коюлган эмес"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Ысымы"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS прокси"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS порту"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN түрү"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN жок кылуу"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Жаңы APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Сактоо"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Жарактан чыгаруу"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Аталыш талаасы бош болбошу керек."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN бош болбошу керек."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC талаасы 3 сандан турушу керек."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC талаасы 2 же 3 сандан турушу керек."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Демейки APN жөндөөлөрү калыбына келтирилүүдө."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Баштапкы абалга келтирүү"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Демейки APN жөндөөлөрү баштапкы абалга келтирилди."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Аталышы жок"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Мүмкүнчүлүк алуу түйүнүнүн аталыштары"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN\'дер"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Жаңы APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Бул колдонуучу мүмкүнчүлүк алуу түйүнүнүн аталышынын жөндөөлөрүн колдоно албайт"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Буферге көчүрүлсүнбү?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Көчүрүү"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> SIMге"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Жалпы"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Өркүндөтүлгөн"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Жалпы жөндөөлөр"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Өркүндөтүлгөн жөндөөлөр"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Бардык алуучуларга жеке SMS билдирүүлөрүн жөнөтүү. Бардык жоопторду сиз гана аласыз"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Бардык алуучуларга бир MMS жөнөтүү"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Белгисиз номер"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Жаңы билдирүү"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Жаңы билдирүү."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM тандагыч"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> тандалган, SIM тандагыч"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Теманы түзөтүү"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM тандоо же теманы түзөтүү"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Аудио жаздырыш үчүн кол тийгизип туруңуз"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Жаңы сүйлөшүү баштоо"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS/MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"SMS/MMS тизмеси"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS/MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Жаңы билдирүү"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Маек тизмеси"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Сүйлөшүүлөр жүктөлүүдө…"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Билдирүүлөр жүктөлүүдө"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Көбүрөөк сүйлөшүүлөрдү көрүү"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Дагы билдирүүлөрдү көрүү"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Сүйлөшүү жок кылынды"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Сүйлөшүү жок кылынды. Башка SMS/MMS сүйлөшүүсүн көрсөтүү үчүн тийиңиз"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Бөгөттөлдү"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Бөгөттөн чыгарылды"</string>
+    <string name="db_full" msgid="8459265782521418031">"Сактагычта бош орун аз. Айрым дайындар жоголушу мүмкүн."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Тиркемелерди тандаңыз"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Тандалгандарды ырастаңыз"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> тандалды"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Тиркемелердин бирин же көбүрөөгүн алып салып, кайра аракет кылыңыз."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Билдирүүңүздү жөнөтүп көрсөңүз болот, бирок ал бир же көбүрөөк тиркемени алып салмайыңызча жеткирилбеши мүмкүн."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Бир билдирүү менен бир эле видео жөнөтө аласыз. Кошумча видеолорду алып салып, кайра аракет кылыңыз."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Тиркелген файлдар жүктөлбөй калды."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Баары бир жөнөтүлсүн"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Сүйлөшүүнү баштай алган жок"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> тандалды"</string>
+</resources>
diff --git a/res/values-ldrtl-v21/styles.xml b/res/values-ldrtl-v21/styles.xml
new file mode 100644
index 0000000..4775979
--- /dev/null
+++ b/res/values-ldrtl-v21/styles.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <style name="ComposeMessageViewAttachMediaButtonStyle">
+        <item name="android:paddingStart">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:paddingEnd">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
+    </style>
+</resources>
diff --git a/res/values-ldrtl/styles.xml b/res/values-ldrtl/styles.xml
new file mode 100644
index 0000000..de4d9e8
--- /dev/null
+++ b/res/values-ldrtl/styles.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <style name="AttachmentPreviewCloseButtonStyle">
+        <item name="android:gravity">start</item>
+    </style>
+
+    <style name="ComposeMessageViewAttachMediaButtonStyle">
+        <item name="android:paddingStart">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:paddingEnd">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="ConversationComposeSendText">
+        <item name="android:textColor">@color/compose_send_text_color</item>
+        <item name="android:singleLine">false</item>
+        <item name="android:textSize">@dimen/conversation_compose_send_text_size</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:paddingStart">@dimen/compose_message_text_box_padding_side</item>
+        <item name="android:paddingEnd">@dimen/compose_message_text_box_padding_side</item>
+        <item name="android:minHeight">@dimen/conversation_message_contact_icon_size</item>
+        <item name="android:maxLines">4</item>
+        <item name="android:background">@null</item>
+        <item name="android:scrollHorizontally">false</item>
+        <item name="android:textCursorDrawable">@null</item>
+        <item name="android:inputType">textShortMessage|textAutoCorrect|textCapSentences|textMultiLine</item>
+    </style>
+
+    <style name="ConversationComposeSubjectText" parent="ConversationComposeSendText">
+        <item name="android:paddingStart">18dp</item>
+        <item name="android:gravity">start|center_vertical</item>
+        <item name="android:layout_marginStart">@dimen/compose_message_subject_cancel_left_margin</item>
+    </style>
+
+    <style name="ContactListItemViewStyle">
+        <item name="android:paddingStart">16dp</item>
+    </style>
+
+    <style name="ContactListItemLinearLayoutStyle">
+        <item name="android:paddingStart">12dp</item>
+        <item name="android:paddingEnd">24dp</item>
+    </style>
+
+    <style name="ConversationListItemViewPaddingStyle">
+        <item name="android:paddingStart">@dimen/conversation_list_item_view_padding</item>
+        <item name="android:paddingEnd">@dimen/conversation_list_item_view_padding</item>
+    </style>
+
+    <style name="ConversationListItemViewTextStyle">
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:background">@null</item>
+        <item name="android:textAlignment">viewStart</item>
+        <item name="android:textColor">@color/conversation_list_details</item>
+    </style>
+
+    <style name="ConversationListItemViewConversationNameStyle" parent="ConversationListItemViewTextStyle">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/conversation_list_name</item>
+    </style>
+
+    <style name="ConversationListNotificationBellPaddingStyle">
+        <item name="android:paddingEnd">@dimen/conversation_list_notification_bell_padding</item>
+    </style>
+
+    <style name="ComposeMessageViewFrameLayoutStyle">
+        <item name="android:paddingEnd">@dimen/compose_message_send_button_padding_right</item>
+    </style>
+
+    <style name="ConversationListFragmentStartNewButtonStyle">
+        <item name="android:layout_marginEnd">@dimen/fab_left_right_margin</item>
+    </style>
+
+    <style name="GalleryGridItemViewCheckBoxStyle">
+        <item name="android:paddingEnd">4dp</item>
+    </style>
+
+    <style name="BugleActionBarTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
+      <item name="android:textColor">@color/action_bar_title_text_color</item>
+      <item name="android:textSize">@dimen/action_bar_text_size</item>
+      <item name="android:lines">1</item>
+      <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="AttachmentPreviewAttachmentStyle">
+        <item name="android:layout_marginStart">10dp</item>
+    </style>
+
+    <style name="AudioAttachmentViewPlayPauseButtonStyle">
+        <item name="android:layout_marginEnd">16dp</item>
+    </style>
+
+    <style name="ComposeMessageViewDraftViewStyle">
+        <item name="android:layout_marginStart">53dp</item>
+        <item name="android:layout_marginEnd">63dp</item>
+    </style>
+
+    <style name="AudioAttachmentTimerText">
+        <item name="android:textSize">@dimen/audio_attachment_text_size</item>
+        <item name="android:textColor">@color/audio_attachment_timer_text_color</item>
+        <item name="android:layout_marginEnd">16dp</item>
+    </style>
+
+    <style name="ConversationMessageText">
+        <item name="android:background">@null</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="ConversationMessageViewStyle">
+        <item name="android:paddingStart">12dp</item>
+        <item name="android:paddingEnd">12dp</item>
+    </style>
+
+    <style name="SnackBarMessageWrapper">
+        <item name="android:layout_marginStart">@dimen/snack_bar_left_right_margin</item>
+        <item name="android:layout_marginEnd">0dp</item>
+    </style>
+
+    <style name="SubjectViewStyle">
+        <item name="android:paddingStart">@dimen/compose_message_subject_left_padding</item>
+        <item name="android:paddingEnd">@dimen/compose_message_subject_right_padding</item>
+    </style>
+
+    <style name="SmsDeliverdBadge">
+        <item name="android:layout_marginStart">4dp</item>
+    </style>
+
+    <style name="ChipDeleteIconStyle">
+        <item name="android:paddingStart">8dp</item>
+    </style>
+
+    <style name="ChipIconStyle">
+        <item name="android:layout_marginEnd">12dp</item>
+    </style>
+
+    <style name="SimSelectorItem">
+        <item name="android:textSize">@dimen/sim_selector_text_size</item>
+        <item name="android:textColor">@color/sim_selector_text_primary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">end</item>
+    </style>
+
+    <style name="SimSelectorItemDetail">
+        <item name="android:textSize">@dimen/sim_selector_detail_text_size</item>
+        <item name="android:textColor">@color/sim_selector_text_secondary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">end</item>
+    </style>
+
+    <style name="SimSelectorItemLinearLayoutStyle">
+        <item name="android:paddingEnd">12dp</item>
+    </style>
+
+    <style name="MessageSimIndicator">
+        <item name="android:textSize">@dimen/conversation_status_text_size</item>
+        <item name="android:layout_marginStart">4dp</item>
+    </style>
+
+    <style name="ComposeMessageViewMessageBodySizeStyle">
+        <item name="android:textColor">@color/message_body_size_text_color</item>
+        <item name="android:textSize">@dimen/message_body_size_text_size</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:layout_gravity">end|center_vertical</item>
+        <item name="android:paddingEnd">@dimen/compose_message_text_box_padding_side</item>
+    </style>
+
+    <style name="MmsIndicatorStyle">
+        <item name="android:textColor">@color/mms_indicator_color</item>
+        <item name="android:textSize">@dimen/mms_indicator_size</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:background">@null</item>
+        <item name="android:paddingEnd">@dimen/compose_message_send_button_padding_right</item>
+        <item name="android:paddingTop">@dimen/compose_message_mms_indicator_padding_top</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+    </style>
+
+    <style name="AttachmentGridItemViewCheckBoxStyle">
+        <item name="android:paddingEnd">4dp</item>
+    </style>
+
+    <style name="ParticipantListItem">
+        <item name="android:textSize">@dimen/participant_list_text_size</item>
+        <item name="android:textColor">@color/participant_list_text_primary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">start|center_vertical</item>
+    </style>
+
+    <style name="WidgetConversationItemFailed">
+        <item name="android:layout_gravity">bottom|end</item>
+    </style>
+
+    <style name="WidgetConversationItemIncomingAvatarShadow">
+        <item name="android:layout_marginStart">4dp</item>
+    </style>
+
+    <style name="WidgetConversationItemOutgoingAvatarShadow">
+        <item name="android:layout_marginStart">-4dp</item>
+    </style>
+
+    <style name="WidgetConversationItemDate">
+        <item name="android:layout_marginEnd">8dp</item>
+        <item name="android:layout_marginStart">5dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+
+    <style name="WidgetConversationItemWidget">
+        <item name="android:layout_marginEnd">8dp</item>
+        <item name="android:layout_marginStart">5dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+
+    <style name="WidgetConversationListItemBody">
+        <item name="android:layout_toEndOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetLoading">
+        <item name="android:layout_marginStart">16dp</item>
+    </style>
+
+    <style name="WidgetConversationItemBodyIncoming">
+        <item name="android:layout_toEndOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetConversationItemBodyOutgoing">
+        <item name="android:layout_toStartOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetConversationItemIncoming">
+        <item name="android:layout_marginEnd">5dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+        <item name="android:layout_toStartOf">@id/date</item>
+    </style>
+
+    <style name="WidgetConversationItemAttachment">
+        <item name="android:layout_gravity">bottom|end</item>
+    </style>
+
+    <style name="WidgetConversationAppIcon" parent="WidgetHeaderImage">
+        <item name="android:layout_marginStart">-20dp</item>
+    </style>
+
+    <style name="WidgetConversationItemAvatarOutgoing">
+        <item name="android:layout_marginEnd">8dp</item>
+        <item name="android:layout_alignParentEnd">true</item>
+    </style>
+
+    <style name="WidgetConversationListItemFrom">
+        <item name="android:layout_marginEnd">5dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+
+    <style name="WidgetConversationListItemDate">
+        <item name="android:layout_marginEnd">8dp</item>
+        <item name="android:layout_marginStart">5dp</item>
+        <item name="android:layout_gravity">start</item>
+    </style>
+
+</resources>
diff --git a/res/values-lo/arrays.xml b/res/values-lo/arrays.xml
new file mode 100644
index 0000000..cae3797
--- /dev/null
+++ b/res/values-lo/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ບໍ່ມີຫົວຂໍ້"</item>
+    <item msgid="272485471009191934">"​ບໍ່​ມີ​ຫົວ​ຂໍ້"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"​ແມ່ນ​ແລ້ວ"</item>
+    <item msgid="6049132459802288033">"ບໍ່​"</item>
+    <item msgid="3084376867445867895">"ຕົກລົງ"</item>
+    <item msgid="3155097332660174689">"​ຮິ​ຮິ"</item>
+    <item msgid="2611328818571146775">"​ຂອບ​ໃຈ"</item>
+    <item msgid="4881335087096496747">"​ຂ້ອຍ​​ຍອມ​ຮັບ"</item>
+    <item msgid="2422296858597420738">"​ຄັກຫຼາຍ"</item>
+    <item msgid="4805581752819452687">"​ກຳ​ລັງ​ໄປ"</item>
+    <item msgid="4746700499431366214">"​ຕົກ​ລົງ, ດຽວ​ຂ້ອຍ​ຈະ​ຕິດ​ຕໍ່​ກັບ​ໄປ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
new file mode 100644
index 0000000..4911499
--- /dev/null
+++ b/res/values-lo/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"ຂໍ້ຄວາມ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"ຂໍ້ຄວາມ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"​ເລືອກ​ການ​ແປງ​ຂໍ້​ມູນ"</string>
+    <string name="action_settings" msgid="1329008122345201684">"​ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"​ສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ເພີ່ມໄຟລ໌ແນບ"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"​ຊ່ວຍ​ເຫຼືອ"</string>
+    <string name="welcome" msgid="2857560951820802321">"ຍິນດີຕ້ອນຮັບ"</string>
+    <string name="skip" msgid="7238879696319945853">"ຂ້າມ"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ຕໍ່ໄປ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"ຕໍ່​ໄປ"</string>
+    <string name="exit" msgid="1905187380359981199">"ອອກ"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ການ​ຕັ້ງ​ຄ່າ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"ການສົ່ງຂໍ້​ຄວາມຕ້ອງ​ການ​ການ​ອະ​ນຸ​ຍາດ​ຫາ SMS, ໂທ​ລະ​ສັບ ແລະ ​ລາຍ​ຊື່."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ທ່ານ​ສາ​ມາດ​ປ່ຽນ​ແປງ​ການ​ການ​ອະ​ນຸ​ຍາດ​ໄດ້​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ &gt; ແອັບ &gt; ຂໍ້​ຄວາມ &gt; ການ​ອະ​ນຸ​ຍາດ."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ທ່ານ​ສາ​ມາດ​ປ່ຽນ​ແປງ​ການ​ອະ​ນຸ​ຍາດ​ໄດ້​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ, ແອັບ, ຂໍ້​ຄວາມ, ການ​ອະ​ນຸ​ຍາດ."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"​ຄວາມ​ຖີ່"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ລາຍ​ຊື່​ຜູ້ຕິດ​ຕໍ່​ທັງ​ໝົດ"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"ສົ່ງໄປ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ບັນ​ທຶກ​ຮູບ ຫຼື​ວິ​ດີ​ໂອ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ເລືອກ​ຮູບ​ສຳ​ລັບ​ອຸ​ປະ​ກອນ​ນີ້"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ບັນທຶກສຽງ"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ເລືອກ​ຮູບ"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"ມີ​ດີ​ນີ້​ຖືກ​ເລືອກ​ແລ້ວ."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ມີ​ເດຍ​ຖືກ​ຖອນ​ເລືອກ​ແລ້ວ."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"ເລືອກແລ້ວ <xliff:g id="COUNT">%d</xliff:g> ລາຍການ"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ຮູບ <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ຮູບ"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ບັນທຶກສຽງ"</string>
+    <string name="action_share" msgid="2143483844803153871">"ແບ່ງ​ປັນ"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ຕອນນີ້"</string>
+    <string name="posted_now" msgid="867560789350406701">"ຕອນນີ້"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ນ​ທ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ນ​ທ</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ຊົ່ວ​ໂມງ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ຊົ່ວ​ໂມງ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ວັນ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ວັນ</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ອາ​ທິດ</item>
+      <item quantity="one">ໜຶ່ງອາ​ທິດ</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ເດືອນ</item>
+      <item quantity="one">ໜຶ່ງ​ເດືອນ</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ປີ</item>
+      <item quantity="one">ໜຶ່ງ​ປີ</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ຂໍ້ຄວາມຄລາສ 0"</string>
+    <string name="save" msgid="5081141452059463572">"ບັນທຶກ"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ອຸ​ປະ​ກອນ​ມີ​ພື້ນ​ທີ່​​ເກັບ​ຂໍ້​ມູນ​ໜ້ອຍ. ກາ​ນສົ່ງຂໍ້​ຄວາມ​ຈະ​ລຶບ​ຂໍ້​ຄວາມ​ເກົ່າ​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ ເພື່ອ​ເຮັດ​ໃຫ້​ມີ​ພື້ນ​ທີ່​ຫວ່າງ​ເພີ່ມ​ຂຶ້ນ."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"ພື້ນທີ່​ຈັດ​ເກັບ​ຂໍ້ມູນ​ກຳລັງ​ຈະ​ເຕັມ"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"ການສົ່ງຂໍ້​ຄວາມ​ອາດ​ຈະ​ບໍ່​ສົ່ງ ຫຼື ຮັບ​ຂໍ້​ຄວາມ​ຈົນ​ກ່​ວາ​ມີ​ພື້ນ​ທີ່​ເພີ່ມ​ເຕີມ​ຢູ່​ໃນ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ພື້ນ​ທີ່​ເກັບ​ຂໍ້ຄວາມ​ໜ້ອຍ​ລົງ. ທ່ານ​ອາດ​ຈະ​ຕ້ອງ​ລຶບ​ຂໍ້​ຄວາມ​ເກົ່າ​ອອກ​ກ່ອນ."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ຢືນຢັນເບີໂທລະສັບຂອງທ່ານ"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ຂັ້ນ​ຕອນ​ໃຊ້​ເທື່ອ​ດຽວ​ນີ້​ຈະ​ຮັບ​ປະ​ກັນ​ໃຫ້ຂໍ້​ຄວາມສົ່ງ​ຂໍ້​ຄວາມ​ກຸ່ມ​ຂອງ​ທ່ານ​ໄດ້​ຢ່າງ​ຖືກ​ຕ້ອງ."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ເບີໂທລະສັບ"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ລຶບ​ຂໍ້ຄວາມ​ທັງໝົດ​ພ້ອມ​ທັງ​ມີເດຍ​ຕ່າງໆ"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"ລຶບ​ຂໍ້​ຄວາມ​ທີ່​ເກົ່າ​ກວ່າ <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"ລຶບ​ຂໍ້​ຄວາມ​ເກົ່າ​ກວ່າ <xliff:g id="DURATION">%s</xliff:g> ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ"</string>
+    <string name="ignore" msgid="7063392681130898793">"ບໍ່ສົນໃຈ"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"ລຶບ​ຂໍ້ຄວາມ​ທັງ​ໝົດ​ພ້ອມ​ທັງ​ມີເດຍ​ຕ່າງໆຫຼື​ບໍ່?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"ລຶບ​ຂໍ້ຄວາມ​ທີ່ເກົ່າກວ່າ <xliff:g id="DURATION">%s</xliff:g> ຫຼື​ບໍ່?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"​ລຶບ​ຂໍ້​ຄວາມ​ເກົ່າ​ກວ່າ <xliff:g id="DURATION">%s</xliff:g> ​ແລະ ເປີດ​ການ​ລຶບ​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດຫຼື​ບໍ່?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ໄດ້ເວົ້າ"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"ທ່ານໄດ້​ເວົ້າ"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"ຂໍ້ຄວາມຈາກ <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"ທ່ານ​ໄດ້ສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"ກຳລັງສົ່ງ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ສົ່ງ​ບໍ່​ໄດ້. ສຳ​ຜັດ​ເພື່ອ​ລອງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ສົ່ງ​ບໍ່​ໄດ້. ກຳ​ລັງ​ລອງ​ໃໝ່​ອີກ​ຄັ້ງ…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Resend or delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"ກະ​ລຸ​ນາ​ໂທ​ດ້ວຍ​ສຽງ​ໄປ​ຫາ​ບໍ​ລິ​ການ​ສຸກ​ເສີນ. ຂໍ້​ຄວາມ​ຂອງ​ທ່ານ​ບໍ່​ສາ​ມາດ​ນຳ​ສົ່ງ​ໄດ້​ໃນ​ເວ​ລາ​ນີ້."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"​ລົ້ມ​ເຫລວ"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ຂໍ້ຄວາມ MMS ​ໃຫມ່​ທີ່ຈະ​ດາວ​ໂຫລດ"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"ຂໍ້ຄວາມ MMS ​ໃຫມ່"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ບໍ່​ສາ​ມາດ​ດາວ​ໂຫລດ​ໄດ້"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ສຳ​ຜັດ​ເພື່ອ​ລອງ​ອີກ​ຄັ້ງ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ແຕະເພື່ອ​ດາວ​ໂຫຼດ"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ດາວ​ໂຫລດ​ ຫລື​ລຶບ"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"​ກຳ​ລັງ​ດາວ​ໂຫລດ..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"ຂໍ້​ຄວາມ​ໝົດ​ອາຍຸ ຫຼື ໃຊ້​ບໍ່​ໄດ້​ແລ້ວ"</string>
+    <string name="mms_info" msgid="3402311750134118165">"size: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"​ບໍ່​ສາ​ມາດ​ສົ່ງ​ໄດ້. ຂໍ້​ມູນ​ຜູ່​ຮັບ​ບໍ່​ຖືກ​ຕ້ອງ."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ບໍ່​ໄດ້​ເປີດ​ໃຊ້​ບໍລິການ​ໃນ​ເຄືອຂ່າຍ"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ບໍ່ສາມາດ​ສົ່ງໄດ້​ເນື່ອງຈາກ​ມີບັນຫາ​ກັບເຄືອຂ່າຍ"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"ຂໍ້​ຄວາມ​ໝົດ​ກຳ​ນົດ ຫຼື ໃຊ້​ບໍ່​ໄດ້​ແລ້ວ"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ບໍ່ມີຫົວຂໍ້)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ບໍ່ຮູ້ຜູ່ສົ່ງ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ສົ່ງຮອດແລ້ວ"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"ບໍ່​ສາມາດ​ດາວໂຫລດ​ຂໍ້​ຄວາມ <xliff:g id="SUBJECT">%1$s</xliff:g> ຈາກ <xliff:g id="FROM">%2$s</xliff:g> ໄດ້."</string>
+    <string name="low_memory" msgid="5300743415198486619">"ບໍ່​ສາມາດ​ປະຕິບັດ​ການ​ທາງ​ດ້ານ​ຖານ​ຂໍ້ມູນ​ເນື່ອງ​ຈາກ​ໜ່ວຍ​ຄວາມ​ຈຳ​ຕໍ່າ"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"ຂໍ້ຄວາມ​ຍັງ​ບໍ່ໄດ້​ຖືກສົ່ງ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"ບາງ​ຂໍ້​ຄວາມ​ບໍ່​ໄດ້​ສົ່ງ​ຢູ່​ໃນການສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ຂໍ້​ຄວາມ​ໃນ <xliff:g id="CONVERSATIONS">%d</xliff:g> ບົດ​ສົນ​ທະ​ນາ</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> ຂໍ້​ຄວາມ​ໃນ​ຫນຶ່ງ​ບົດ​ສົນ​ທະ​ນາ</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"ບໍ່ສາມາດດາວໂຫລດຂໍ້ຄວາມໄດ້"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"ບາງ​ຂໍ້​ຄວາມ​ບໍ່​ໄດ້​ຮັບ​ການ​ດາວ​ໂຫຼດ​ຢູ່​ໃນການສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ຂໍ້​ຄວາມ​ໃນ <xliff:g id="CONVERSATIONS">%d</xliff:g> ບົດ​ສົນ​ທະ​ນາ</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> ຂໍ້​ຄວາມ​ໃນ​ຫນຶ່ງ​ບົດ​ສົນ​ທະ​ນາ</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"ຂໍ້​ຄວາມ​ຫາ <xliff:g id="NUMBER">%1$s</xliff:g> ບໍ່​ໄດ້​ສົ່ງ"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"ກະ​ລຸ​ນາ​ໂທ​ດ້ວຍ​ສຽງ​ໄປ​ຫາ​ບໍ​ລິ​ການ​ສຸກ​ເສີນ. ຂໍ້​ຄວາມ​ຂອງ​ທ່ານຫາ <xliff:g id="NUMBER">%1$s</xliff:g> ບໍ່​ສາ​ມາດ​ນຳ​ສົ່ງ​ໄດ້​ໃນ​ເວ​ລາ​ນີ້."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ຂໍ້ຄວາມ​ໃໝ່.</item>
+      <item quantity="one">ຂໍ້ຄວາມ​ໃໝ່.</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ເລີ່ມ"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ບໍ່​ສາມາດ​ໃຊ້​ກ້ອງໄດ້"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ບໍ່​ສາມາດ​ໃຊ້​ກ້ອງໄດ້"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"​ບໍ່​ສາ​ມາດ​ໃຊ້​ການບັນ​ທຶກວິ​ດີ​ໂອ​ໄດ້"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"​ບໍ່​ສາ​ມາດ​ບັນ​ທຶກ​ມີ​ເດຍ​ໄດ້"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ບໍ່​ສາ​ມາດ​ຖ່າຍ​ຮູບ​ໄດ້"</string>
+    <string name="back" msgid="1477626055115561645">"ກັບຄືນ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ຈັດເກັບແລ້ວ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"​ລຶບ"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ຈັດເກັບ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ຖອດອອກຈາກແຟ້ມ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"ປິດ​ການ​ແຈ້ງເຕືອນ"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"ເປີດ​ການ​ແຈ້ງເຕືອນ"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"ເພີ່ມ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່"</string>
+    <string name="action_download" msgid="7786338136368564146">"ດາວໂຫລດ"</string>
+    <string name="action_send" msgid="377635240181672039">"ສົ່ງ"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"​ລຶບ"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ລຶບ​ຂໍ້ຄວາມ​ນີ້ຫຼືບໍ່?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"​ການ​ກະ​ທຳ​ນີ້ຈະ​ບໍ່​ສາ​ມາດ​ກູ້​ຄືນ​ໄດ້."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"​ລຶບ"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ລຶບການສົນທະນານີ້ບໍ?</item>
+      <item quantity="one">ລຶບການສົນທະນານີ້ບໍ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"​ລຶບ"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"​ຍົກ​ເລີກ"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ໄປ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"​ເລືອກ​ຫຼາຍ​ຮູບ"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"​ຢືນ​ຢັນ​ການ​ເລືອກ"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ບໍ່​ສາ​ມາດ​ອັດ​ສຽງ​ໄດ້. ລອງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ບໍ່​ສາ​ມາດຫຼິ້ນ​ສຽງ​ໄດ້. ລອງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"​ບໍ່​ສາ​ມາດ​ບັນ​ທຶກ​ສຽງ​ໄດ້. ລອງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ແຕະຄ້າງ​ໄວ້"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ຮູບພາບ"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ຄລິບສຽງ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ວິດີໂອ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"ບັດ​ລາຍຊື່​ຜູ່ຕິດຕໍ່"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ດາວໂຫຼດ"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"ຕອບ​ກັບ​ຜ່ານ SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"ຕອບ​ກັບ​ຜ່ານ MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ຕອບກັບ"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ຜູ້ເຂົ້າ​ຮ່ວມ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ຜູ້ເຂົ້າ​ຮ່ວມ</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ຂ້ອຍ"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"ບລັອກ​ &amp; ຈັດ​ເກັບ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່​ເຂົ້າ​ແຟ້ມ​ແລ້ວ"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"ປົດ​ບ​ລັອກ​ລາຍ​ຊື່​ແລ້ວ &amp; ບໍ່​ໄດ້​ເກັບ​ໄວ້"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ຖືກຈັດເກັບແລ້ວ"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ຖືກ​ຖອດ​ອອກ​ຈາກ​ບ່ອນ​ຈັດ​ເກັບ​ແລ້ວ"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ການ​ແຈ້ງ​ເຕືອນ​ປິດ​ແລ້ວ"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"ການ​ແຈ້ງ​ເຕືອນ​ເປີດ​ແລ້ວ"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"​ຕັ້ງ​ຮຽບ​ຮ້ອຍ​ແລ້ວ. ສຳ​ຜັດ​ເພື່ອ​ສົ່ງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"ຕັ້ງ​ຂໍ້​ຄວາມ​ເປັນ​ແອັບ SMS ເລີ່ມຕົ້ນ​ສຳ​ເລັດ​ແລ້ວ."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">ເອົາ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖິ້ມ</item>
+      <item quantity="one">ເອົາ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖິ້ມ</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ໄຟ​ລ໌​ຄັດ​ຕິດ​ສຽງ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ຫຼິ້ນ​ສິ່ງຕິດຄັດທີ່ເປັນ​ສຽງ"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ຢຸດຊົ່ວຄາວ"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"ຂໍ້​ຄວາມ​ຈາກ<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"ຂໍ້​ຄວາມ​ບໍ່​ສຳ​ເລັດ​ຈາກ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"ຂໍ້​ຄວາມ​ຈາກ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"ຂໍ້​ຄວາມ​ບໍ່​ໄດ້​ສົ່ງ​ຫາ <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"ຂໍ້​ຄວາມ​ກຳ​ລັງ​ສົ່ງ​ຫາ <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"ຂໍ້​ຄວາມ​ບໍ່​ສຳ​ເລັດ​ຫາ <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"ຂໍ້​ຄວາມ​ຫາ <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"ຂໍ້​ຄວາມ​ບໍ່​ສຳ​ເລັດຈາກ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"ຂໍ້​ຄວາມ​ຈາກ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"ຂໍ້​ຄວາມ​ບໍ່​ໄດ້​ສົ່ງ​ຫາ <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"ຂໍ້​ຄວາມກຳ​ລັງ​ສົ່ງ​​ຫາ <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"ຂໍ້​ຄວາມ​ບໍ່​ສຳເລັດ​ຫາ <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Time: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"ຂໍ້​ຄວາມ​ຫາ <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. ເວ​ລາ: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ຂໍ້​ຄວາມ​ບໍ່​ສຳ​ເລັດ. ສຳ​ຜັດ​ເພື່ອ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"ການ​ສົນ​ທະ​ນາ​ກັບ <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"​ລຶບ​ຫົວ​ຂໍ້"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ບັນ​ທຶກ​ວິດີໂອ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ບັນ​ທຶກ​ຮູບ"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ຖ່າຍຮູບ"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ເລີ່ມ​ການ​ບັນທຶກ​ວິດີໂອ"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"ສະລັບ​ໄປ​ໃຊ້​ກ້ອງ​ແບບ​ເຕັມຈໍ"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"​ສະ​ລັບ​ລະ​ຫວ່າງ​ກ້ອງ​ໜ້າ ແລະ ຫຼັງ"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"​ຢຸດ​ການ​ບັນ​ທຶກ ແລະ ແນບ​ວິ​ດີ​ໂອ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"​ຢຸດ​ການ​ບັນ​ທຶກວິ​ດີ​ໂອ"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"ຮູບຖ່າຍານສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ຮູບ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່​ອາ​ລະ​ບັ້ມ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ຮູບ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່​ອາ​ລະ​ບັ້ມ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ວິ​ດີ​ໂອ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່​ອາ​ລະ​ບັ້ມ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ວິ​ດີ​ໂອ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່​ອາ​ລະ​ບັ້ມ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶ​ກ​ໄປ​ໃສ່ອາ​ລະບັ້ມ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶ​ກ​ໄປ​ໃສ່ອາ​ລະ​ບັ້ມ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່ \"ດາວ​ໂຫຼດ\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶກ​ໄປ​ໃສ່ \"ດາວ​ໂຫຼດ\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶກ​ແລ້ວ</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ຖືກ​ບັນ​ທຶກ​ແລ້ວ</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">ບໍ່​ສາ​ມາດ​ບັນ​ທຶກ <xliff:g id="QUANTITY_1">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ໄດ້</item>
+      <item quantity="one">ບໍ່​ສາ​ມາດ​ບັນ​ທຶກ <xliff:g id="QUANTITY_0">%d</xliff:g> ໄຟ​ລ໌​ຄັດ​ຕິດ​ໄດ້</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"ບັນ​ທຶກ​ໄຟລ໌​ແນບ MMS ​ແລ້ວ"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ຈັດເກັບແລ້ວ"</string>
+    <string name="action_close" msgid="1840519376200478419">"ປິດ"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"​ຂັ້ນ​ສູງ"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ດີບັ໊ກ"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"ການແຈ້ງເຕືອນ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ສຽງ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"ປິດສຽງ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ສັ່ນເຕືອນ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ບລັອກ​ແລ້ວ"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"​ລາຍ​ງານ​ຜົນ​ການສົ່ງ SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"​ຂໍ​ລາຍ​ງານຜົນ​ການ​ສົ່ງ​ສຳ​ລັບ​ແຕ່​ລະ​ SMS ທີ່​ທ່ານ​ສົ່ງ"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"ດຶງ​ຂໍ້ມູນ​ອັດຕະໂນມັດ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"ດຶງຂໍ້ຄວາມ MMS ອັດຕະໂນມັດ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ດຶງ​ຂໍ້ຄວາມ​ອັດຕະໂນມັດ​ເມື່ອ​ໂຣມມິງ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ກູ້​ຄືນ MMS ອັດ​ຕະ​ໂນ​ມັດ​ເມື່ອ​ໂຣມ​ມິງ"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ການສົ່ງ​ຂໍ້ຄວາມກຸ່ມ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ໃຊ້ MMS ເພື່ອສົ່ງ​ຂໍ້ຄວາມ​ໃດນຶ່ງ​ເມື່ອມີຜູ່ຮັບ​ຫຼາຍຄົນ"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ແອັບຯ SMS ມາດ​ຕະ​ຖານ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ແອັບຯ SMS ມາດ​ຕະ​ຖານ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"​ເບີ​ໂທ​ລະ​ສັບ​ຂອງ​ທ່ານ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"​ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"ສຽງ​ຂໍ້​ຄວາມ​ຂາ​ອອກ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"ດຶງ SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ດຶງ​ຂໍ້​ມູນ SMS ​ດິບທີ່​ໄດ້​ຮັບ​ໃນ​ຮູບ​ແບບ​ໄຟ​ລ໌​ເກັບ​ຂໍ້​ມູນ​ພາຍນອກ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"ດຶງ MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ດຶງ​ຂໍ້​ມູນ MMS ​ດິບທີ່​ໄດ້​ຮັບ​ໃນ​ຮູບ​ແບບ​ໄຟ​ລ໌​ເກັບ​ຂໍ້​ມູນ​ພາຍນອກ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ແຈ້ງ​ເຕືອນ​ລະບົບ​ໄຮ້ສາຍ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"​ໂຕ​ເລືອກ​ຂໍ້​ຄວາມ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"​ສຳ​ເນົາ​ຂໍ້​ຄວາມ"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"​ເບິ່ງ​ລາຍ​ລະ​ອຽດ"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"​ລຶບ"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ສົ່ງຕໍ່"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"​ລາຍ​ລະ​ອຽດ​ຂໍ້​ຄວາມ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ປະ​ເພດ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"​ຂໍ້​ຄວາມ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ຂໍ້​ຄວາມ​ມັນ​ຕິ​ມີ​ເດຍ"</string>
+    <string name="from_label" msgid="1947831848146564875">"ຈາກ: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ເຖິງ: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ສົ່ງ​ເມື່ອ: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ໄດ້​ຮັບເມື່ອ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"ຫົວ​ຂໍ້: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"​ຂະ​ໜາດ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ຄວາມ​ສຳ​ຄັນ: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"​ຊິມ: "</string>
+    <string name="priority_high" msgid="728836357310908368">"​ສູງ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"​ປານ​ກາງ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"​ຕ່ຳ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"​ຊິມ <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"​​ເຊື່ອງ​ທີ່​ຢູ່​ຜູ່​ສົ່ງ"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"​ບໍ່​ສາ​ມາດ​ສົ່ງ​ຂໍ້​ຄວາມ​ໄດ້​ໃນ​ຂະ​ນະ​ທີ່​ໂຫຼດ​ໄຟລ໌​ແນບ."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ບໍ່​ສາ​ມາດ​ໂຫລດ​ໄຟລ໌​ແນບ​ໄດ້. ​ລອງ​ໃໝ່​ອີກ​ຄັ້ງ."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ເຄືອ​ຂ່າຍ​ບໍ່​ພ້ອມ. ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ລຶບ​ຂໍ້​ຄວາມ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ສະ​ລັບ​ລະ​ຫວ່າງ​ການ​ພິມ​ໂຕ​ອັກ​ສອນ ແລະ​ໂຕ​ເລກ"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"ເພີ່ມ​ຜູ່​ເຂົ້າ​ຮ່ວມ​ອື່ນ"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ຢືນ​ຢັນ​ຜູ່​ເຂົ້າ​ຮ່ວມ"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"​ເລີ່ມ​ບົດ​ສົນ​ທະ​ນາ​ໃໝ່"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"​ເລືອກ​ລາຍ​ການ​ນີ້"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ຫຼິ້ນວິດີໂອ"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່ &amp; ໂຕ​ເລືອກ"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ດີບັ໊ກ"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່ &amp; ໂຕ​ເລືອກ"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ທົ່ວໄປ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ຄ​ົນ​ໃນ​ບົດ​ສົນ​ທະ​ນາ​ນີ້"</string>
+    <string name="action_call" msgid="6596167921517350362">"​ໂທ​ອອກ"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ສົ່ງຂໍ້ຄວາມ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"​ສົ່ງ​ຂໍ້​ຄວາມ&lt;br/&gt;&lt;small&gt;​ຈາກ <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">​ສົ່ງ​ຮູບ​ພາບ</item>
+      <item quantity="one">​ສົ່ງ​ຮູບ​ພາບ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">​ສົ່ງ​ສຽງ</item>
+      <item quantity="one">​ສົ່ງ​ສຽງ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ສົ່ງ​ວິດີໂອ</item>
+      <item quantity="one">ສົ່ງ​ວິດີໂອ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">​ສົ່ງ​ບັດ​ລາຍ​ຊື່​ຜູ້ຕິດ​ຕໍ່</item>
+      <item quantity="one">​ສົ່ງ​ບັດ​ລາຍ​ຊື່​ຜູ້ຕິດ​ຕໍ່</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">​ສົ່ງ​ໄຟລ໌​ຄັດ​ຕິດ</item>
+      <item quantity="one">​ສົ່ງ​ໄຟລ໌​ຄັດ​ຕິດ</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ພ້ອມ​ສົ່ງ​ໄດ້​ແລ້ວ</item>
+      <item quantity="one">ໜຶ່ງ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ພ້ອມ​ສົ່ງ​ໄດ້​ແລ້ວ</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"​ສົ່ງ​ຄຳ​ຕິ​ຊົມ"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"ເບິ່ງໃນ Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"​​ຂໍ​້​ມູນ​ເວີ​ຊັນ"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ເວີ​ຊັນ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"​ລິ​ຂະ​ສິດ​ໂອ​ເພນ​ຊອດ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"ການແຈ້ງເຕືອນ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ຮອດ​ຂີດ​ຈຳ​ກັດ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ແລ້ວ"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ໂຫຼດ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ບໍ່​ສຳ​ເລັດ."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"ເພີ່ມ​ໃສ່​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່​ບໍ່?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"ເພີ່ມ​​ໃສ່​ລາ​ຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ຫົວຂໍ້"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"ຫົວຂໍ້: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"​ກຳ​ລັງ​ໂຫລດ​ບັດ​ລາຍ​ຊື່​ຜ​ູ່​ຕິດ​ຕໍ່"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"​ບໍ່​ສາ​ມາດ​ໂຫລດ​ບັດ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່ໄດ້"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"​ເບິ່ງ​ບັດ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ລາຍ​ຊື່</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ລາຍ​ຊື່</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"ບັດ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"ວັນເດືອນປີເກີດ"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ບັນທຶກ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"​ສົ່ງ​ຕໍ່​ຂໍ້​ຄວາມ"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ຕອບຄືນ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS ​ຖືກ​ປິດ​ແລ້ວ"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ເພື່ອ​ສົ່ງ, ຕັ້ງ​ການສົ່ງຂໍ້​ຄວາມ​ເປັນ​ແອັບ SMS ເລີ່ມຕົ້ນ"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"ຕັ້ງການສົ່ງ​ຂໍ້​ຄວາມ​ເປັນ​ແອັບ SMS ເລີ່ມຕົ້ນ"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ປ່ຽນແປງ"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"​ເພື່ອ​ຮັບ​ຂໍ້​ຄວາມ, ຕັ້ງການສົ່ງຂໍ້​ຄວາມໃຫ້​ເປັນ​ແອັບ SMS ​ເລີ່ມ​ຕົ້ນ​ຂອງ​ທ່ານ"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"ບໍ່​ມີ SIM ທີ່​ມັກ​ຖືກ​ເລືອກ​ໄວ້​ ເພື່ອ​ສົ່ງ​ຂໍ້​ຄວາມ SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"​​ເຈົ້າ​ຂອງ​ອຸ​ປະ​ກອນບໍ່​ອະ​ນຸ​ຍາດ​ໃຫ້​ໃຊ້​ແອັບຯ​ນີ້."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ຕົກລົງ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"​ມີ​ຜູ່​ເຂົ້າ​ຮ່ວມ​ໃນ​ການ​ສົນ​ທະ​ນາຫຼາຍ​ເກີນ​ໄປ"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">ລາຍ​ຊື່​ຕິດ​ຕໍ່​ບໍ່​ຖືກ​ຕ້ອງ</item>
+      <item quantity="one">ລາຍ​ຊື່​ຕິດ​ຕໍ່​ບໍ່​ຖືກ​ຕ້ອງ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"​ບໍ່​ສາ​ມາດ​ໂຫລດ​ຮູບ​ຈາກ​ກ້ອງ​ໄດ້"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"ທ່ານ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ສະບັບຮ່າງ"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"ໃນເວລາ​ທີ່ທານ​ເລີ່ມການ​ສົນທະນາ​ໃຫມ່, ທ່ານຈະເຫັນ​ມັນສະແດງ​ຢູ່ບ່ອນ​ນີ້"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"​ບົດ​ສົນ​ທະ​ນາ​ທີ່​ຖືກ​ຈັດ​ເກັບ​ຈະ​ສະ​ແດງ​ຢູ່​ນີ້"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"ກຳລັງ​ໂຫລດ​ບົດ​ສົນທະນາ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ຮູບພາບ"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ຄລິບສຽງ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ວິດີໂອ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"ບັດ​ລາຍຊື່​ຕິດຕໍ່"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"ຍົກເລີກ"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ລອງໃໝ່"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"​ປ້ອນ​ຊື່​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່ ຫຼື ເບີ​ໂທ​ລະ​ສັບ​ເພື່ອ​ເລີ່ມ​ຂໍ້​ຄວາມ​ໃໝ່"</string>
+    <string name="action_block" msgid="9032076625645190136">"ບລັອກ"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"ບລັອກ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"​ປົດ​ບລັອກ <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"ບລັອກ <xliff:g id="DESTINATION">%s</xliff:g> ບໍ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"​ທ່ານ​ຈະ​ຍັງ​ສືບ​ຕໍ່​ໄດ້​ຮັບ​ຂໍ້​ຄວາມ​ຈາກ​ເບີ​ນີ້ ແຕ່​ຈະ​ບໍ່​ຖືກ​ແຈ້ງ​ເຕືອນ​ອີກ​ຕໍ່​ໄປ. ບົດ​ສົນ​ທະ​ນາ​ນີ້​ຈະ​ຖືກ​ຈັດ​ເກັບ."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່​ທີ່​ຖືກບລັອກ"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"​ປົດ​ບລັອກ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"ບລັອກ​ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່​ແລ້ວ"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"​ເລືອກ​ຮູບ​ຈາກ​ຫ້ອງ​ສະ​ໝຸດ​ເອ​ກະ​ສານ"</string>
+    <string name="sending_message" msgid="6363584950085384929">"ກຳລັງສົ່ງຂໍ້ຄວາມ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"ສົ່ງຂໍ້ຄວາມແລ້ວ"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ຂໍ້​ມູນ​ເຄືອ​ຂ່າຍ​ໂທ​ລະ​ສັບ​ຖືກ​ປິດ​ໄວ້. ກະ​ລຸ​ນາ​ກວດ​ສອບ​ການ​ຕັ້ງ​ຄ່າ​ຂອງ​ທ່ານ."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"​ບໍ່​ສາ​ມາດ​ສົ່ງ​ຂໍ້​ຄວາມ​ໃນ​ໂໝດ​ໃນ​ຍົນ​ໄດ້"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"ບໍ່ສາມາດສົ່ງຂໍ້ຄວາມໄປໄດ້"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"ດາວ​ໂຫຼດ​ຂໍ້​ຄວາມ​ແລ້ວ"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ຂໍ້​ມູນເຊວ​ລູ​ລາ​ຖືກ​ປິດ​ໄວ້. ສອບ​ການ​ຕັ້ງ​ຄ່າ​ຂອງ​ທ່ານ."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ບໍ່​ສາ​ມາດ​ກາວ​ໂຫຼດ​ຂໍ້​ຄວາມ​ຢູ່​ໃນ​ໂໝດ​ເຮືອ​ບິນ​ໄດ້"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"ບໍ່​ສາ​ມາດ​ດາວ​ໂຫຼດ​ໄດ້"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"​ສູນ"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"​ນຶ່ງ"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"​ສອງ"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"​ສາມ"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"​ສີ່"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"​ຫ້າ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"​ຫົກ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"​ເຈັດ"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ແປດ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"​ເກົ້າ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"ບໍ່​ສາ​ມາດ​ສົ່ງ​ຂໍ້​ຄວາມ​ດ້ວຍ <xliff:g id="CARRIERNAME">%1$s</xliff:g> ໄດ້, ຂໍ້​ຜິດ​ພາດ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"ບໍ່​ສາ​ມາດ​ສົ່ງ​ຂໍ້​ຄວາມ​ດ້ວຍບໍ​ລິ​ສັດ​ເຄືອ​ຂ່າຍ​ມື​ຖື​ບໍ່​ຮູ້​ຈັກ​ໄດ້, ຂໍ້​ຜິດ​ພາດ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"ຂໍ້​ຄວາມ​ຍັງ​ບໍ່​ໄດ້​ສົ່ງ: ບໍ​ລິ​ການ​ຍັງ​ບໍ່​ໄດ້​ເປີດ​ນຳ​ໃຊ້​ໃນ​ເຄືອ​ຂ່າຍ​ເທື່ອ"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"ຂໍ້​ຄວາມ​ຍັງ​ບໍ່​ໄດ້​ສົ່ງ: ທີ່​ຢູ່​ປາຍ​ທາງບໍ່​ຖືກ​ຕ້ອງ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"ຂໍ້​ຄວາມ​ຍັງ​ບໍ່​ໄດ້​ສົ່ງ: ຂໍ້​ຄວາມ​ບໍ່​ຖືກ​ຕ້ອງ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"ຂໍ້​ຄວາມ​ຍັງ​ບໍ່​ໄດ້​ສົ່ງ: ​ບໍ່​ຮອງ​ຮັບ​ເນື້ອ​ຫາ"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"ຂໍ້​ຄວາມ​ຍັງ​ບໍ່​ໄດ້​ສົ່ງ: ບໍ່​ຮອງ​ຮັບ​ຂໍ້​ຄວາມ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"ຂໍ້ຄວາມ​ຍັງ​ບໍ່ໄດ້​ຖືກສົ່ງ: ໃຫຍ່​ເກີນ​ໄປ"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"ຂໍ້ຄວາມໃໝ່"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"​ເບິ່ງ"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ຮູບພາບ"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"ບໍ່​ສາ​ມາດ​ຊອກ​ຫາ​ແອັບ​ພລິ​ເຄ​ຊັນ​ທີ່​ເໝາະ​ສົມ​ໄດ້"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"ລຶບ​ຜູ່​ຮັບ"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"ຂໍ້ຄວາມໃໝ່"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"​ຍົກ​ເລີກ"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ແກ້ໄຂ​ຈຸດ​ການ​ເຊື່ອມຕໍ່"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"ຍັງບໍ່ໄດ້ຕັ້ງ"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ຊື່"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"ພອດ MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"ປະເພດ APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"ລຶບ APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN ໃໝ່"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"ບັນທຶກ"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ຍົກເລີກ"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"ຊ່ອງຂໍ້ມູນ​ຊື່​ບໍ່ສາມາດ​ປ່ອຍ​ຫວ່າງໄດ້."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ບໍ່​ສາມາດ​ປ່ອຍ​ໃຫ້​ຫວ່າງ​ໄດ້."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"ຊ່ອງຂໍ້ມູນ MMC ຕ້ອງມີ 3 ໂຕເລກ."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"ຊ່ອງຂໍ້ມູນ MNC ຕ້ອງມີ 2 ຫຼື 3 ໂຕເລກ."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ກຳລັງ​ກັບ​ໄປ​ໃຊ້ການຕັ້ງຄ່າ APN ເລີ່ມຕົ້ນ."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ກັບຄືນໄປໃຊ້ຄ່າເລີ່ມຕົ້ນ"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"​ສຳ​ເລັດ​ການ​ກັບ​ໄປໃຊ້ການ​ຕັ້ງ​ຄ່າ APN ເລີ່ມຕົ້ນແລ້ວ."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ບໍ່ໄດ້ຕັ້ງຊື່"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ຊື່ຂອງ​ຈຸດການ​ເຂົ້າເຖິງ (APN)"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN ໃໝ່"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ຜູ່​ໃຊ້​ນີ້ບໍ່​ສາ​ມາດ​ຕັ້ງ​ຄ່າ​ຊື່​ຈຸດ​ການ​ເຂົ້າ​ເຖິງ​ໄດ້"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"​ສຳ​ເນົາ​ໄວ້​ໃນຄລິບບອດຫຼື​ບໍ່?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ສຳເນົາ"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ເຖິງ <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ທົ່ວໄປ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"​ຂັ້ນ​ສູງ"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"ການຕັ້ງຄ່າ​ທົ່ວໄປ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"ການຕັ້ງຄ່າ​ຂັ້ນສູງ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"​ສົ່ງ​ຂໍ້​ຄວາມ SMS ​ສະ​ເພາະ​ບຸກ​ຄົນໄປ​ຫາ​ທຸກໆ​ຜູ່​ຮັບ. ​ສະ​ເພາະ​ທ່ານ​ເທົ່າ​ນັ້ນ​ທີ່​ຈະ​ໄດ້​ຮັບ​ແຕ່​ລະ​ການ​ຕອບ​ກັບ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"​ສົ່ງ MMS ​ສະ​ບັບ​ນຶ່ງ​ໄປ​ຫາ​ທຸກໆ​ຜູ່​ຮັບ"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"​ເບີ​ໂທບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"ຂໍ້ຄວາມ​ໃໝ່"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"ຂໍ້ຄວາມ​ໃໝ່."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"ຕົວ​ເລືອກ SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ຖືກ​ເລືອກ​ແລ້ວ, ຕົວ​ເລືອກ SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ແກ້ໄຂຫົວຂໍ້"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"ເລືອກ SIM ຫຼື​ແກ້​ໄຂ​ຫົວ​ຂໍ້"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ສຳ​ພັດ​ຄ້າງ​ໄວ້ ເພື່ອ​ບັນ​ທຶກ​ສຽງ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"​ເລີ່ມ​ບົດ​ສົນ​ທະ​ນາ​ໃໝ່"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"ຂໍ້ຄວາມ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"ລາຍ​ການການສົ່ງ​ຂໍ້​ຄວາມ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"ຂໍ້ຄວາມ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"ຂໍ້ຄວາມໃໝ່"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"ລາຍການການສົນທະນາ"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"ກຳລັງ​ໂຫລດ​ບົດ​ສົນທະນາ..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"ກຳລັງໂຫລດຂໍ້ຄວາມ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"ເບິ່ງບົດສົນທະນາເພີ່ມເຕີມ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"ເບິ່ງ​ຂໍ້​ຄວາມ​ເພີ່ມ​ເຕີມ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"ການ​ສົນທະນາ​ຖືກລຶບແລ້ວ"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ການ​ສົນ​ທະ​ນາ​ຖືກ​ລຶບ​ແລ້ວ. ສຳ​ຜັດ​ເພື່ອ​ສະ​ແດງ, ການ​ສົນ​ທະ​ນາ​ຂໍ້​ຄວາມ​ທີ່​ແຕກ​ຕ່າງ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ບລັອກ​ແລ້ວ"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"ປົດ​ບ​ລັອກ​ແລ້ວ"</string>
+    <string name="db_full" msgid="8459265782521418031">"ພື້ນ​ທີ່​ຈັດ​ເກັບ​ຕ່ຳ. ບາງ​ຂໍ້​ມູນ​ອາດ​ຈະ​ເສຍ​ໄປ."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ເລືອກ​ໄຟ​ລ໌​ຄັດ​ຕິດ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"​ຢືນ​ຢັນ​ການ​ເລືອກ"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ເລືອກ​ແລ້ວ"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ກະ​ລຸ​ນາ​ເອົາ​ໜຶ່ງ ຫຼື​ຫຼາຍ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ອອກ​ໄປ ແລະ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"ທ່ານ​ສາ​ມາດ​ລອງ​ສົ່ງ​ຂໍ້​ຄວາມ​ຂອງ​ທ່ານ​ໄດ້, ແຕ່​ມັນ​ອາດ​ຈະ​ບໍ່​ຖືກ​ສົ່ງ​ໄປ ນອກ​ຈາກວ່າ​ທ່ານ​ເອົາ​ໜຶ່ງ ຫຼື​ຫຼາຍ​ໄຟ​ລ໌​ຄັດ​ຕິດ."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ທ່ານ​ສາ​ມາດ​ສົ່ງ​ໄດ້​ແຕ່​ໜຶ່ງວິ​ດີ​ໂອ​ຕໍ່​ຂໍ້​ຄວາມ​ເທົ່າ​ນັ້ນ. ກະ​ລຸ​ນາ​ເອົາ​ວິ​ດີ​ໂອ​ເພີ່ມ​ເຕີມ​ອອກ ແລະ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"ການສົ່ງຂໍ້​ຄວາມ​ໂຫຼດ​ໄຟ​ລ໌​ຄັດ​ຕິດ​ບໍ່ສຳເລັດ."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ແນວ​ໃດ​ກໍ່​ສົ່ງ​"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"ບໍ່​ສາ​ມາດ​ເລີ່ມ​ຕົ້ນ​ການ​ສົນ​ທະ​ນາ​ໄດ້"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ເລືອກ​ແລ້ວ"</string>
+</resources>
diff --git a/res/values-lt/arrays.xml b/res/values-lt/arrays.xml
new file mode 100644
index 0000000..3c1c116
--- /dev/null
+++ b/res/values-lt/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"nėra temos"</item>
+    <item msgid="272485471009191934">"nėra temos"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Taip"</item>
+    <item msgid="6049132459802288033">"Ne"</item>
+    <item msgid="3084376867445867895">"Gerai"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Ačiū"</item>
+    <item msgid="4881335087096496747">"Sutinku"</item>
+    <item msgid="2422296858597420738">"Puiku"</item>
+    <item msgid="4805581752819452687">"Pakeliui"</item>
+    <item msgid="4746700499431366214">"Gerai, informuosiu vėliau"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
new file mode 100644
index 0000000..0430221
--- /dev/null
+++ b/res/values-lt/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Susirašinėjimas pranešimais"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Susirašinėjimas pranešimais"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Pasirinkti pokalbį"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Nustatymai"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Siųsti pranešimą"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Pridėti priedą"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Pagalba"</string>
+    <string name="welcome" msgid="2857560951820802321">"Sveiki!"</string>
+    <string name="skip" msgid="7238879696319945853">"Praleisti"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Kitas &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Kitas"</string>
+    <string name="exit" msgid="1905187380359981199">"Išeiti"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Nustatymai &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Nustatymai"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Susirašinėjimo programai reikia leidimų pasiekti SMS pranešimus, telefoną ir kontaktus."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Leidimus galite pakeisti skiltyje „Nustatymai &gt; Programos &gt; Susirašinėjimo programa &gt; Leidimai“."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Leidimus galite pakeisti skiltyje „Nustatymai, Programos, Susirašinėjimo programa, Leidimai“."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Dažniausiai naudojami"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Visi kontaktai"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Siųsti: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Fotografuokite arba filmuokite"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Pasirinkite vaizdus iš šio įrenginio"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Įrašyti garsą"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Pasirinkti nuotrauką"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Medija pasirinkta."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Medija nepasirinkta."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Pasirinkta: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"vaizdas: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"vaizdas"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Įrašyti garsą"</string>
+    <string name="action_share" msgid="2143483844803153871">"Bendrinimas"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Ką tik"</string>
+    <string name="posted_now" msgid="867560789350406701">"Dabar"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> val.</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> val.</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> val.</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> val.</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> diena</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dienos</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> dienos</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dienų</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> savaitė</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> savaitės</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> savaitės</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> savaičių</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mėnesiai</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> mėnesiai</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> mėnesio</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mėnesių</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> metai</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> metai</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> metų</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> metų</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0 klasės pranešimas"</string>
+    <string name="save" msgid="5081141452059463572">"Išsaugoti"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Mažai vietos įrenginyje. Susirašinėjimo programa automatiškai ištrins senesnius pranešimus, kad atlaisvintų vietos."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Mažėja laisvos saugyklos vietos saugykloje"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Galbūt Susirašinėjimo programa negalės siųsti ar gauti pranešimų, kol įrenginyje nebus daugiau laisvos vietos."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Mažai laisvos SMS saugyklos vietos. Gali reikėti ištrinti pranešimus."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Patvirtinkite telefono numerį"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Atlikę šį vienkartinį veiksmą užtikrinsite, kad Susirašinėjimo programa tinkamai pateiks grupės pranešimus."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefono numeris"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Ištrinti visus pranešimus su medija"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Ištrinti senesnius nei <xliff:g id="DURATION">%s</xliff:g> pranešimus"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automatiškai ištrinti pranešimus, kurie senesni nei <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Nepaisyti"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Ištrinti visus pranešimus su medija?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Ištrinti pranešimus, kurie senesni nei <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Ištrinti pranešimus, kurie senesni nei <xliff:g id="DURATION">%s</xliff:g>, ir įjungti automatinį ištrynimą?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sakė"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Jūs sakėte"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Pranešimas nuo <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Išsiuntėte pranešimą"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Siunčiama…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Neišsiųsta. Palieskite, kad bandytumėte dar kartą."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Neišsiųsta. Bandoma dar kartą…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Persiųsti arba ištrinti"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Atlikite balso skambutį pagalbos tarnyboms. Šiuo metu negalime pateikti teksto pranešimo."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Nepavyko"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Naujas MMS pranešimas, kurį galima atsisiųsti"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Naujas MMS pranešimas"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nepavyko atsisiųsti"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Palieskite ir bandykite dar kartą"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Palieskite, kad atsisiųstumėte"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Atsisiųskite arba ištrinkite"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Atsisiunčiama..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Pranešimo galiojimo laikas pasibaigė arba jis negalimas"</string>
+    <string name="mms_info" msgid="3402311750134118165">"dydis: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, galiojimo pabaiga: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nepavyko išsiųsti. Netinkamas gavėjas."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Paslauga nesuaktyvinta tinkle"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Nepavyko išsiųsti dėl tinklo problemos"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Pranešimo galiojimo laikas pasibaigė arba jis negalimas"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Nėra temos)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Nežinomas siuntėjas"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Pristatyta"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nepavyko atsisiųsti pranešimo „<xliff:g id="SUBJECT">%1$s</xliff:g>“ nuo <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Nepavyko atlikti duomenų bazės operacijos dėl atminties trūkumo"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Pranešimas neišsiųstas"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Kai kurie pranešimai neišsiųsti naudojant Susirašinėjimo programą"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbis)</item>
+      <item quantity="few">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbiai)</item>
+      <item quantity="many">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbio)</item>
+      <item quantity="other">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbių)</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Pranešimas neatsisiųstas"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Kai kurie pranešimai neatsisiųsti naudojant Susirašinėjimo programą"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbis)</item>
+      <item quantity="few">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbiai)</item>
+      <item quantity="many">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbio)</item>
+      <item quantity="other">Pranešimų: <xliff:g id="MESSAGES_1">%d</xliff:g> (<xliff:g id="CONVERSATIONS">%d</xliff:g> pokalbių)</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Pranešimas numeriu <xliff:g id="NUMBER">%1$s</xliff:g> nebuvo išsiųstas"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Atlikite balso skambutį pagalbos tarnyboms. Šiuo metu negalime pateikti teksto pranešimo numeriu <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> naujas pranešimas</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nauji pranešimai</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> naujo pranešimo</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> naujų pranešimų</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Pradėti"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotoaparatas negalimas"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotoaparatas negalimas"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Vaizdo įrašo fiksavimas negalimas"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nepavyko išsaugoti medijos"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Negalima fotografuoti"</string>
+    <string name="back" msgid="1477626055115561645">"Atgal"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Suarchyvuota"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Ištrinti"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archyvuoti"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Išarchyvuoti"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Išjungti pranešimus"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Įjungti pranešimus"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Pridėti kontaktą"</string>
+    <string name="action_download" msgid="7786338136368564146">"Atsisiųsti"</string>
+    <string name="action_send" msgid="377635240181672039">"Siųsti"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Ištrinti"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Ištrinti šį pranešimą?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Šio veiksmo anuliuoti negalima."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Ištrinti"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Ištrinti šiuos pokalbius?</item>
+      <item quantity="few">Ištrinti šiuos pokalbius?</item>
+      <item quantity="many">Ištrinti šiuos pokalbius?</item>
+      <item quantity="other">Ištrinti šiuos pokalbius?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Ištrinti"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Atšaukti"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kam"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Pasirinkti kelis vaizdus"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Patvirtinti pasirinkimą"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"Dar <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Nepavyko įrašyti garso. Bandykite dar kartą."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Nepavyko paleisti garso įrašo. Bandykite dar kartą."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Nepavyko išsaugoti garso įrašo. Bandykite dar kartą."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Palieskite ir palaikykite"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Nuotrauka"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Garso įrašo klipas"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vaizdo įrašas"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontakto kortelė"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Atsisiųsti"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Atsakyti SMS žinute"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Atsakyti MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Atsakyti"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dalyvis</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dalyviai</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> dalyvio</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dalyvių</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Aš"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontaktas užblokuotas ir suarchyvuotas"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontaktas atblokuotas ir išarchyvuotas"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Suarchyvuota: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Išarchyvuota: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Pranešimai išjungti"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Pranešimai įjungti"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Viskas nustatyta. Dar kartą palieskite „Siųsti“."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Susirašinėjimo programa sėkmingai nustatyta kaip numatytoji SMS programa."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Išmesti priedus</item>
+      <item quantity="few">Išmesti priedus</item>
+      <item quantity="many">Išmesti priedus</item>
+      <item quantity="other">Išmesti priedus</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Garso priedas"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Leisti garso priedą"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pristabdyti"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Pranešimas nuo <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Nepavyko atsiųsti pranešimo nuo <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Pranešimas nuo <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Neišsiųstas pranešimas grupei „<xliff:g id="CONTACT">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Siunčiamas pranešimas grupei „<xliff:g id="CONTACT">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Nepavyko išsiųsti pranešimo grupei „<xliff:g id="CONTACT">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Pranešimas grupei „<xliff:g id="CONTACT">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Nepavyko atsiųsti pranešimo nuo <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Pranešimas nuo <xliff:g id="SENDER">%1$s</xliff:g>: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Neišsiųstas pranešimas grupei „<xliff:g id="GROUP">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Siunčiamas pranešimas grupei „<xliff:g id="GROUP">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Nepavyko išsiųsti pranešimo grupei „<xliff:g id="GROUP">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Pranešimas grupei „<xliff:g id="GROUP">%1$s</xliff:g>“: „<xliff:g id="MESSAGE">%2$s</xliff:g>“. Laikas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Įvyko pranešimo klaida. Palieskite ir bandykite dar kartą."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Pokalbis su <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Pašalinti temą"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Filmuoti"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Fiksuoti nejudantį vaizdą"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Fotografuoti"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Pradėti filmuoti"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Perjungti į viso ekrano režimu veikiantį fotoaparatą"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Perjungti priekinį ir užpakalinį fotoaparatus"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Sustabdyti įrašymą ir pridėti vaizdo įrašą"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Sustabdyti vaizdo įrašymą"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Susirašinėjimo programos nuotraukos"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> nuotrauka išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> nuotraukos išsaugotos albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> nuotraukos išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> nuotraukų išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> vaizdo įrašas išsaugotas albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> vaizdo įrašai išsaugoti albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> vaizdo įrašo išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vaizdo įrašų išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> priedas išsaugotas albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> priedai išsaugoti albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> priedo išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> priedų išsaugota albume „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> priedas išsaugotas aplanke „Atsisiuntimai“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> priedai išsaugoti aplanke „Atsisiuntimai“</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> priedo išsaugota aplanke „Atsisiuntimai“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> priedų išsaugota aplanke „Atsisiuntimai“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one">Išsaugotas <xliff:g id="QUANTITY_1">%d</xliff:g> priedas</item>
+      <item quantity="few">Išsaugoti <xliff:g id="QUANTITY_1">%d</xliff:g> priedai</item>
+      <item quantity="many">Išsaugota <xliff:g id="QUANTITY_1">%d</xliff:g> priedo</item>
+      <item quantity="other">Išsaugota <xliff:g id="QUANTITY_1">%d</xliff:g> priedų</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Nepavyko išsaugoti <xliff:g id="QUANTITY_1">%d</xliff:g> priedo</item>
+      <item quantity="few">Nepavyko išsaugoti <xliff:g id="QUANTITY_1">%d</xliff:g> priedų</item>
+      <item quantity="many">Nepavyko išsaugoti <xliff:g id="QUANTITY_1">%d</xliff:g> priedo</item>
+      <item quantity="other">Nepavyko išsaugoti <xliff:g id="QUANTITY_1">%d</xliff:g> priedų</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Išsaugotas MMS priedas"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Nustatymai"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Suarchyvuota"</string>
+    <string name="action_close" msgid="1840519376200478419">"Uždaryti"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Išplėstiniai"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Derinti"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Pranešimai"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Garsas"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Tylus"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibravimas"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Užblokuota"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS pristatymo ataskaitos"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Pateikti kiekvieno išsiųsto SMS pristatymo ataskaitos užklausą"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatiškai nuskaityti"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatiškai nuskaityti MMS pranešimus"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Aut. nuskait. naud. tarptinklinį ryšį"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatiškai nuskaityti MMS, kai veikia tarptinklinis ryšys"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Grupinis susirašinėjimas"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Naudokite MMS, kad siųstumėte vieną pranešimą, kai yra keli gavėjai"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Numatytoji SMS programa"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Numatytoji SMS programa"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Jūsų telefono numeris"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Nežinomas"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Siunčiamų pranešimų garsai"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Pateikti SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Pateikti gautų SMS neapdorotus duomenis išorinės atminties faile"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Pateikti MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Pateikti gautų MMS neapdorotus duomenis išorinės atminties faile"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Belaidžiu ryšiu siunčiami įspėjimai"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Pranešimo parinktys"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopijuoti tekstą"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Peržiūrėti išsamią informaciją"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Ištrinti"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Persiųsti"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Išsami pranešimo informacija"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipas: "</string>
+    <string name="text_message" msgid="7415419755252205721">"teksto pranešimas"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Įvairialypės informacijos pranešimas"</string>
+    <string name="from_label" msgid="1947831848146564875">"Nuo: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kam: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Išsiųsta: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Gauta: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Tema: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Dydis: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Pirmenybė: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Aukšta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Įprasta"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Žema"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Paslėptas siuntėjo adresas"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Negalima siųsti žinutės, kol įkeliami priedai."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nepavyko įkelti priedo. Bandykite dar kartą."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Tinklas neparuoštas. Bandykite dar kartą."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Pašalinti tekstą"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Perjungti iš teksto įvedimo į skaičių įvedimą ir atvirkščiai"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Pridėti daugiau dalyvių"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Patvirtinti dalyvius"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Pradėti naują pokalbį"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Pasirinkti šį elementą"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Leisti vaizdo įrašą"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Žmonės ir parinktys"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Derinti"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Žmonės ir parinktys"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Bendrieji"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Žmonės šiame pokalbyje"</string>
+    <string name="action_call" msgid="6596167921517350362">"Skambinti"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Siųsti pranešimą"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Siųsti pranešimą&lt;br/&gt;&lt;small&gt;iš <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Siųsti nuotraukas</item>
+      <item quantity="few">Siųsti nuotraukas</item>
+      <item quantity="many">Siųsti nuotraukas</item>
+      <item quantity="other">Siųsti nuotraukas</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Siųsti garso įrašus</item>
+      <item quantity="few">Siųsti garso įrašus</item>
+      <item quantity="many">Siųsti garso įrašus</item>
+      <item quantity="other">Siųsti garso įrašus</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Siųsti vaizdo įrašus</item>
+      <item quantity="few">Siųsti vaizdo įrašus</item>
+      <item quantity="many">Siųsti vaizdo įrašus</item>
+      <item quantity="other">Siųsti vaizdo įrašus</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Siųsti kontaktų korteles</item>
+      <item quantity="few">Siųsti kontaktų korteles</item>
+      <item quantity="many">Siųsti kontaktų korteles</item>
+      <item quantity="other">Siųsti kontaktų korteles</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Siųsti priedus</item>
+      <item quantity="few">Siųsti priedus</item>
+      <item quantity="many">Siųsti priedus</item>
+      <item quantity="other">Siųsti priedus</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priedas paruoštas siųsti</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priedai paruošti siųsti</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priedo paruošta siųsti</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priedų paruošta siųsti</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Siųsti atsiliepimą"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Žr. „Google Play“ parduotuvėje"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versijos informacija"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"%1$s versija"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Atvirojo šaltinio licencijos"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Pranešimai"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Pasiektas priedų apribojimas"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Nepavyko įkelti priedo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Pridėti prie kontaktų?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Pridėti kontaktą"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Tema"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Tema: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Įkeliama kontakto kortelė"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nepavyko įkelti kontakto kortelės"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Peržiūrėti kontakto kortelę"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> kontaktas</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> kontaktai</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> kontakto</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktų</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktų kortelės"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Gimimo data"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Užrašai"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Persiųsti pranešimą"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Atsakyti"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS išjungta"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Kad galėtumėte išsiųsti, nustatykite Susirašinėjimo programą kaip numatytąją SMS programą"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Nustatykite Susirašinėjimo programą kaip numatytąją SMS programą"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Pakeisti"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Kad galėtumėte gauti pranešimus, nustatykite Susirašinėjimo programą kaip numatytąją SMS programą"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nepasirinkta jokių pageidaujamų SIM kortelių, kurias būtų galima naudoti SMS pranešimams siųsti"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Įrenginio savininkas neleidžia naudoti šios programos."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Gerai"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Per daug pokalbio dalyvių"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Netinkami kontaktai</item>
+      <item quantity="few">Netinkami kontaktai</item>
+      <item quantity="many">Netinkami kontaktai</item>
+      <item quantity="other">Netinkami kontaktai</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nepavyko įkelti fotoaparato vaizdo"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Jūs: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Juodraštis"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Kai pradėsite naują pokalbį, jis bus pateiktas čia"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Archyvuoti pokalbiai rodomi čia"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Įkeliami pokalbiai..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Nuotrauka"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Garso įrašo klipas"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vaizdo įrašas"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontakto kortelė"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Anuliuoti"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Bandyti dar kartą"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Įveskite kontakto vardą arba telefono numerį, kad pradėtumėte naują pranešimą"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokuoti"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokuoti <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Panaikinti <xliff:g id="DESTINATION">%s</xliff:g> blokavimą"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokuoti <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Ir toliau gausite pranešimus iš šio numerio, bet nebūsite apie juos įspėti. Šis pokalbis bus archyvuotas."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Užblokuoti kontaktai"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"PANAIKINTI BLOKAVIMĄ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Užblokuoti kontaktai"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Pasirinkite vaizdą iš dokumentų bibliotekos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Siunčiamas pranešimas"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Pranešimas išsiųstas"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobiliojo ryšio duomenys išjungti. Patikrinkite nustatymus."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Negalima siųsti pranešimų lėktuvo režimu"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Nepavyko išsiųsti pranešimo"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Pranešimas atsisiųstas"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobiliojo ryšio duomenys išjungti. Patikrinkite nustatymus."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Nepavyksta atsisiųsti pranešimų lėktuvo režimu"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Pranešimo nepavyko atsisiųsti"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nulis"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Vienas"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Du"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trys"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Keturi"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Penki"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Šeši"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Septyni"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Aštuoni"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Devyni"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nepavyko išsiųsti pranešimo; operatorius „<xliff:g id="CARRIERNAME">%1$s</xliff:g>“, <xliff:g id="ERRORCODE">%2$d</xliff:g> klaida"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nepavyko išsiųsti pranešimo; operatorius nežinomas, <xliff:g id="ERRORCODE">%1$d</xliff:g> klaida"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Pers.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Pranešimas neišsiųstas: paslauga nesuaktyvinta tinkle"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Pranešimas neišsiųstas: netinkamas paskirties adresas"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Pranešimas neišsiųstas: netinkamas pranešimas"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Pranešimas neišsiųstas: nepalaikomas turinys"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Pranešimas neišsiųstas: nepalaikomas pranešimas"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Pranešimas neišsiųstas: per didelis"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Naujas pranešimas"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Peržiūrėti"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Vaizdas"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nepavyko rasti tinkamos programos"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Pašalinti gavėją"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Naujas pranešimas"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Atšaukti"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Redaguoti prieigos tašką"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nenustatyta"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Pavadinimas"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS tarpinis serveris"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS prievadas"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN tipas"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Ištrinti APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Naujas APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Išsaugoti"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Atmesti"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Pavadinimo laukas negali būti tuščias."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN laukas negali būti tuščias."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC lauke turi būti įvesti 3 skaitmenys."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC lauke turi būti įvesti 2 ar 3 skaitmenys."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Atkuriami numatytieji APN nustatymai."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Iš naujo nustatyti numatytuosius nustatymus"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Numatytųjų APN nustatymų nustatymas iš naujo baigtas."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Be pavadinimo"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Prieigos taškų pavadinimai"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Naujas APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Prieigos taško pavadinimo nustatymai šiam naudotojui nepasiekiami"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopijuoti į iškarpinę?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopijuoti"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"į <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Bendrieji"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Išplėstiniai"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Bendrieji nustatymai"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Išplėstiniai nustatymai"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"„<xliff:g id="SIM_NAME">%s</xliff:g>“ SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Siųsti individualius SMS pranešimus visiems gavėjams. Atsakymus gausite tik jūs"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Siųsti vieną MMS visiems gavėjams"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nežinomas numeris"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Naujas pranešimas"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Naujas pranešimas."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM pasirinkimas"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Pasirinkta: <xliff:g id="SIM_0">%1$s</xliff:g>, SIM pasirinkimas"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Redaguoti temą"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Pasirinkite SIM arba redaguokite temą"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Palaikykite palietę, kad įrašytumėte garso įrašą"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Pradėti naują pokalbį"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Susirašinėjimo programa"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Susirašinėjimo programos sąrašas"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Susirašinėjimo programa"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Naujas pranešimas"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Pokalbių sąrašas"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Įkeliami pokalbiai"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Įkeliami pranešimai"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Peržiūrėti daugiau pokalbių"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Peržiūrėti daugiau pranešimų"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Pokalbis ištrintas"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Pokalbis ištrintas. Palieskite, kad būtų rodomas kitas Susirašinėjimo programos pokalbis."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Užblokuota"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Atblokuota"</string>
+    <string name="db_full" msgid="8459265782521418031">"Mažai laisvos saugyklos vietos. Kai kurie duomenys gali būti prarasti."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Pasirinkti priedus"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Patvirtinti pasirinkimą"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Pasirinkta: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Pašalinkite bent vieną priedą ir bandykite dar kartą."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Galite pabandyti siųsti pranešimą, bet gali nepavykti jo pristatyti, nebent pašalinsite bent vieną priedą."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Viename pranešime galite siųsti tik vieną vaizdo įrašą. Pašalinkite papildomus vaizdo įrašus ir bandykite dar kartą."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Susirašinėjimo programai nepavyko įkelti priedo."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Vis tiek siųsti"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Nepavyko pradėti pokalbio"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Pasirinkta <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-lv/arrays.xml b/res/values-lv/arrays.xml
new file mode 100644
index 0000000..0e130b7
--- /dev/null
+++ b/res/values-lv/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"bez temata"</item>
+    <item msgid="272485471009191934">"bez temata"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Jā"</item>
+    <item msgid="6049132459802288033">"Nē"</item>
+    <item msgid="3084376867445867895">"Labi"</item>
+    <item msgid="3155097332660174689">"He-he"</item>
+    <item msgid="2611328818571146775">"Paldies!"</item>
+    <item msgid="4881335087096496747">"Piekrītu"</item>
+    <item msgid="2422296858597420738">"Jauki"</item>
+    <item msgid="4805581752819452687">"Esmu ceļā"</item>
+    <item msgid="4746700499431366214">"Labi, vēlāk ar tevi sazināšos."</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
new file mode 100644
index 0000000..f598c77
--- /dev/null
+++ b/res/values-lv/strings.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Ziņojumapmaiņa"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Ziņojumapmaiņa"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Atlasiet sarunu"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Iestatījumi"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Nosūtīt ziņojumu"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Pievienot pielikumu"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Palīdzība"</string>
+    <string name="welcome" msgid="2857560951820802321">"Laipni lūdzam!"</string>
+    <string name="skip" msgid="7238879696319945853">"Izlaist"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Tālāk &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Tālāk"</string>
+    <string name="exit" msgid="1905187380359981199">"Iziet"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Iestatījumi &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Iestatījumi"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Lietotnei Ziņojumapmaiņa ir nepieciešama piekļuves atļauja īsziņām, kā arī lietotnēm Tālrunis un Kontaktpersonas."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Atļaujas varat mainīt sadaļā Iestatījumi &gt; Lietotnes &gt; Ziņojumapmaiņa &gt; Atļaujas."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Atļaujas varat mainīt sadaļā Iestatījumi &gt; Lietotnes &gt; Ziņojumapmaiņa &gt; Atļaujas."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Biežāk izmantotās"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Visas kontaktpersonas"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Nosūtīt uz: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Uzņemt attēlus vai video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Izvēlieties attēlus no šīs ierīces."</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Ierakstīt audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Fotoattēla izvēle"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Saturs ir atlasīts."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Satura atlase ir noņemta."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Atlasīts: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"attēls, <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"attēls"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Ierakstīt audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Kopīgot"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Tikko"</string>
+    <string name="posted_now" msgid="867560789350406701">"Tikko"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> stundas</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> stunda</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> stundas</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> dienas</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> diena</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dienas</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> nedēļas</item>
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> nedēļa</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> nedēļas</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> mēneši</item>
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mēnesis</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mēneši</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> gadi</item>
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> gads</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> gadi</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0. klases ziņojums"</string>
+    <string name="save" msgid="5081141452059463572">"Saglabāt"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Ierīcē ir maz vietas. Lai atbrīvotu vietu, lietotnē Ziņojumapmaiņa tiks automātiski dzēsti vecāki ziņojumi."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Paliek maz brīvas vietas"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Kamēr ierīcē nebūs vairāk vietas, lietotnē Ziņojumapmaiņa, iespējams, nevarēs sūtīt vai saņemt ziņojumus."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Maz vietas īsziņām. Iespējams, jums būs jādzēš īsziņas."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Tālruņa numura apstiprināšana"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Šī vienreizējā darbība ir nepieciešama, lai lietotnē Ziņojumapmaiņa tiktu pareizi piegādāti jūsu grupas ziņojumi."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Tālruņa numurs"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Dzēst visus ziņojumus, kas ietver multivides saturu"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Dzēst ziņojumus, kas vecāki par <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automātiski dzēst ziņojumus, kas vecāki par: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorēt"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Vai dzēst visas ziņas, kurās ietverts multivides saturs?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Vai dzēst ziņojumus, kas vecāki par: <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Vai dzēst ziņojumus, kas vecāki par: <xliff:g id="DURATION">%s</xliff:g>, un ieslēgt automātisko dzēšanu?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> rakstīja"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Jūs rakstījāt"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Ziņojums no <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Jūs nosūtījāt ziņojumu"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Notiek sūtīšana…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Neizdevās nosūtīt. Pieskarieties, lai mēģinātu vēlreiz."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Neizdevās nosūtīt. Notiek atkārtots mēģinājums…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Sūtiet vēlreiz vai dzēsiet vienumu"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Veiciet balss zvanu uz avārijas dienesta tālruņa numuru. Pašlaik nevar nosūtīt īsziņu."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Neizdevās"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Jauna lejupielādējama multiziņa"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Jauna multiziņa"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nevarēja lejupielādēt"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Pieskarieties, lai mēģinātu vēlreiz"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Pieskarieties, lai lejupielādētu"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Lejupielādējiet vai dzēsiet"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Notiek lejupielāde…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Ziņojums nav pieejams, vai ir beidzies tā derīguma termiņš"</string>
+    <string name="mms_info" msgid="3402311750134118165">"lielums: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>; derīgs līdz: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nevar nosūtīt ziņojumu. Adresāts nav derīgs."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Pakalpojums tīklā nav aktivizēts."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Nevarēja nosūtīt tīkla problēmas dēļ."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Ziņa nav pieejama, vai ir beidzies tās derīguma termiņš."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Bez temata)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Nezināms sūtītājs"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Piegādāts"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nevarēja lejupielādēt no sūtītāja <xliff:g id="FROM">%2$s</xliff:g> saņemto ziņojumu “<xliff:g id="SUBJECT">%1$s</xliff:g>”."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Nevarēja pabeigt datu bāzes darbību, jo nav vietas atmiņā."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Ziņojums netika nosūtīts."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Lietotnē Ziņojumapmaiņa netika nosūtīti daži ziņojumi."</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="zero"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunās</item>
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunā</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunās</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Ziņojums nav lejupielādēts."</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Lietotnē Ziņojumapmaiņa nav lejupielādēti daži ziņojumi."</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="zero"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunās</item>
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunā</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ziņojumi <xliff:g id="CONVERSATIONS">%d</xliff:g> sarunās</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Ziņojums netika nosūtīts uz tālruņa numuru <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Veiciet balss zvanu uz avārijas dienesta tālruņa numuru. Pašlaik nevar nosūtīt īsziņu uz tālruņa numuru <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="zero"><xliff:g id="MESSAGES">%d</xliff:g> jauni ziņojumi</item>
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> jauns ziņojums</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> jauni ziņojumi</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Ieslēgt"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera nav pieejama."</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera nav pieejama."</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video tveršana nav pieejama."</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nevar saglabāt multivides failu."</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nevar uzņemt attēlu"</string>
+    <string name="back" msgid="1477626055115561645">"Atpakaļ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arhīvs"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Dzēst"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arhivēt"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Izņemt no arhīva"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Izslēgt paziņojumus"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Ieslēgt paziņojumus"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Pievienot kontaktpersonu"</string>
+    <string name="action_download" msgid="7786338136368564146">"Lejupielādēt"</string>
+    <string name="action_send" msgid="377635240181672039">"Sūtīt"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Dzēst"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vai dzēst šo ziņojumu?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Šo darbību nevar atsaukt."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Dzēst"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="zero">Vai dzēst šīs sarunas?</item>
+      <item quantity="one">Vai dzēst šīs sarunas?</item>
+      <item quantity="other">Vai dzēst šīs sarunas?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Dzēst"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Atcelt"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kam:"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Atlasīt vairākus attēlus"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Apstiprināt atlasi"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"Vēl <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Nevar ierakstīt audio. Mēģiniet vēlreiz."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Nevar atskaņot audio. Mēģiniet vēlreiz."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Nevarēja saglabāt audio. Mēģiniet vēlreiz."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Pieskarieties un turiet."</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Attēls"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audioklips"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videoklips"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktpersonas kartīte"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Lejupielādēt"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Atbildēt ar īsziņu"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Atbildēt ar MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Atbildēt"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> dalībnieki</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dalībnieks</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dalībnieki</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Es"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontaktpersona ir bloķēta un arhivēta"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontaktpersona ir atbloķēta un atarhivēta."</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Arhivētas: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Atcelta arhivēšana: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Paziņojumi ir izslēgti."</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Paziņojumi ir ieslēgti."</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Iestatīšana ir pabeigta. Vēlreiz pieskarieties vienumam Sūtīt."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Lietotne Ziņojumapmaiņa ir sekmīgi iestatīta kā noklusējuma īsziņu lietotne."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="zero">Atmest pielikumus</item>
+      <item quantity="one">Atmest pielikumu</item>
+      <item quantity="other">Atmest pielikumus</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audio pielikums"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Atskaņot audio pielikumu"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pārtraukt"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Ziņojums no lietotāja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Neizdevās saņemt ziņojumu no kontaktpersonas <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Ziņojums no kontaktpersonas <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Nenosūtīts ziņojums kontaktpersonai <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Notiek ziņojuma sūtīšana kontaktpersonai <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Neizdevās nosūtīt ziņojumu kontaktpersonai <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Ziņojums kontaktpersonai <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Neizdevās saņemt ziņojumu no kontaktpersonas <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Ziņojums no kontaktpersonas <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Nenosūtīts ziņojums grupai <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Notiek ziņojuma sūtīšana grupai <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Neizdevās nosūtīt ziņojumu grupai <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Ziņojums grupai <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Laiks: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Radās problēma ar ziņojumu. Pieskarieties, lai mēģinātu vēlreiz."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Saruna ar grupu: <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Dzēst tēmu"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Uzņemt video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Uzņemt fotoattēlu"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Uzņemt attēlu"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Sākt video ierakstīšanu"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Pārslēgties uz pilnekrāna kameru"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Pārslēgties no priekšējās kameras uz aizmugurējo kameru un otrādi"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Pārtraukt ierakstīšanu un pievienot videoklipu"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Pārtraukt videoklipa ierakstīšanu"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotoattēli lietotnē Ziņojumapmaiņa"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="zero"><xliff:g id="QUANTITY_2">%d</xliff:g> fotoattēli tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> fotoattēls tika saglabāts albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotoattēli tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="zero"><xliff:g id="QUANTITY_2">%d</xliff:g> videoklipi tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> videoklips tika saglabāts albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videoklipi tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="zero"><xliff:g id="QUANTITY_2">%d</xliff:g> pielikumi tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> pielikums tika saglabāts albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> pielikumi tika saglabāti albumā “<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="zero"><xliff:g id="QUANTITY_1">%d</xliff:g> pielikumi tika saglabāti mapē “Lejupielādes”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> pielikums tika saglabāts mapē “Lejupielādes”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> pielikumi tika saglabāti mapē “Lejupielādes”</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="zero">Tika saglabāti <xliff:g id="QUANTITY_1">%d</xliff:g> pielikumi.</item>
+      <item quantity="one">Tika saglabāts <xliff:g id="QUANTITY_1">%d</xliff:g> pielikums.</item>
+      <item quantity="other">Tika saglabāti <xliff:g id="QUANTITY_1">%d</xliff:g> pielikumi.</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="zero">Nevarēja saglabāt <xliff:g id="QUANTITY_1">%d</xliff:g> pielikumus.</item>
+      <item quantity="one">Nevarēja saglabāt <xliff:g id="QUANTITY_1">%d</xliff:g> pielikumu.</item>
+      <item quantity="other">Nevarēja saglabāt <xliff:g id="QUANTITY_1">%d</xliff:g> pielikumus.</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Multiziņas pielikums tika saglabāts."</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Iestatījumi"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arhīvs"</string>
+    <string name="action_close" msgid="1840519376200478419">"Aizvērt"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Multiziņa"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Papildu"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Atkļūdot"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Paziņojumi"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Signāls"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Klusums"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrozvans"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloķēts"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Īsziņu piegādes atskaites"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Pieprasiet piegādes atskaiti par katru sūtīto īsziņu."</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automātiski izgūt"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automātiski izgūstiet multiziņas."</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Autom. izgūšana viesabon. laikā"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automātiska multiziņu izgūšana viesabonēšanas laikā"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Grupas ziņojumapmaiņa"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Izmantojiet multiziņu, lai vairākiem adresātiem nosūtītu vienu ziņu."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Noklusējuma īsziņu lietotne"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Noklusējuma īsziņu lietotne"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Jūsu tālruņa numurs"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Nezināms"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Izejošo ziņojumu signāli"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Īsziņu izrakstīšana"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Izrakstiet saņemto īsziņu jēldatus ārējā krātuves failā."</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Multiziņu izrakstīšana"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Izrakstiet saņemto multiziņu jēldatus ārējā krātuves failā."</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Bezvadu brīdinājumi"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Ziņojuma opcijas"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopēt tekstu"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Skatīt detalizētu informāciju"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Dzēst"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Pārsūtīt"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalizēta informācija par ziņojumu"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Veids: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Īsziņa"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multiziņa"</string>
+    <string name="from_label" msgid="1947831848146564875">"No: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kam: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Nosūtīts: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Saņemts: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Temats: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Lielums: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritāte: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Augsta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Parasta"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Zema"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Sūtītāja adrese ir slēpta"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Ziņojumu nevar nosūtīt, kamēr tiek ielādēti pielikumi."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nevar ielādēt pielikumu. Mēģiniet vēlreiz."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Tīkls nav gatavs lietošanai. Mēģiniet vēlreiz."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Dzēst tekstu"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Pārslēgties starp teksta un ciparu ievadīšanu"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Pievienot vēl dalībniekus"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Apstiprināt dalībniekus"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Sākt jaunu sarunu"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Atlasīt šo vienumu"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Atskaņot videoklipu"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Personas un opcijas"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Atkļūdot"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Personas un opcijas"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Vispārīgi"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Sarunas dalībnieki"</string>
+    <string name="action_call" msgid="6596167921517350362">"Zvanīt"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Sūtīt ziņojumu"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Sūtiet īsziņu,&lt;br/&gt;&lt;small&gt;izmantojot šo SIM: <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="zero">Sūtīt fotoattēlus</item>
+      <item quantity="one">Sūtīt fotoattēlus</item>
+      <item quantity="other">Sūtīt fotoattēlus</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="zero">Sūtīt audio failus</item>
+      <item quantity="one">Sūtīt audio failus</item>
+      <item quantity="other">Sūtīt audio failus</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="zero">Sūtīt videoklipus</item>
+      <item quantity="one">Sūtīt videoklipus</item>
+      <item quantity="other">Sūtīt videoklipus</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="zero">Sūtīt kontaktpersonu kartītes</item>
+      <item quantity="one">Sūtīt kontaktpersonu kartītes</item>
+      <item quantity="other">Sūtīt kontaktpersonu kartītes</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="zero">Sūtīt pielikumus</item>
+      <item quantity="one">Sūtīt pielikumus</item>
+      <item quantity="other">Sūtīt pielikumus</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="zero">Nav atlasīts neviens pielikums.</item>
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pielikums ir gatavs nosūtīšanai.</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> pielikumi ir gatavi nosūtīšanai.</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Sūtīt atsauksmes"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Skatīt Google Play veikalā"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informācija par versiju"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versija %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Atklātā pirmkoda licences"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Paziņojumi"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Sasniegts pielikumu ierobežojums."</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Neizdevās ielādēt pielikumu."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Vai pievienot kontaktpersonām?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Pievienot kontaktpersonu"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Temats"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Temats: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Notiek kontaktpersonas kartītes ielāde…"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nevarēja ielādēt kontaktpersonas kartīti."</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Skatiet kontaktpersonas kartīti"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> kontaktpersonas</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> kontaktpersona</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktpersonas</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktpersonu kartītes"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Dzimšanas diena"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Piezīmes"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Ziņojuma pārsūtīšana"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Atbildēt"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Īsziņas ir atspējotas."</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Lai sūtītu īsziņas, iestatiet lietotni Ziņojumapmaiņa kā noklusējuma īsziņu lietotni."</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Iestatiet lietotni Ziņojumapmaiņa kā noklusējuma īsziņu lietotni."</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Mainīt"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Lai saņemtu īsziņas, iestatiet lietotni Ziņojumapmaiņa kā noklusējuma īsziņu lietotni."</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Īsziņu sūtīšanai nav atlasīta vēlamā SIM karte"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Ierīces īpašnieks nav atļāvis šīs lietotnes darbību."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Labi"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Sarunā ir pārāk daudz dalībnieku."</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="zero">Nederīgas kontaktpersonas</item>
+      <item quantity="one">Nederīga kontaktpersona</item>
+      <item quantity="other">Nederīgas kontaktpersonas</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nevarēja ielādēt kameras attēlu."</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Jūs: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Melnraksts"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Jaunas sarunas tiks rādītas šeit."</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Šeit tiek rādītas arhivētās sarunas."</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Notiek sarunu ielāde..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Attēls"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audioklips"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Videoklips"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktpersonas kartīte"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Multiziņa"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Atsaukt"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Mēģināt vēlreiz"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Ievadiet kontaktpersonas vārdu vai tālruņa numuru, lai sāktu rakstīt jaunu ziņojumu."</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloķēt"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloķēt: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Atbloķēt: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vai bloķēt <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Jūs turpināsiet saņemt ziņojumus no šī numura, taču vairs nesaņemsiet par tiem paziņojumus. Šī saruna tiks arhivēta."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Bloķētās kontaktpersonas"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ATBLOĶĒT"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Bloķētās kontaktpersonas"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Izvēlēties attēlu no dokumentu bibliotēkas"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Notiek ziņojuma sūtīšana"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Ziņojums nosūtīts"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobilo datu savienojums ir izslēgts. Pārbaudiet iestatījumus."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Lidojuma režīmā nevar nosūtīt ziņojumus."</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Ziņojumu nevarēja nosūtīt."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Ziņojums lejupielādēts"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobilo datu savienojums ir izslēgts. Pārbaudiet iestatījumus."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Ziņojumus nevar lejupielādēt lidojuma režīmā"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Ziņojumu nevarēja lejupielādēt"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nulle"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Viens"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Divi"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trīs"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Četri"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pieci"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seši"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Septiņi"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Astoņi"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Deviņi"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nevar nosūtīt ziņojumu: operatora <xliff:g id="CARRIERNAME">%1$s</xliff:g> kļūda <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nevar nosūtīt ziņojumu: nezināma operatora kļūda <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Pārs.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Ziņojums netika nosūtīts: pakalpojums nav aktivizēts tīklā."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Ziņojums nav nosūtīts: nederīga galamērķa adrese"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Ziņojums nav nosūtīts: nederīgs ziņojums"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Ziņojums nav nosūtīts: neatbalstīts saturs"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Ziņojums nav nosūtīts: neatbalstīts ziņojums"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Ziņojums nav nosūtīts: pārāk liels"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Jauns ziņojums"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Skatīt"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Attēls"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Neizdevās atrast atbilstošu lietojumprogrammu."</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Noņemt adresātu"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Jauns ziņojums"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Atcelt"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Piekļuves punkta rediģēšana"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nav iestatīts"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nosaukums"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Multiziņu starpniekserveris"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Multiziņu ports"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN veids"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Dzēst APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Jauns APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Saglabāt"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Atmest"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Nosaukuma lauks nedrīkst būt tukšs."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN lauks nedrīkst būt tukšs."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC laukā ir jābūt 3 cipariem."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC laukā ir jābūt 2 vai 3 cipariem."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Notiek APN noklusējuma iestatījumu atjaunošana."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Atiestatīt noklusējuma vērtības"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Noklusējuma APN iestatījumu atiestatīšana ir pabeigta."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Bez nosaukuma"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Piekļuves punktu nosaukumi"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Jauns APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Piekļuves punkta nosaukuma iestatījumi šim lietotājam nav pieejami."</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Vai kopēt starpliktuvē?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopēt"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"šajā SIM: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Vispārīgi"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Papildu"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Vispārīgi iestatījumi"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Papildu iestatījumi"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM kartes “<xliff:g id="SIM_NAME">%s</xliff:g>” iestatījumi"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Sūtīt atsevišķas īsziņas visiem adresātiem (atbildes saņemsiet tikai jūs)"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Sūtīt vienu multiziņu visiem adresātiem"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nezināms numurs"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Jauns ziņojums"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Jauns ziņojums"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM kartes atlasītājs"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Atlasīta <xliff:g id="SIM_0">%1$s</xliff:g>, SIM kartes atlasītājs"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Rediģēt tematu"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Atlasīt SIM karti vai rediģēt tematu"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Pieskarieties un turiet, lai ierakstītu skaņu."</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Sākt jaunu sarunu"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Ziņojumapmaiņa"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Sarunu saraksts lietotnē Ziņojumapmaiņa"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Ziņojumapmaiņa"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Jauns ziņojums"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Sarunu saraksts"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Notiek sarunu ielāde"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Notiek ziņojumu ielāde."</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Skatīt citas sarunas"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Skatīt vairāk ziņojumu"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Saruna ir izdzēsta"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Saruna dzēsta. Pieskarieties, lai skatītu citu sarunu lietotnē Ziņojumapmaiņa."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloķēts"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Atbloķēts"</string>
+    <string name="db_full" msgid="8459265782521418031">"Krātuvē ir maz vietas. Daļa datu var tikt zaudēta."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Pielikumu atlasīšana"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Apstiprināt atlasi"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Atlasīti: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Lūdzu, noņemiet vienu vai vairākus pielikumus un mēģiniet vēlreiz."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Varat mēģināt sūtīt ziņojumu, taču tas, iespējams, netiks piegādāts, ja vien nenoņemsiet vienu vai vairākus pielikumus."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Ziņojumam var pievienot tikai vienu videoklipu. Lūdzu, noņemiet liekos videoklipus un mēģiniet vēlreiz."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Lietotnē Ziņojumapmaiņa neizdevās ielādēt pielikumu."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Tik un tā sūtīt"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Nevarēja sākt sarunu"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Atlasīts: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-mk/arrays.xml b/res/values-mk/arrays.xml
new file mode 100644
index 0000000..eba8db7
--- /dev/null
+++ b/res/values-mk/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"без наслов"</item>
+    <item msgid="272485471009191934">"без тема"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Да"</item>
+    <item msgid="6049132459802288033">"Не"</item>
+    <item msgid="3084376867445867895">"Во ред"</item>
+    <item msgid="3155097332660174689">"Хехе"</item>
+    <item msgid="2611328818571146775">"Фала"</item>
+    <item msgid="4881335087096496747">"Се согласувам"</item>
+    <item msgid="2422296858597420738">"Убаво"</item>
+    <item msgid="4805581752819452687">"На пат сум"</item>
+    <item msgid="4746700499431366214">"Во ред, ќе ти јавам подоцна"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
new file mode 100644
index 0000000..16f60c9
--- /dev/null
+++ b/res/values-mk/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Пораки"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Пораки"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Изберете разговор"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Поставки"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Испрати порака"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Додај прилог"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Помош"</string>
+    <string name="welcome" msgid="2857560951820802321">"Добре дојдовте"</string>
+    <string name="skip" msgid="7238879696319945853">"Прескокни"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Следно &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Следно"</string>
+    <string name="exit" msgid="1905187380359981199">"Излези"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Поставки &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Поставки"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"На Messaging му треба дозвола за СМС, телефон и контакти."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Дозволите може да ги промените во Поставки &gt; Апликации &gt; Messaging &gt; Дозволи."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Дозволите може да ги промените во Поставки, Апликации, Messaging, Дозволи."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Чести"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Сите контакти"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Испрати на <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Снимај слики или видео"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Изберете слики од уредот"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Снимај аудио"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Избери фотографија"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медиумот е избран."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Медиумот е неизбран."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Избрани: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"слика <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"слика"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Снимај аудио"</string>
+    <string name="action_share" msgid="2143483844803153871">"Сподели"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Пред малку"</string>
+    <string name="posted_now" msgid="867560789350406701">"Сега"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> мин.</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> мин.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> час</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> часа</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ден</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> дена</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> седмица</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> седмици</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> месец</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> месеци</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> година</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> години</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Порака 0 класа"</string>
+    <string name="save" msgid="5081141452059463572">"Зачувај"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Уредот нема доволно меморија. Messaging автоматски ќе ги брише постарите текстуални пораки за да ослободи простор."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Меморијата е речиси полна"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaging може да не испраќа или прима пораки сѐ додека не се ослободи повеќе простор на уредот."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Малку простор за складирање СМС. Можеби ќе треба да избришете пораки."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Потврдете го својот телефонски број"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Со овој еднократен чекор ќе се погрижите Messaging правилно да ви ги испорачува групните пораки."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Телефонски број"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Избриши ги сите пораки со медиуми"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Избриши ги пораките постари од <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Автоматско бришење пораки постари од <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Игнорирај"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Да се избришат сите пораки со медиуми?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Да се избришат пораките постари од <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Да се избришат пораките постари од <xliff:g id="DURATION">%s</xliff:g> и да се вклучи автоматското бришење?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> рече"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Рековте"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Порака од <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Испративте порака"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Се испраќа..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Не се испрати. Допрете за да се обидете повторно."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Не се испрати. Се обидуваме повторно…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Испратете повторно или избришете"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Направете гласовен повик до службите за итни случаи. Вашата текстуална порака не може да се испорача во ова време."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Неуспешно"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Нова ММС-порака за преземање"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Нова ММС-порака"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Не можеше да се преземе"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Допрете да се обидете повторно"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Допри за преземање"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Преземете или избришете"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Се презема..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Пораката е истечена или не е достапна"</string>
+    <string name="mms_info" msgid="3402311750134118165">"големина: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, истекување: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Не може да се испрати. Примачот не е важечки."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Услугата не е активирана на мрежата"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Не можеше да се испрати поради проблем со мрежата"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Пораката е истечена или не е достапна"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Без наслов)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Непознат испраќач"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Доставено"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Пораката <xliff:g id="SUBJECT">%1$s</xliff:g> од <xliff:g id="FROM">%2$s</xliff:g> не може да се преземе."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Не може да се заврши дејството во базата со податоци поради мала меморија"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Пораката не се испрати"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Некои пораки не се испратени во Messaging"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> пораки во <xliff:g id="CONVERSATIONS">%d</xliff:g> разговор</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> пораки во <xliff:g id="CONVERSATIONS">%d</xliff:g> разговори</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Пораката не е преземена"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Некои пораки не се преземени во Messaging"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> пораки во <xliff:g id="CONVERSATIONS">%d</xliff:g> разговор</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> пораки во <xliff:g id="CONVERSATIONS">%d</xliff:g> разговори</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Пораката до <xliff:g id="NUMBER">%1$s</xliff:g> не се испрати"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Направете гласовен повик до службите за итни случаи. Вашата текстуална порака до <xliff:g id="NUMBER">%1$s</xliff:g> не може да се испорача во ова време."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> нова порака</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> нови пораки</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Започни"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Нема фотоапарат на располагање"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Нема фотоапарат на располагање"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Снимањето видео не е достапно"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Медиумите не може да се зачуваат"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Не може да фотографира"</string>
+    <string name="back" msgid="1477626055115561645">"Назад"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архивирано"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Бришење"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архивирање"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Извади од архива"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Исклучи известувања"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Вклучи известувања"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Додај контакт"</string>
+    <string name="action_download" msgid="7786338136368564146">"Преземи"</string>
+    <string name="action_send" msgid="377635240181672039">"Испрати"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Избриши"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Да се избрише пораката?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Дејството не може да се врати."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Избриши"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Да се избрише разговоров?</item>
+      <item quantity="other">Да се избришат разговориве?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Избриши"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Откажи"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"До"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Избери повеќе слики"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Потврдете го изборот"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Аудиото не може да се сними. Обидете се повторно."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Аудиото не може да се пушти. Обидете се повторно."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Аудиото не можеше да се зачува. Обидете се повторно."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Допри и задржи"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Слика"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудиоклип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Картичка за контакти"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Преземи"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Одговори преку СМС"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Одговори преку ММС"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Одговори"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> учесник</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> учесници</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Јас"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Контактот е блокиран и архивиран"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Одблокиран и одархивиран контакт"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> архивирани"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> извадени од архива"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Известувањата се исклучени"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Известувањата се вклучени"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Сè е подготвено. Допрете Испрати повторно."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaging е успешно поставен како стандардна апликација за СМС."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Отфрли го прилогот</item>
+      <item quantity="other">Отфрли ги прилозите</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудио прилог"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Репродуцирај аудио прилог"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Пауза"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Порака од <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Неуспешна порака од <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Порака од <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Неиспратена порака до <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Се испраќа порака до <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Неуспешна порака до <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Порака до <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Неуспешна порака од <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Порака од <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Неиспратена порака до <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Се испраќа порака до <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Неуспешна порака до <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Порака до <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Неуспешна порака. Допрете за да се обидете повторно."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Разговор со <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Избриши тема"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Снимај видео"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Сними фотографија"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Фотографирај"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Започни со снимање видео"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Префрлете на камера на цел екран"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Префрли меѓу предна и задна камера"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Престани со снимање и прикачи видео"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Прекини со снимање видео"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Фотографии во Messaging"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографија се зачува во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографии се зачуваа во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> видео се зачува во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> видеа се зачуваа во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> прилог се зачува во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> прилози се зачуваа во албумот „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> прилог се зачува во „Преземања“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прилози се зачуваа во „Преземања“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one">Зачуван е <xliff:g id="QUANTITY_1">%d</xliff:g> прилог</item>
+      <item quantity="other">Зачувани се <xliff:g id="QUANTITY_1">%d</xliff:g> прилози</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Не можеше да се зачува <xliff:g id="QUANTITY_1">%d</xliff:g> прилог</item>
+      <item quantity="other">Не можеше да се зачуваат <xliff:g id="QUANTITY_1">%d</xliff:g> прилози</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Зачуван ММС-прилог"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Поставки"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архивирано"</string>
+    <string name="action_close" msgid="1840519376200478419">"Затвори"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"ММС"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Напредни"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Отстрани грешка"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Известувања"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Звук"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"На тивко"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Вибрации"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Блокирано"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Извештаи за испорака на СМС"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Побарајте извештај за испорака за секоја СМС што ја испраќате"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Автоматско преземање"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Преземај ММС-пораки автоматски"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Автоматско преземање во роаминг"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Автоматски преземај MMS додека си во роаминг"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Групно испраќање пораки"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Користи ММС за испраќање една порака кога има повеќе примачи"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Стандардна СМС апликација"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Стандардна СМС апликација"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Вашиот телефонски број"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Непознато"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Звуци на појдовни пораки"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Извади СМС"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Извади ги примените необработени податоци за СМС на надворешна датотека за складирање"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Извади ММС"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Извади ги примените необработени податоци за ММС на надворешна датотека за складирање"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Безжични предупредувања"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Опции на порака"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Копирај текст"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Прикажи детали"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Избриши"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Проследи"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Детали на порака"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Тип: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Текстуална порака"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мултимедијална порака"</string>
+    <string name="from_label" msgid="1947831848146564875">"Од: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"До: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Испратено: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Примени: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Предмет: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Големина: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Приоритет: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"СИМ: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Високо"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Нормално"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Ниско"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"СИМ <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Скриена адреса на испраќачот"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Не може да се испрати порака додека се вчитуваат прилозите."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Прилогот не може да се вчита. Обидете се повторно."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Мрежата не е подготвена. Обидете се повторно."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Избриши текст"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Префрлајте меѓу внесување текст и броеви"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Додај повеќе учесници"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Потврди учесници"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Започнете нов разговор"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Изберете ја ставкава"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Пушти видео"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Луѓе и опции"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Отстрани грешка"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Луѓе и опции"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Општи"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Луѓе во овој разговор"</string>
+    <string name="action_call" msgid="6596167921517350362">"Повикај"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Испрати порака"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Испратете порака &lt;br/&gt;&lt;small&gt;од <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Испрати ја фотографијата</item>
+      <item quantity="other">Испрати ги фотографиите</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Испрати го аудиото</item>
+      <item quantity="other">Испрати ги аудиата</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Испрати го видеото</item>
+      <item quantity="other">Испрати ги видеата</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Испрати ја картичката за контакт</item>
+      <item quantity="other">Испрати ги картичките за контакт</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Испрати го прилогот</item>
+      <item quantity="other">Испрати ги прилозите</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прилог е подготвен за испраќање</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прилози се подготвени за испраќање</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Испрати повратни информации"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Прикажи во продавницата на Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Информации за верзијата"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Верзија %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Лиценци со отворен код"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Известувања"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Достигнато е ограничувањето за прилози"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Не успеа да се вчита прилогот."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Да додадеме во контакти?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Додај контакт"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Предмет"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Предмет: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Се вчитува картичката за контакт"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Картичката за контакт не можеше да се вчита"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Прикажи картичка за контакти"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> контакт</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контакти</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Картички за контакт"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Роденден"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Белешки"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Проследи порака"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Одговори"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"СМС-пораките се оневозможени"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"За испраќање, поставете го Messaging како стандардна апликација за СМС"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Поставете го Messaging како стандардна апликација за СМС"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Промени"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"За примање пораки, поставете го Messaging како стандардна апликација за СМС"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Не е избрана претпочитана СИМ за испраќање СМС-пораки"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Оваа апликација не е дозволена од сопственикот на уредот."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Во ред"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Премногу учесници во разговорот"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Неважечки контакт</item>
+      <item quantity="other">Неважечки контакти</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Слика од камерата не можеше да се вчита"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Вие: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Нацрт"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Штом започнете нов разговор, ќе го видите наведен тука"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Архивираните разговори се појавуваат тука"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Се вчитуваат разговори…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Слика"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудиоклип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Картичка за контакти"</string>
+    <string name="mms_text" msgid="1528791558806015806">"ММС"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Врати"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Обидете се повторно"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Внесете име на контактот или телефонски број за да започнете нова порака"</string>
+    <string name="action_block" msgid="9032076625645190136">"Блокирај"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Блокирај <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Одблокирај <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Да се блокира <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Ќе продолжите да добивате пораки од овој број, но веќе нема да добивате известувања. Разговорот ќе се архивира."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Блокирани контакти"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ОДБЛОКИРАЈ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Блокирани контакти"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Изберете слика од библиотеката со документи"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Пораката се испраќа"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Пораката е испратена"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Мобилните податоци се исклучени. Проверете ги поставките."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Не може да се испраќаат пораки во авионски режим"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Пораката не може да се испрати."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Пораката е преземeна"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Мобилните податоци се исклучени. Проверете ги поставките."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Не може да се преземаат пораки во авионски режим"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Пораката не можеше да се преземе"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Нула"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Еден"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Два"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Три"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Четири"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Пет"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Шест"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Седум"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Осум"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Девет"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Пораката не може да се испрати преку <xliff:g id="CARRIERNAME">%1$s</xliff:g>, грешка <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Пораката не може да се испрати преку непознат давател на услуга, грешка <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Препрати: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Пораката не се испрати: услугата не е активирана на мрежата"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Пораката не е испратена: неважечка адреса на одредиштето"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Пораката не е испратена: неважечка порака"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Пораката не е испратена: неподдржана содржина"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Пораката не е испратена: неподдржана порака"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Пораката не е испратена: преголема"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Нова порака"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Прикажи"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Слика"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Не може да се најде соодветна апликација"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Отстрани го примачот"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Нова порака"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Откажи"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Уреди пристапна точка"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Не е поставено"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Име"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Име на пристапна точка (APN)"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"ММСЦ"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Прокси на ММС"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Порта за ММС"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Тип APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Избриши APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Ново APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Зачувај"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Отфрли"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Полето за име не може да биде празно."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN не може да биде празна."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Полето MNC мора да содржи 3 цифри."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Полето MNC мора да содржи 2 или 3 цифри."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Враќање стандардни поставки на APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Ресетирај на стандардни вредности"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Ресетирањето стандардни поставки на APN е завршено."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Без наслов"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Имиња на пристапни точки"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Поставување APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Ново APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Поставките за името на пристапната точка не се достапни за овој корисник"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Копирајте во таблата со исечоци?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Копирај"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"до <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Општи"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Напредни"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Општи поставки"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Напредни поставки"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"СИМ „<xliff:g id="SIM_NAME">%s</xliff:g>“"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Испратете поединечни СМС-пораки до сите примачи. Само вие ќе добивате одговори"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Испратете единствена ММС-порака до сите примачи"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Непознат број"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Нова порака"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Нова порака."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Бирач на СИМ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> е избран, бирач на СИМ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Уреди предмет"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Избери СИМ или уреди предмет"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Допри и задржи за снимање аудио"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Започнете нов разговор"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Список на Messaging"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Нова порака"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Список со разговори"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Разговорите се вчитуваат"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Се вчитуваат пораки"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Прикажи повеќе разговори"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Прикажи повеќе пораки"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Конверзацијата е избришана"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Разговорот е избришан. Допрете за да се прикаже друг разговор на Messaging"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Блокирано"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Одблокирано"</string>
+    <string name="db_full" msgid="8459265782521418031">"Просторот за складирање е премногу мал. Некои податоци може да се изгубат."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Изберете прилози"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Потврдете го изборот"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Избрани <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Отстранете еден или повеќе прилози и обидете се повторно."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Може да се обидете да ја испратите пораката, но можеби нема да се испорача, освен ако не отстраните еден или повеќе прилози."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Може да испраќате само едно видео по порака. Отстранете ги дополнителните видеа и обидете се повторно."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging не успеа да го вчита прилогот."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Сепак испрати"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Не може да се започне разговор"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Избрана е <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-ml/arrays.xml b/res/values-ml/arrays.xml
new file mode 100644
index 0000000..7454e1f
--- /dev/null
+++ b/res/values-ml/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"വിഷയമില്ല"</item>
+    <item msgid="272485471009191934">"വിഷയമൊന്നുമില്ല"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ഉവ്വ്"</item>
+    <item msgid="6049132459802288033">"ഇല്ല"</item>
+    <item msgid="3084376867445867895">"ശരി"</item>
+    <item msgid="3155097332660174689">"ഹിഹി"</item>
+    <item msgid="2611328818571146775">"നന്ദി"</item>
+    <item msgid="4881335087096496747">"ഞാൻ അംഗീകരിക്കുന്നു"</item>
+    <item msgid="2422296858597420738">"കൊള്ളാം"</item>
+    <item msgid="4805581752819452687">"മറുപടി നൽകാൻ തയ്യാറാണ്"</item>
+    <item msgid="4746700499431366214">"ശരി, പിന്നീട് നിങ്ങളുമായി ബന്ധപ്പെടാൻ എന്നെ അനുവദിക്കുക"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
new file mode 100644
index 0000000..b292525
--- /dev/null
+++ b/res/values-ml/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"സംഭാഷണം തിരഞ്ഞെടുക്കുക"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ക്രമീകരണങ്ങൾ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"സന്ദേശം അയയ്ക്കൂ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ഒരു അറ്റാച്ചുമെന്റ് ചേർക്കുക"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"സഹായം"</string>
+    <string name="welcome" msgid="2857560951820802321">"സ്വാഗതം"</string>
+    <string name="skip" msgid="7238879696319945853">"ഒഴിവാക്കുക"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"അടുത്തത് &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"അടുത്തത്"</string>
+    <string name="exit" msgid="1905187380359981199">"പുറത്തുകടക്കുക"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ക്രമീകരണം &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ക്രമീകരണം"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"SMS, ഫോൺ, കോൺടാക്റ്റുകൾ എന്നിവയിലേക്ക് സന്ദേശമയയ്ക്കലിന് അനുമതി ആവശ്യമാണ്."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ക്രമീകരണം &gt; ആപ്സ് &gt; സന്ദേശമയയ്ക്കൽ &gt; അനുമതികൾ എന്നതിൽ നിങ്ങൾക്ക് അനുമതികൾ മാറ്റാവുന്നതാണ്."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ക്രമീകരണം, ആപ്സ്, സന്ദേശമയയ്ക്കൽ, അനുമതികൾ എന്നതിൽ നിങ്ങൾക്ക് അനുമതികൾ മാറ്റാവുന്നതാണ്."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"പതിവായി കോൺടാക്‌റ്റുചെയ്യുന്നവർ"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"എല്ലാ കോൺടാക്റ്റുകളും"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> എന്നതിലേയ്ക്ക് അയയ്ക്കുക"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ചിത്രങ്ങൾ അല്ലെങ്കിൽ വീഡിയോ എടുക്കുക"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ഈ ഉപകരണത്തിൽ നിന്ന് ചിത്രങ്ങൾ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ഓഡിയോ റെക്കോർഡുചെയ്യുക"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ഫോട്ടോ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"മീഡിയ തിരഞ്ഞെടുത്തിരിക്കുന്നു."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"മീഡിയ തിരഞ്ഞെടുത്തത് മാറ്റി."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ചിത്രം <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ചിത്രം"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ഓഡിയോ റെക്കോർഡുചെയ്യുക"</string>
+    <string name="action_share" msgid="2143483844803153871">"പങ്കിടുക"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ഇപ്പോൾ"</string>
+    <string name="posted_now" msgid="867560789350406701">"ഇപ്പോൾ"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> മിനിറ്റ്</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> മിനിറ്റ്</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> മണിക്കൂർ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> മണിക്കൂർ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ദിവസം</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ദിവസം</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ആഴ്‌ച</item>
+      <item quantity="one">ഒരു ആഴ്‌ച</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> മാസം</item>
+      <item quantity="one">ഒരു മാസം</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> വർഷം</item>
+      <item quantity="one">ഒരു വർഷം</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ക്ലാസ് 0 സന്ദേശം"</string>
+    <string name="save" msgid="5081141452059463572">"സംരക്ഷിക്കുക"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ഉപകരണത്തിൽ ഇടം കുറവാണ്. ഇടം സ്വതന്ത്രമാക്കുന്നതിന് പഴയ സന്ദേശങ്ങളെ സന്ദേശമയയ്ക്കൽ സ്വയമേവ ഇല്ലാതാക്കും."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"സംഭരണയിടം കഴിഞ്ഞു"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"നിങ്ങളുടെ ഉപകരണത്തിൽ കൂടുതൽ ഇടം ലഭ്യമാകുന്നത് വരെ സന്ദേശമയയ്ക്കലിന് സന്ദേശങ്ങൾ അയയ്ക്കാനോ സ്വീകരിക്കാനോ ആയേക്കില്ല."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS സ്റ്റോറേജ്  കുറവാണ്. നിങ്ങൾക്ക് സന്ദേശങ്ങൾ ഇല്ലാതാക്കേണ്ടതായി വരാം."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"നിങ്ങളുടെ ഫോൺ നമ്പർ സ്ഥിരീകരിക്കുക"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"സന്ദേശമയയ്ക്കൽ നിങ്ങളുടെ ഗ്രൂപ്പ് സന്ദേശങ്ങൾ ശരിയായി വിതരണം ചെയ്യുമെന്ന് ഈ ഒറ്റത്തവണയുള്ള ഘട്ടം ഉറപ്പാക്കും."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ഫോണ്‍‌ നമ്പര്‍‌"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"മീഡിയയുള്ള എല്ലാ സന്ദേശങ്ങളും ഇല്ലാതാക്കുക"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> എന്നതിലും പഴയ സന്ദേശങ്ങൾ ഇല്ലാതാക്കുക"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> മുമ്പുള്ള സന്ദേശങ്ങൾ യാന്ത്രികമായി ഇല്ലാതാക്കുക"</string>
+    <string name="ignore" msgid="7063392681130898793">"നിരസിക്കുക"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"മീഡിയയുള്ള എല്ലാ സന്ദേശങ്ങളും ഇല്ലാതാക്കണോ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> മുമ്പുള്ള സന്ദേശങ്ങൾ ഇല്ലാതാക്കണോ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> മുമ്പുള്ള സന്ദേശങ്ങൾ ഇല്ലാതാക്കുകയും യാന്ത്രിക ഇല്ലാതാക്കൽ ഓണാക്കുകയും ചെയ്യണോ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>, പറഞ്ഞു"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"നിങ്ങൾ പറഞ്ഞു"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> എന്നയാളില്‍ നിന്നുള്ള സന്ദേശം"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"നിങ്ങൾ ഒരു സന്ദേശമയച്ചു"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"അയയ്‌ക്കുന്നു…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"അയച്ചില്ല. വീണ്ടും ശ്രമിക്കാൻ സ്‌പർശിക്കുക."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"അയച്ചില്ല. വീണ്ടും ശ്രമിക്കുന്നു..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"വീണ്ടും അയയ്ക്കുക അല്ലെങ്കിൽ ഇല്ലാതാക്കുക"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"അടിയന്തര സേവനങ്ങളിലേക്ക് വോയ്‌സ് കോൾ ചെയ്യുക. ഇപ്പോൾ നിങ്ങളുടെ ടെക്‌സ്‌റ്റ് സന്ദേശം കൈമാറാനായില്ല."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"പരാജയപ്പെട്ടു"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ഡൗൺലോഡുചെയ്യാനുള്ള പുതിയ MMS സന്ദേശം"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"പുതിയ MMS സന്ദേശം"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ഡൗൺലോഡുചെയ്യാനായില്ല"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"വീണ്ടും ശ്രമിക്കാൻ സ്‌പർശിക്കുക"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ഡൗൺലോഡുചെയ്യാൻ സ്‌പർശിക്കുക"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ഡൗൺലോഡുചെയ്യുക അല്ലെങ്കിൽ ഇല്ലാതാക്കുക"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ഡൗൺലോഡുചെയ്യുന്നു…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"സന്ദേശം കാലഹരണപ്പെട്ടു അല്ലെങ്കിൽ ലഭ്യമല്ല"</string>
+    <string name="mms_info" msgid="3402311750134118165">"വലുപ്പം: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, കാലഹരണപ്പെടുന്നത്: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"അയയ്‌ക്കാനാവില്ല. സ്വീകർത്താവ് അസാധുവാണ്."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"സേവനം നെറ്റ്‌വർക്കിൽ സജീവമാക്കിയിട്ടില്ല"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"നെറ്റ്‌വർക്ക് പ്രശ്‌നം കാരണം അയ‌യ്‌ക്കാനായില്ല"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"സന്ദേശം കാലഹരണപ്പെട്ടു അല്ലെങ്കിൽ ലഭ്യമല്ല"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(വിഷയമൊന്നുമില്ല)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"അയച്ചയാൾ അജ്ഞാതനാണ്"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ഡെലിവർ ചെയ്‌തു"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള <xliff:g id="SUBJECT">%1$s</xliff:g> എന്ന സന്ദേശം ഡൗൺലോഡുചെയ്യാനായില്ല."</string>
+    <string name="low_memory" msgid="5300743415198486619">"മെമ്മറി കുറവായതിനാൽ ഡാറ്റാബേസ് പ്രവർത്തനം പൂർത്തിയാക്കാനായില്ല"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"സന്ദേശം അയച്ചില്ല"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"സന്ദേശമയയ്ക്കലിൽ ചില സന്ദേശങ്ങൾ അയച്ചിട്ടില്ല"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> സംഭാഷണങ്ങളിൽ <xliff:g id="MESSAGES_1">%d</xliff:g> സന്ദേശങ്ങൾ</item>
+      <item quantity="one">ഒരു സംഭാഷണത്തിൽ <xliff:g id="MESSAGES_0">%d</xliff:g> സന്ദേശങ്ങൾ</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"സന്ദേശം ഡൗൺലോഡുചെയ്‌തില്ല"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"സന്ദേശമയയ്ക്കലിൽ ചില സന്ദേശങ്ങൾ ഡൗൺലോഡ് ചെയ്തിട്ടില്ല"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> സംഭാഷണങ്ങളിൽ <xliff:g id="MESSAGES_1">%d</xliff:g> സന്ദേശങ്ങൾ</item>
+      <item quantity="one">ഒരു സംഭാഷണത്തിൽ <xliff:g id="MESSAGES_0">%d</xliff:g> സന്ദേശങ്ങൾ</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> എന്ന നമ്പറിലേക്ക് സന്ദേശം അയച്ചില്ല"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"അടിയന്തര സേവനങ്ങളിലേക്ക് വോയ്‌സ് കോൾ ചെയ്യുക. ഇപ്പോൾ നിങ്ങളുടെ ടെക്‌സ്‌റ്റ് സന്ദേശം <xliff:g id="NUMBER">%1$s</xliff:g> എന്ന നമ്പറിലേക്ക് കൈമാറാനായില്ല."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> പുതിയ സന്ദേശങ്ങൾ</item>
+      <item quantity="one">പുതിയ സന്ദേശം</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ആരംഭിക്കുക"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ക്യാമറ ലഭ്യമല്ല"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ക്യാമറ ലഭ്യമല്ല"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"വീഡിയോ എടുക്കൽ ലഭ്യമല്ല"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"മീഡിയ സംരക്ഷിക്കാനാവില്ല"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ചിത്രമെടുക്കാനാവില്ല"</string>
+    <string name="back" msgid="1477626055115561645">"മടങ്ങുക"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ആർക്കൈവുചെയ്‌തവ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ഇല്ലാതാക്കുക"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ആര്‍ക്കൈവുചെയ്യുക"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ആർക്കൈവുചെയ്‌തത് മാറ്റുക"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"അറിയിപ്പുകൾ ഓഫാക്കുക"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"അറിയിപ്പുകൾ ഓണാക്കുക"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"കോൺടാക്റ്റ് ചേർക്കുക"</string>
+    <string name="action_download" msgid="7786338136368564146">"ഡൗൺലോഡ്"</string>
+    <string name="action_send" msgid="377635240181672039">"അയയ്‌ക്കുക"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ഇല്ലാതാക്കുക"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ഈ സന്ദേശം ഇല്ലാതാക്കണോ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ഈ പ്രവർത്തനം പഴയപടിയാക്കാനാകില്ല."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ഇല്ലാതാക്കുക"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ഈ സംഭാഷണങ്ങൾ ഇല്ലാതാക്കണോ?</item>
+      <item quantity="one">ഈ സംഭാഷണം ഇല്ലാതാക്കണോ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ഇല്ലാതാക്കുക"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"റദ്ദാക്കുക"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"സ്വീകര്‍ത്താവ്"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"ഒന്നിലധികം ചിത്രങ്ങൾ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"തിരഞ്ഞെടുത്തവ സ്ഥിരീകരിക്കുക"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"<xliff:g id="COUNT">%d</xliff:g> എണ്ണം കൂടി"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ഓഡിയോ പ്ലേ ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ഓഡിയോ സംരക്ഷിക്കാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"സ്‌പർശിച്ച് പിടിക്കുക"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ചിത്രം"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ഓഡിയോ ക്ലിപ്പ്"</string>
+    <string name="notification_video" msgid="4331423498662606204">"വീഡിയോ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"കോൺടാക്‌റ്റ് കാർഡ്"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ഡൗൺലോഡുചെയ്യുക"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS വഴി മറുപടി നൽകുക"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS വഴി മറുപടി നൽകുക"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"മറുപടി നൽകുക"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> പങ്കെടുക്കുന്നവർ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> പങ്കെടുക്കുന്നയാൾ</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ഞാന്‍"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"കോൺടാക്‌റ്റ് തടഞ്ഞ് ആർക്കൈവുചെയ്‌തു"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"കോൺടാക്റ്റിനെ തടഞ്ഞതും ആർക്കൈവ് ചെയ്‌തതും മാറ്റി"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> എണ്ണം ആർക്കൈവുചെ‌യ്‌തു"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> എണ്ണം ആർക്കൈവുചെയ്‌തത് മാറ്റി"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"അറിയിപ്പുകൾ ഓഫാക്കി"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"അറിയിപ്പുകൾ ഓണാക്കി"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"എല്ലാം സജ്ജീകരിച്ചു. വീണ്ടും അയയ്‌ക്കാൻ സ്‌‌‌പർശിക്കുക."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"സ്ഥിര SMS ആപ്പായി സന്ദേശമയയ്ക്കൽ സജ്ജീകരിച്ചു."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">അറ്റാച്ച്‌മെന്റുകൾ ഉപേക്ഷിക്കുക</item>
+      <item quantity="one">അറ്റാച്ച്‌മെന്റ് ഉപേക്ഷിക്കുക</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ഓഡിയോ അറ്റാച്ചുമെന്റ്"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ഓഡിയോ അറ്റാച്ചുമെന്റ് പ്ലേ ചെയ്യുക"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"താൽക്കാലികമായി നിർത്തുക"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള സന്ദേശം : <xliff:g id="MESSAGE">%2$s</xliff:g> ."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള സന്ദേശം പരാജയപ്പെട്ടു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള സന്ദേശം: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> എന്നതിലേക്ക് സന്ദേശം അയച്ചില്ല: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> എന്നതിലേക്ക് സന്ദേശം അയയ്‌ക്കുന്നു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> എന്നതിലേക്കുള്ള സന്ദേശം പരാജയപ്പെട്ടു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> എന്നതിലേക്കുള്ള സന്ദേശം: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള സന്ദേശം പരാജയപ്പെട്ടു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> എന്നയാളിൽ നിന്നുള്ള സന്ദേശം: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> എന്നതിലേക്ക് സന്ദേശം അയച്ചില്ല: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> എന്നതിലേക്ക് സന്ദേശം അയയ്‌ക്കുന്നു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> എന്നതിലേക്കുള്ള സന്ദേശം പരാജയപ്പെട്ടു: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> എന്നതിലേക്കുള്ള സന്ദേശം: <xliff:g id="MESSAGE">%2$s</xliff:g>. സമയം: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"സന്ദേശം പരാജയപ്പെട്ടു. വീണ്ടും ശ്രമിക്കുന്നതിന് സ്‌പർശിക്കുക."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> എന്നിവരുമായുള്ള സംഭാഷണം"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"വിഷയം ഇല്ലാതാക്കുക"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"വീഡിയോ എടുക്കുക"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ഒരു സ്റ്റിൽ ചിത്രം എടുക്കുക"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ചിത്രം എടുക്കുക"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"വീഡിയോ റെക്കോർഡുചെയ്യാൻ ആരംഭിക്കുക"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"പൂർണ്ണസ്ക്രീൻ ക്യാമറയിലേക്ക് മാറുക"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"മുന്നിലെയും പിന്നിലെയും ക്യാമറയ്‌ക്കിടയിൽ മാറുക"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"റെക്കോർഡുചെയ്യൽ നിർത്തി, വീഡിയോ അറ്റാച്ചുചെയ്യുക"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"വീഡിയോ റെക്കോർഡുചെയ്യൽ നിർത്തുക"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"സന്ദേശമയയ്ക്കൽ ഫോട്ടോകൾ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ഫോട്ടോകൾ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ഫോട്ടോ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> വീഡിയോകൾ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> വീഡിയോ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> അറ്റാച്ചുമെന്റുകൾ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> അറ്റാച്ച്‌മെന്റ് \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ആൽബത്തിലേക്ക് സംരക്ഷിച്ചു</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> അറ്റാച്ചുമെന്റുകൾ \"ഡൗൺലോഡുകളി\"ലേക്ക് സംരക്ഷിച്ചു </item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> അറ്റാച്ചുമെന്റ് \"ഡൗൺലോഡുകളി\"ലേക്ക് സംരക്ഷിച്ചു</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> അറ്റാച്ച്‌മെന്റുകൾ സംരക്ഷിച്ചു</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> അറ്റാച്ച്‌മെന്റ് സംരക്ഷിച്ചു</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g>അറ്റാച്ച്‌മെന്റുകൾ സംരക്ഷിക്കാനായില്ല</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> അറ്റാച്ച്‌മെന്റ് സംരക്ഷിക്കാനായില്ല</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS അറ്റാച്ചുമെന്റ് സംരക്ഷിച്ചു"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ക്രമീകരണങ്ങൾ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ആർക്കൈവുചെയ്‌തവ"</string>
+    <string name="action_close" msgid="1840519376200478419">"അടയ്‌ക്കുക"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"വിപുലം"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ഡീബഗ്"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"അറിയിപ്പുകൾ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ശബ്‌ദം"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"നിശബ്‌ദം"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"വൈബ്രേറ്റുചെയ്യുക"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"തടഞ്ഞിരിക്കുന്നു"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS ഡെലിവറി റിപ്പോർട്ടുകൾ"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"അയയ്‌ക്കുന്ന ഓരോ SMS-നും ഒരു ഡെലിവറി റിപ്പോർട്ട് അഭ്യർത്ഥിക്കുക"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"സ്വയമേവ വീണ്ടെടുക്കുക"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS സന്ദേശങ്ങൾ സ്വയമേവ ലഭ്യമാക്കുക"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"റോമിംഗിൽ ലഭ്യമാക്കുക"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"റോമിംഗിലായിരിക്കുമ്പോൾ സ്വയമേ MMS വീണ്ടെടുക്കുന്നു"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ഗ്രൂപ്പ് സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ഒന്നിലധികം സ്വീകർത്താക്കൾ ഉള്ളപ്പോൾ ഒരൊറ്റ സന്ദേശം അയയ്‌ക്കാൻ MMS ഉപയോഗിക്കുക."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"സ്ഥിര SMS അപ്ലിക്കേഷൻ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"സ്ഥിര SMS അപ്ലിക്കേഷൻ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"നിങ്ങളുടെ ഫോൺ നമ്പർ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"അജ്ഞാതം"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"ഔട്ട്‌ഗോയിംഗ് സന്ദേശ ശബ്‌ദങ്ങൾ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS നൽകുക"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ബാഹ്യ സംഭരണ ഫയലിലേക്ക് സ്വീകരിച്ച SMS റോ ഡാറ്റ നൽകുക"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS നൽകുക"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ബാഹ്യ സംഭരണ ഫയലിലേക്ക് സ്വീകരിച്ച MMS റോ ഡാറ്റ നൽകുക"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"വയർലെസ് അലേർട്ടുകൾ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"സന്ദേശ ഓ‌പ്ഷനുകൾ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ടെക്‌‌സ്‌റ്റ് പകർത്തുക"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"വിശദാംശങ്ങൾ കാണുക"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ഇല്ലാതാക്കുക"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"കൈമാറുക"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"സന്ദേശ വിശദാംശങ്ങൾ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"തരം: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ടെക്‌സ്റ്റ് സന്ദേശം"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"മൾട്ടിമീഡിയ സന്ദേശം"</string>
+    <string name="from_label" msgid="1947831848146564875">"അയച്ചയാൾ: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"സ്വീകർത്താവ്: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"അയച്ചത്: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ലഭിച്ചവ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"വിഷയം: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"വലുപ്പം: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"പ്രധാനപ്പെട്ടവ: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"ഉയർന്നത്"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"സാധാരണ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"കുറഞ്ഞവ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"അയച്ചയാളിന്റെ വിലാസം മറച്ചിരിക്കുന്നു"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"അറ്റാച്ചുമെന്റുകൾ ലോഡുചെയ്യുന്ന സമയത്ത് സന്ദേശം അയയ്‌ക്കാനാവില്ല."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"അറ്റാച്ചുമെന്റ് ലോഡുചെയ്യാനാവില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"നെറ്റ്‌വർക്ക് തയ്യാറായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ടെക്‌സ്റ്റ് ഇല്ലാതാക്കുക"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ടെക്സ്റ്റും നമ്പറുകളും നൽകുന്നതിനിടയിൽ മാറുക"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"കൂടുതൽ പങ്കാളികളെ ചേർക്കുക"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"പങ്കെടുക്കുന്നവരെ സ്ഥിരീകരിക്കുക"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"പുതിയ സംഭാഷണം ആരംഭിക്കുക"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ഈ ഇനം തിരഞ്ഞെടുക്കുക"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"വീഡിയോ പ്ലേചെയ്യുക"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ആളുകളും ഓപ്‌ഷനുകളും"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ഡീബഗ്"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ആളുകളും ഓപ്‌ഷനുകളും"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"പൊതുവായത്"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ഈ സംഭാഷണത്തിലെ ആളുകൾ"</string>
+    <string name="action_call" msgid="6596167921517350362">"ഒരു കോൾ ചെയ്യുക"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"സന്ദേശം അയയ്ക്കുക"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> -ൽ നിന്ന്&lt;/small&gt; സന്ദേശമയയ്‌ക്കുക"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ഫോട്ടോകൾ അയയ്‌ക്കുക</item>
+      <item quantity="one">ഫോട്ടോ അയയ്ക്കുക</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">ഓഡിയോകൾ അയയ്‌ക്കുക</item>
+      <item quantity="one">ഓഡിയോ അയയ്ക്കുക</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">വീഡിയോകൾ അയയ്‌ക്കുക</item>
+      <item quantity="one">വീഡിയോ അയയ്‌ക്കുക</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">കോൺടാക്റ്റ് കാർഡുകൾ അയയ്‌ക്കുക</item>
+      <item quantity="one">കോൺടാക്റ്റ് കാർഡ് അയയ്ക്കുക</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">അറ്റാച്ച്‌മെന്റുകൾ അയയ്ക്കുക</item>
+      <item quantity="one">അറ്റാച്ച്‌മെന്റ് അയയ്ക്കുക</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> അറ്റാച്ച്‌മെന്റുകൾ അയയ്‌ക്കാൻ തയ്യാറാണ്</item>
+      <item quantity="one">ഒരു അറ്റാച്ച്‌മെന്റ് അയയ്‌ക്കാൻ തയ്യാറാണ്</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ഫീഡ്‍ബാക്ക് അയയ്ക്കുക"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store-ൽ കാണുക"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"പതിപ്പ് വിവരം"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"പതിപ്പ് %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ഓപ്പൺ സോഴ്‌സ് ലൈസൻസുകൾ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"അറിയിപ്പുകൾ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"അറ്റാച്ചുമെന്റ് പരിധിയെത്തി"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"അറ്റാച്ചുമെന്റ് ലോഡുചെയ്യുന്നത് പരാജയപ്പെട്ടു."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"കോൺടാക്റ്റിലേക്ക് ചേർക്കണോ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"കോൺടാക്‌റ്റ് ചേർക്കുക"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"വിഷയം"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"വിഷയം: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"കോൺടാക്‌റ്റ് കാർഡ് ലോഡുചെയ്യുന്നു"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"കോൺടാക്‌റ്റ് കാർഡ് ലോഡുചെയ്യാനായില്ല"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"കോൺടാക്റ്റ് കാർഡ് കാണുക"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> കോൺടാക്റ്റുകൾ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> കോൺടാക്റ്റ്</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"കോൺ‌ടാക്‌റ്റ് കാർഡുകൾ"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"ജന്മദിനം"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"കുറിപ്പുകള്‍"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"സന്ദേശം കൈമാറൽ"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"മറുപടി നൽകുക"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1 ചെയ്യുക"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"അയയ്ക്കുന്നതിന്, സ്ഥിര SMS ആപ്പ് ആയി സന്ദേശമയയ്ക്കൽ സജ്ജമാക്കുക"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"സ്ഥിര SMS ആപ്പ് ആയി സന്ദേശമയയ്ക്കൽ സജ്ജമാക്കുക"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"മാറ്റുക"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"സന്ദേശങ്ങൾ സ്വീകരിക്കുന്നതിന്, സ്ഥിര SMS ആപ്പ് ആയി സന്ദേശമയയ്ക്കൽ സജ്ജമാക്കുക"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS സന്ദേശങ്ങൾ അയയ്‌ക്കാൻ പ്രസ്താവിത SIM ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ഉപകരണത്തിന്റെ ഉടമ ഈ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നില്ല."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ശരി"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"ഒരു സംഭാഷണത്തിൽ നിരവധി പേർ പങ്കെടുക്കുന്നു"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">അസാധുവായ കോൺടാക്റ്റുകൾ</item>
+      <item quantity="one">അസാധുവായ കോൺടാക്‌റ്റ്</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ക്യാമറ ചിത്രം ലോഡുചെയ്യാനായില്ല"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"നിങ്ങൾ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ഡ്രാഫ്റ്റ്"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"ഒരു പുതിയ സംഭാഷണം ആരംഭിക്കുമ്പോൾ, ഇത് ഇവിടെ ലിസ്‌റ്റുചെയ്‌തിരിക്കുന്നത് നിങ്ങൾ കാണും"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ആർക്കൈവുചെയ്‌ത സംഭാഷണങ്ങൾ ഇവിടെ ദൃശ്യമാകും"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"സംഭാഷണങ്ങൾ ലോഡുചെയ്യുന്നു…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ചിത്രം"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ഓഡിയോ ക്ലിപ്പ്"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"വീഡിയോ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"കോൺടാക്‌റ്റ് കാർഡ്"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"പഴയപടിയാക്കുക"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"വീണ്ടും ശ്രമിക്കുക"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ഒരു പുതിയ സന്ദേശം ആരംഭിക്കാൻ കോൺടാക്‌റ്റ് പേരോ ഫോൺ നമ്പറോ നൽകുക"</string>
+    <string name="action_block" msgid="9032076625645190136">"തടയുക"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> എന്നയാളെ തടയുക"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> എന്നയാളെ തടഞ്ഞത് മാറ്റുക"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> തടയണോ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ഈ നമ്പറിൽ നിന്ന് സന്ദേശങ്ങൾ തുടർന്നും ലഭിക്കുമെങ്കിലും ഇനി അറിയിപ്പൊന്നും ലഭിക്കില്ല. ഈ സംഭാഷണം ആർക്കൈവുചെയ്യും."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"തടഞ്ഞ കോൺടാക്‌റ്റുകൾ"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"തടഞ്ഞത് മാറ്റുക"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"തടഞ്ഞ കോൺടാക്‌റ്റുകൾ"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"പ്രമാണ ലൈബ്രറിയിൽ നിന്ന് ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
+    <string name="sending_message" msgid="6363584950085384929">"സന്ദേശം അയക്കുന്നു"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"സന്ദേശം അയച്ചു"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"സെല്ലുലാർ ഡാറ്റ ഓഫാക്കിയിരിക്കുന്നു. നിങ്ങളുടെ ക്രമീകരണങ്ങൾ പരിശോധിക്കുക."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"വിമാന മോഡിൽ സന്ദേശങ്ങൾ അയയ്‌ക്കാനാവില്ല"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"സന്ദേശം അയയ്ക്കാനായില്ല"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"സന്ദേശം ഡൗൺലോഡുചെയ്‌തു"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"സെല്ലുലാർ ഡാറ്റ ഓഫാണ്. നിങ്ങളുടെ ക്രമീകരണം പരിശോധിക്കുക."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"വിമാന മോഡിൽ സന്ദേശങ്ങൾ ഡൗൺലോഡുചെയ്യാനാവില്ല"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"സന്ദേശം ഡൗൺലോഡുചെയ്യാനായില്ല"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"പൂജ്യം"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ഒന്ന്"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"രണ്ട്"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"മൂന്ന്"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"നാല്"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"അഞ്ച്"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ആറ്"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ഏഴ്"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"എട്ട്"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ഒൻപത്"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> എന്നതിലൂടെ സന്ദേശമയയ്‌ക്കാനായില്ല, പിശക് <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"അജ്ഞാത കാരിയറിലൂടെ സന്ദേശമയയ്‌ക്കാനായില്ല, പിശക് <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"കൈമാറിയത്: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"സന്ദേശം അയച്ചില്ല: നെറ്റ്‌വർക്കിൽ സേവനം സജീവമാക്കിയിട്ടില്ല"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"സന്ദേശം അയച്ചില്ല: ലക്ഷ്യസ്ഥാന വിലാസം അസാധുവാണ്"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"സന്ദേശം അയച്ചില്ല: സന്ദേശം അസാധുവാണ്"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"സന്ദേശം അയച്ചില്ല: ഉള്ളടക്കം പിന്തുണയ്ക്കാത്തതാണ്"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"സന്ദേശം അയച്ചില്ല: സന്ദേശം പിന്തുണയ്ക്കാത്തതാണ്"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"സന്ദേശം അയച്ചില്ല: വളരെ വലുതാണ്"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"പുതിയ സന്ദേശം"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"കാണുക"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ചിത്രം"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"അനുയോജ്യമായൊരു അപ്ലിക്കേഷൻ കണ്ടെത്താനായില്ല"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"സ്വീകർത്താവിനെ നീക്കംചെയ്യുക"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"പുതിയ സന്ദേശം"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"റദ്ദാക്കുക"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ആക്‌സസ്സ്‌പോയിന്റ് എഡിറ്റുചെയ്യൂ"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"സജ്ജീകരിച്ചിട്ടില്ല"</string>
+    <string name="apn_name" msgid="1572691851070894985">"പേര്"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS പ്രോക്‌സി"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS പോർട്ട്"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN തരം"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN ഇല്ലാതാക്കുക"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"പുതിയ APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"സംരക്ഷിക്കുക"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"നിരസിക്കുക"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"പേരിന്റെ ഫീൽഡ് ശൂന്യമായിരിക്കരുത്."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ശൂന്യമായിരിക്കരുത്."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ഫീൽഡിൽ 3 സംഖ്യകൾ ഉണ്ടായിരിക്കണം."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ഫീൽഡിൽ 2 അല്ലെങ്കിൽ 3 സംഖ്യകൾ ഉണ്ടായിരിക്കണം."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"സ്ഥിര APN ക്രമീകരണങ്ങൾ പുനഃസ്ഥാപിക്കുന്നു"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"സ്ഥിരമായതിലേക്ക് പുനഃസജ്ജമാക്കുക"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"സ്ഥിര APN ക്രമീകരണങ്ങൾ പുനഃസജ്ജീകരിക്കൽ പൂർത്തിയാക്കി."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"പേരില്ലാത്തത്"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ആക്‌സസ്സ് പോയിന്റ് പേരുകൾ"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-കൾ"</string>
+    <string name="menu_new" msgid="8286285392706532511">"പുതിയ APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ആക്‌സസ്സ് പോയിന്റ് നെയിം ക്രമീകരണങ്ങൾ ഈ ഉപയോക്താവിനായി ലഭ്യമല്ല"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ക്ലിപ്പ്‌ബോർഡിലേക്ക് പകർത്തണോ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"പകര്‍ത്തുക"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> എന്നതിലേക്ക്"</string>
+    <string name="general_settings" msgid="5409336577057897710">"പൊതുവായത്"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"വിപുലമായത്"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"പൊതു ക്രമീകരണങ്ങൾ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"വിപുലമായ ക്രമീകരണങ്ങൾ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"എല്ലാ സ്വീകർത്താക്കൾക്കും വെവ്വേറെ SMS സന്ദേശങ്ങൾ അയയ്‌ക്കുക. മറുപടികളെല്ലാം നിങ്ങൾക്കുമാത്രമേ ലഭിക്കൂ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"എല്ലാ സ്വീകർത്താക്കൾക്കും ഒരൊറ്റ MMS അയയ്‌ക്കുക"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"അജ്ഞാത നമ്പര്‍"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"പുതിയ സന്ദേശം"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"പുതിയ സന്ദേശം."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM സെലക്‌ടർ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> തിരഞ്ഞെടുത്തു, SIM സെലക്‌ടർ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"വിഷയം എഡിറ്റുചെയ്യുക"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM തിരഞ്ഞെടുക്കുക അല്ലെങ്കിൽ വിഷയം എഡിറ്റുചെയ്യുക"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ഓഡിയോ റെക്കോർഡുചെയ്യാൻ സ്‌പർശിച്ച് പിടിക്കുക"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"പുതിയ സംഭാഷണം ആരംഭിക്കുക"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"സന്ദേശമയയ്ക്കൽ ലിസ്റ്റ്"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"പുതിയ സന്ദേശം"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"സംഭാഷണ ലിസ്റ്റ്"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"സംഭാഷണങ്ങൾ ലോഡുചെയ്യുന്നു"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"സന്ദേശങ്ങൾ ലോഡുചെയ്യുന്നു"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"കൂടുതൽ സംഭാഷണങ്ങൾ കാണുക"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"കൂടുതൽ സന്ദേശങ്ങൾ കാണുക"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"സംഭാഷണം ഇല്ലാതാക്കി"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"സംഭാഷണം ഇല്ലാതാക്കി. മറ്റൊരു സന്ദേശമയയ്ക്കൽ സംഭാഷണം കാണിക്കുന്നതിന് സ്പർശിക്കുക"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"തടഞ്ഞു"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"തടഞ്ഞത് മാറ്റി"</string>
+    <string name="db_full" msgid="8459265782521418031">"സംഭരണത്തിനുള്ള ഇടം കുറവാണ്. ചില വിവരം നഷ്‌ടപ്പെട്ടേക്കാം."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"അറ്റാച്ചുമെന്റുകൾ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"തിരഞ്ഞെടുത്തവ സ്ഥിരീകരിക്കുക"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> എണ്ണം തിരഞ്ഞെടുത്തു"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ഒന്നോ അതിൽ കൂടുതലോ അറ്റാച്ചുമെന്റുകൾ നീക്കംചെയ്‌തുകൊണ്ട് വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"നിങ്ങളുടെ സന്ദേശം അയയ്‌ക്കാൻ ശ്രമിക്കാമെങ്കിലും ഒന്നോ അതിലധികമോ അറ്റാച്ചുമെന്റുകൾ നീക്കംചെയ്യാതെ അത് ഡെലിവർ ചെയ്തേക്കില്ല."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"നിങ്ങൾക്ക് ഒരു സന്ദേശത്തിന് ഒരു വീഡിയോ മാത്രമേ അയയ്‌ക്കാനാകൂ. കൂടുതൽ വീഡിയോകൾ നീക്കംചെയ്‌ത് വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"അറ്റാച്ച്മെന്റ് ലോഡുചെയ്യുന്നതിൽ സന്ദേശമയയ്‌ക്കൽ പരാജയപ്പെട്ടു."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ഏതുവിധേനയും അയയ്‌ക്കുക"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"സംഭാഷണം ആരംഭിക്കാനായില്ല"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"തിരഞ്ഞെടുത്തത്, <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-mn/arrays.xml b/res/values-mn/arrays.xml
new file mode 100644
index 0000000..b47063a
--- /dev/null
+++ b/res/values-mn/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"гарчиггүй"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Тийм"</item>
+    <item msgid="6049132459802288033">"Үгүй"</item>
+    <item msgid="3084376867445867895">"Тийм"</item>
+    <item msgid="3155097332660174689">"Хэхэ"</item>
+    <item msgid="2611328818571146775">"Баярлалаа"</item>
+    <item msgid="4881335087096496747">"Би зөвшөөрч байна"</item>
+    <item msgid="2422296858597420738">"Янзтай"</item>
+    <item msgid="4805581752819452687">"Очиж байна"</item>
+    <item msgid="4746700499431366214">"За, би эргээд холбоо баръя"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
new file mode 100644
index 0000000..f3edd91
--- /dev/null
+++ b/res/values-mn/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Зурвас"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Зурвас"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Харилцааг сонгох"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Тохиргоо"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Зурвас Илгээх"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Хавсралт нэмэх"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Тусламж"</string>
+    <string name="welcome" msgid="2857560951820802321">"Тавтай морилно уу"</string>
+    <string name="skip" msgid="7238879696319945853">"Алгасах"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Дараах &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Дараах"</string>
+    <string name="exit" msgid="1905187380359981199">"Гарах"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Тохиргоо &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Тохиргоо"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging-д SMS, Утас, Харилцагч хаягийн зөвшөөрөл шаардлагатай."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Та зөвшөөрлийг Тохиргоо &gt; Aпп &gt; Зурвас &gt; Зөвшөөрөл хэсэгт өөрчилж болно."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Та зөвшөөрлийг Тохиргоо, Апп, Messaging, Зөвшөөрөл хэсэгт өөрчилж болно."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"БАЙНГЫН ХАРИЛЦАГЧ"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Бүх харилцагч"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> руу илгээх"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Зураг буюу видео авах"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Энэ төхөөрөмжөөс зураг сонгоно уу"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Аудио бичих"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Зураг сонгох"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медиаг сонгосон байна."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Медиаг сонгоогүй байна."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> сонгогдсон"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"зураг <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"зураг"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Аудио бичих"</string>
+    <string name="action_share" msgid="2143483844803153871">"Хуваалцах"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Дөнгөж сая"</string>
+    <string name="posted_now" msgid="867560789350406701">"Одоо"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> минут</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> минут</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> цаг</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> цаг</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> өдөр</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> өдөр</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> долоо хоног</item>
+      <item quantity="one"> долоо хоног</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> сар</item>
+      <item quantity="one"> нэг сар</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> жил</item>
+      <item quantity="one"> нэг жил</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Ангилал 0 зурвас"</string>
+    <string name="save" msgid="5081141452059463572">"Хадгалах"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Төхөөрөмжийн багтаамж бага байна. Messaging нь багтаамж үүсгэхийн тулд хуучин зурвасыг автоматаар устгана."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Сангийн хэмжээ дутагдаж байна"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Мessaging нь таны төхөөрөмжид хангалттай багтаамж гарах хүртэл зурвас илгээх эсвэл хүлээн авах боломжгүй."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS сан бага байна. Та зурвасуудаас устгах шаардлагатай бололтой."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Утасны дугаараа баталгаажуулна уу"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Нэг удаагийн алхам нь Messaging-г таны бүлэг зурвасыг асуудалгүйгээр илгээнэ."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Утасны дугаар"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Медиатай бүх зурвасуудыг устгах"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g>-с өмнөх зурвасуудыг устгах"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g>-с өмнөх зурвасуудыг автоматаар устгах"</string>
+    <string name="ignore" msgid="7063392681130898793">"Үл тоох"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Медиа бүхий бүх зурвасыг устгах уу?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g>-с өмнөх зурвасуудыг устгах уу?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g>-с өмнөх зурвасуудыг устгаж, автомат устгалтыг асаах уу?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> гэж хэлсэн"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Та хэлсэн байна"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g>-ээс ирсэн мессеж"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Та мессеж илгээсэн байна"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Илгээж байна ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Илгээгээгүй. Дахин оролдохын тулд хүрнэ үү."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Илгээгээгүй. Дахин оролдож байна…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Дахин илгээх буюу устгах"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Яаралтай түргэн тусламж руу залгана уу. Таны мессежийг яг одоо явуулах боломжгүй байна."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Амжилтгүй"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Татаж авах шинэ MMS мессеж"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Шинэ MMS мессеж"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Татан авч чадсангүй"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Дахин оролдохын тулд хүрнэ үү"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Татаж авахын тулд хүрнэ үү"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Татаж авах буюу устгах"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Татаж авч байна..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Зурвасын хугацаа өнгөрсөн буюу байхгүй"</string>
+    <string name="mms_info" msgid="3402311750134118165">"хэмжээ: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, хугацаа дуусах: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Илгээх боломжгүй. Хүлээн авагч буруу."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Сүлжээнд үйлчилгээг идэвхжүүлээгүй байна."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Сүлжээний асуудлаас шалтгаалан илгээж чадсангүй."</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Зурвасын хугацаа өнгөрсөн буюу байхгүй"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Гарчиггүй)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Тодорхойгүй илгээгч"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Хүргэгдсэн"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g>-с <xliff:g id="SUBJECT">%1$s</xliff:g> зурвасыг татаж чадсангүй."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Санах ой бага байгаагаас шалтгаалан датабаазын үйлдлийг гүйцээж чадсангүй"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Зурвас илгээгдээгүй"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Messaging-н зарим зурвасыг илгээгээгүй"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> Харилцан ярианд <xliff:g id="MESSAGES_1">%d</xliff:g> зурвас байна</item>
+      <item quantity="one"> Нэг харилцан ярианд <xliff:g id="MESSAGES_0">%d</xliff:g> зурвас байна</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"зурвасыг татаж болсонгүй"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Зарим зурвасыг Messaging-д татаагүй"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> Харилцан ярианд <xliff:g id="MESSAGES_1">%d</xliff:g> зурвас байна</item>
+      <item quantity="one"> Нэг харилцан ярианд <xliff:g id="MESSAGES_0">%d</xliff:g> зурвас байна</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> явуулсан мессеж амжилтгүй болсон байна"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Яаралтай түргэн тусламж руу залгана уу. Таны мессежийг <xliff:g id="NUMBER">%1$s</xliff:g> дугаарт яг одоо явуулах боломжгүй байна. "</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> шинэ зурвас</item>
+      <item quantity="one">Шинэ зурвас</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Эхлэх"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камер ашиглах боломжгүй"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камер ашиглах боломжгүй"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Видео бичих боломжгүй"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Медиаг хадгалах боломжгүй"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Зураг авч болохгүй байна"</string>
+    <string name="back" msgid="1477626055115561645">"Буцах"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архивлагдсан"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Устгах"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архивлах"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Архиваас гаргах"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Мэдэгдэл унтраах"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Мэдэгдлүүдийг асаах"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Харилцагч нэмэх"</string>
+    <string name="action_download" msgid="7786338136368564146">"Татаж авах"</string>
+    <string name="action_send" msgid="377635240181672039">"Илгээх"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Устгах"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Энэ зурвасыг устгах уу?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Энэ үйлдлийг буцаах боломжгүй."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Устгах"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Эдгээр харилцан яриаг устгах уу?</item>
+      <item quantity="one">Энэ харилцан яриаг устах уу?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Устгах"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Цуцлах"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Хэнд"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Олон зураг сонгох"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Сонголтыг баталгаажуулах"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Аудиог бичих боломжгүй. Дахин оролдоно уу."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Аудиог тоглуулах боломжгүй. Дахин оролдоно уу."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Аудиог хадгалж чадсангүй. Дахин оролдоно уу."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Хүрээд &amp; барих"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Зураг"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудио клип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Харилцагчийн карт"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Татаж авах"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS-р хариулах"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS-ээр хариулах"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Хариулах"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> оролцогч</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> оролцогч</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Би"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Харилцагчийг хориглож &amp; архивласан"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Харилцаа холбоог хориглоогүй &amp; архивлагдаагүй"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> aрхивлагдсан"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> архивлагдаагүй"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Мэдэгдлүүдийг унтраасан"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Мэдэгдлүүдийг асаасан"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Бүгдийг нь тохируулсан. Илгээх-д дахин хүрнэ үү."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Мessaging-г SMS-н үндсэн апп-аар амжилттай тохирууллаа."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Хавсралтыг цуцлах</item>
+      <item quantity="one">Хавсралтыг цуцлах</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудио хавсралт"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Аудио хавсралтыг тоглуулах"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Түр зогсоох"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>-аас ирсэн зурвас."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>-с илгээсэн амжилтгүй болсон мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>-с илгээсэн мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>-д илгээгээгүй байгаа мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>-д мессеж илгээж байна: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>-д илгээсэн амжилтгүй болсон мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>-д мессеж илгээх: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>-с илгээсэн амжилтгүй болсон мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>-с илгээсэн мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>-т зориулсан илгээгээгүй байгаа мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>-т мессеж илгээж байна: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>-т зориулсан амжилтгүй болсон мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>-т илгээх мессеж: <xliff:g id="MESSAGE">%2$s</xliff:g>. Цаг: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Амжилтгүй болсон мессеж. Дахин оролдоно уу."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> нартай холбоо тогтоох"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Гарчгийг устгах"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Видео авах"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Хөдөлгөөнгүй зураг авах"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Зураг авах"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Видео бичлэг хийж эхлэх"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Бүтэн дэлгэцийн камер руу сэлгэх"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Урд болон хойд камер хооронд сэлгэх"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Бичлэгийг зогсоож видеог хавсаргах"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Видео бичилтийг зогсоох"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging-н зураг"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> зургийг \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" цомогт хадгаллаа</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> зургийг \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" цомогт хадгаллаа</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> бичлэгийг \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" цомогт хадгаллаа</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> бичлэгийг \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" цомогт хадгаллаа</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> хавсралтыг \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" цомогт хадгаллаа</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> хавсралтыг \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" цомогт хадгаллаа</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> хавсралтыг \"Татаж авсан файл\"-д хадгаллаа</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> хавсралтыг \"Татаж aвсан файл\"-д хадгаллаа</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> хавсралт хадгалсан</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> хавсралт хадгалсан</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> хавсралтыг хадгалж чадсангүй</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> хавсралтыг хадгалж чадсангүй</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS хавсралтыг хадгалсан"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Тохиргоо"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архивлагдсан"</string>
+    <string name="action_close" msgid="1840519376200478419">"Хаах"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Дэлгэрэнгүй"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Дебаг"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Мэдэгдэл"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Дуу"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Чимээгүй"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Чичиргээ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Хориглогдсон"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS хүргэлтийн репорт"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Өөрийн илгээх SMS бүрт хүргэлтийн репорт хүснэ үү"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Автомат-татагч"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS зурвасуудыг автоматаар татах"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Роумингын автомат-татагч"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Роуминг ашиглаж байх үедээ MMS-ийг автоматаар сэргээж авч байх"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Бүлгэмийн зурвас"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Олон хүлээн авагчид нэг зурвас явуулахдаа MMS ашиглаарай"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Үндсэн SMS програм"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Үндсэн SMS програм"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Таны утасны дугаар"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Тодорхойгүй"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Мессеж илгээх үеийн ая"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS хадгалах"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Хүлээн авсан SMS түүхий датаг гадаад сангийн файлд хадгалах"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS хадгалах"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dump Хүлээн авсан MMS түүхий датаг гадаад сангийн файлд хадгалах"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Утасгүй сэрэмжлүүлэг"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Зурвасын тохиргоо"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Текстийг хуулах"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Дэлгэрэнгүй үзэх"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Устгах"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Дамжуулах"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Зурвасын мэдээлэл"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Төрөл: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Текст зурвас"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мультимедиа зурвас"</string>
+    <string name="from_label" msgid="1947831848146564875">"Хэнээс: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Хэнд: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Илгээсэн: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Хүлээн авсан: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Гарчиг: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Хэмжээ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Ач холбогдол: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Өндөр"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Энгийн"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Бага"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Илгээгчийн хаяг нууцлагдсан"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Хавсралтуудыг ачаалах үед зурвас илгээх боломжгүй."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Хавсралтыг ачаалж чадсангүй. Дахин оролдоно уу."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Сүлжээ бэлэн биш байна. Дахин оролдоно уу."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Текстийг устгах"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Текст болон тоо оруулах хооронд сэлгэх"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Өөр оролцогчид нэмэх"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Оролцогчдыг баталгаажуулах"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Шинээр харилцан яриа үүсгэж байна"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Энэ зүйлийг сонгох"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Видео тоглуулах"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Хүмүүс &amp; тохируулга"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Дебаг"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Хүмүүс &amp; тохируулга"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Ерөнхий"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Энэ харилцаан доторх хүмүүс"</string>
+    <string name="action_call" msgid="6596167921517350362">"Дуудлага хийх"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Зурвас илгээх"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Зурвас илгээх&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>-с&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Зураг илгээх</item>
+      <item quantity="one">Зураг илгээх</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Аудио илгээх</item>
+      <item quantity="one">Аудио илгээх</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Видео илгээх</item>
+      <item quantity="one">Видео илгээх</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Харилцагчийн карт илгээх</item>
+      <item quantity="one">Харилцагчийн карт илгээх</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Хавсралт илгээх</item>
+      <item quantity="one">Хавсралт илгээх</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">Илгээхэд бэлэн <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> хавсралт байна</item>
+      <item quantity="one">Илгээхэд бэлэн нэг хавсралт байна</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Санал хүсэлт илгээх"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play дэлгүүр дээр харах"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Хувилбарын мэдээлэл"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Хувилбар %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Нээлттэй эхийн лиценз"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Мэдэгдэл"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Хавсралтын дээд хэмжээнд хүрсэн байна"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Хавсралтыг татаж авах үйлдэл амжилтгүй болсон байна."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Харилцагчидад нэмэх үү?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Харилцагч нэмэх"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Гарчиг"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Гарчиг: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Харилцагчийн картыг ачаалж байна"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Харилцагчийн картыг дуудаж чадсангүй"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Харилцагчийн картыг харах"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> харилцагч</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> харилцагч</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Харилцагчийн картууд"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Төрсөн өдөр"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Тэмдэглэл"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Зурвасыг дамжуулах"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Хариулах"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS идэвхгүй"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Илгээхийн тулд Messaging-г үндсэн SMS апп болго"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Messaging-г үндсэн SMS апп болгох"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Солих"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Зурвас хүлээн авахын тулд Messaging-г үндсэн SMS апп-аар тохируулаарай"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS зурвас илгээхээр сонгосон ямар ч SIM алга байна"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Энэ апп-г төхөөрөмжийн эзэмшигч зөвшөөрөөгүй."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ТИЙМ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Харилцаанд хэт олон оролцогч байна"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Харилцагчийн хаяг буруу байна</item>
+      <item quantity="one">Харилцагчийн хаяг буруу байна</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Камерийн дүрсийг дуудаж чадсангүй"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Та: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Ноорог"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Шинэ харилцаа эхлүүлмэгц энэ жагсаалтад харагдах болно"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Архивлагдсан харилцаанууд энд харагдана"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Харилцааг ачаалж байна..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Зураг"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудио клип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Харилцагчийн карт"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Буцаах"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Дахин оролдох"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Шинэ зурвас эхлүүлэхийн тулд харилцагчийн нэр буюу утасны дугаар оруулна уу"</string>
+    <string name="action_block" msgid="9032076625645190136">"Хориглох"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>-г хориглох"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g>-н хориг авах"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>-г хориглох уу?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Та энэ дугаараас үргэлжлүүлэн зурвас хүлээн авах боловч мэдэгдэл авахгүй. Энэ харилцааг архивлах болно."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Хориглогдсон харилцагчид"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ХОРИГ АВАХ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Хориглогдсон харилцагчид"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Документ сангаас зураг сонгох"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Зурвасыг илгээж байна"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Зурвас илгээгдсэн"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Үүрэн дата унтарсан. Тохиргоог шалгана уу."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Нислэгийн горимд зурвас илгээх боломжгүй"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Зурвасыг илгээж чадсангүй."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Зурвасыг татаж авсан"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Гар утасны интернет холболт идэвхгүй байна. Тохиргоог дахин шалгана уу."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Airplane mode дээр тавьсан байгаа тул мэдээллийг татаж авах боломжгүй байна"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Мэдээллийг татаж авах боломжгүй байна"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Тэг"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Нэг"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Хоёр"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Гурав"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Дөрөв"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Тав"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Зургаа"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Долоо"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Найм"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Ес"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="ERRORCODE">%2$d</xliff:g> алдаа бүхий <xliff:g id="CARRIERNAME">%1$s</xliff:g> мессежийг илгээх боломжгүй"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Үл мэдэгдэх зөөвөрлөгчөөр ирсэн мессежийг илгээх боломжгүй, алдаа <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Зурвас илгээгдээгүй: үйлчилгээ сүлжээн дээр идэвхжээгүй"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Зурвас илгээгдээгүй: чиглэлийн хаяг буруу"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Зурвас илгээгдээгүй: хүчингүй зурвас"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Зурвас илгээгдээгүй: дэмжигдээгүй контент"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Зурвас илгээгдээгүй: дэмжигдээгүй зурвас"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Мессежийг илгээж болохгүй байна: хэтэрхий их хэмжээтэй байна"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Шинэ зурвас"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Харагдац"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Зураг"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Тохирох аппликешныг олж чадсангүй"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Хүлээн авагчийг арилгах"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Шинэ зурвас"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Цуцлах"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Хандалтын цэгийг засах"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Тохируулаагүй"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Нэр"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS прокси"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS порт"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN төрөл"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN устгах"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Шинэ APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Хадгалах"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Устгах"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Нэр оруулах талбар хоосон байж болохгүй."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN хоосон байж болохгүй."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC талбар 3 цифртэй байх ёстой."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC талбар 2 буюу 3 цифртэй байх ёстой."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Үндсэн APN тохиргоог сэргээж байна"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Үндсэн рүү сэргээх"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Үндсэн APN тохиргоог дахин шинэчилж дууслаа."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Гарчиггүй"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Хандалтын Цэгийн Нэрс"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Шинэ APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Энэ хэрэглэгчийн хувьд Хандалтын цэгийн нэрийн тохиргоог ашиглах боломжгүй"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Санах ойд хуулах уу?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Хуулах"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> руу"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Ерөнхий"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Дэлгэрэнгүй"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ерөнхий тохиргоо"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Дэлгэрэнгүй тохиргоо"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\" <xliff:g id="SIM_NAME">%s</xliff:g> \"SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Бүх хүлээн авагч руу хувийн SMS мессеж илгээх. Зөвхөн та ямар ч хариу авахгүй"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Бүх хүлээн авагч руу нэг MMS илгээх"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Тодорхойгүй дугаар"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Шинэ зурвас"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Шинэ зурвас."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM сонгогч"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> сонгосон, СИМ сонгогч"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Гарчигийг засах"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM-г сонгох эсвэл гарчигийг засах"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Дуут бичлэг хийхийн тулд холбогдох хэсэгт даран түр хүлээнэ үү"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Шинээр харилцан яриа үүсгэх"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging-н жагсаалт"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Шинэ мэдээлэл"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Харилцааны жагсаалт"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Харилцан солилцсон мэдээллийг ачаалж байна"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Зурвасуудыг дуудаж байна"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Харилцан яриаг дэлгэрэнгүй харах"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Илүү олон зурвасуудыг харах"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Харилцаа холбоог устгасан байна"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Харилцан яриа устсан. Messaging-н өөр харилцан яриа харуулахын тулд хүрнэ үү"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Блоклосон байна"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Блокыг арилгасан байна"</string>
+    <string name="db_full" msgid="8459265782521418031">"Таны мэдээлэл хадгалах зай хангалтгүй байна. Зарим мэдээлэл алдагдах магадлалтай байна."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Хавсралтыг сонгох"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Сонголтыг баталгаажуулах"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> сонгосон"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Нэг эсвэл түүнээс дээш тооны хавсралтыг арилгасны дараагаар дахин оролдоно уу."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Та өөрийн мессежийг илгээх оролдлогыг хийж болох боловч нэг эсвэл түүнээс дээг тооны хавсралтыг арилгахаас нааш илгээгдэхгүй байх магадлалтай."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Та нэг мессежээр нэг л видео илгээж болно. Нэмэлт видеонуудыг устгаад, дахин оролдоно уу."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging нь хавсралтыг ачаалж чадсангүй."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Юутай ч илгээх"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Харилцан яриаг эхэлж болохгүй байна"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> сонгогдсон"</string>
+</resources>
diff --git a/res/values-mr/arrays.xml b/res/values-mr/arrays.xml
new file mode 100644
index 0000000..73cd4c2
--- /dev/null
+++ b/res/values-mr/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"कोणताही विषय नाही"</item>
+    <item msgid="272485471009191934">"कोणताही विषय नाही"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"होय"</item>
+    <item msgid="6049132459802288033">"नाही"</item>
+    <item msgid="3084376867445867895">"ठीक आहे"</item>
+    <item msgid="3155097332660174689">"हेहे"</item>
+    <item msgid="2611328818571146775">"धन्यवाद"</item>
+    <item msgid="4881335087096496747">"मी सहमत आहे"</item>
+    <item msgid="2422296858597420738">"छान"</item>
+    <item msgid="4805581752819452687">"मी वाटेत आहे"</item>
+    <item msgid="4746700499431366214">"ठीक, नंतर मला आपल्याकडे परत येऊ द्या"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
new file mode 100644
index 0000000..ff585ba
--- /dev/null
+++ b/res/values-mr/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"संदेशन"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"संदेशन"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"संभाषण निवडा"</string>
+    <string name="action_settings" msgid="1329008122345201684">"सेटिंग्ज"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"संदेश पाठवा"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"एखादे संलग्नक जोडा"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"मदत"</string>
+    <string name="welcome" msgid="2857560951820802321">"सुस्वागतम"</string>
+    <string name="skip" msgid="7238879696319945853">"वगळा"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"पुढील &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"पुढील"</string>
+    <string name="exit" msgid="1905187380359981199">"बाहेर पडा"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"सेटिंग्ज &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"सेटिंग्ज"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"संदेशनला SMS, फोन आणि संपर्कांसाठी परवानगी आवश्यक आहे."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"आपण सेटिंग्ज &gt; अॅप्स &gt; संदेशन &gt; परवानग्या मध्ये परवानग्या बदलू शकता."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"आपण सेटिंग्ज, अॅप्स, संदेशन, परवानग्या मध्ये परवानग्या बदलू शकता."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"वारंवार"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"सर्व संपर्क"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> वर पाठवा"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"चित्रे किंवा व्हिडिओ कॅप्चर करा"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"या डिव्हाइसवरून प्रतिमा निवडा"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ऑडिओ रेकॉर्ड करा"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"फोटो निवडा"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"मीडिया निवडण्यात आला आहे."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"मीडियाची निवड रद्द करण्यात आली आहे."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> निवडले"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"प्रतिमा <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"प्रतिमा"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ऑडिओ रेकॉर्ड करा"</string>
+    <string name="action_share" msgid="2143483844803153871">"सामायिक करा"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"आत्ताच"</string>
+    <string name="posted_now" msgid="867560789350406701">"आत्ता"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> मिनि</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनिटे</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> तास</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> तास</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> आठवडा</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> आठवडे</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> महिना</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> महिने</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> वर्ष</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> वर्षे</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"वर्ग 0 संदेश"</string>
+    <string name="save" msgid="5081141452059463572">"जतन करा"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"डिव्हाइसवर स्थान कमी आहे. स्थान मोकळे करण्‍यासाठी संदेशन जुने संदेश स्वयंचलितपणे हटवेल."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"संचयन स्थान संपत आहे"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"आपल्या डिव्हाइसवर आणखी स्थान उपलब्ध होईपर्यंत संदेशन संदेश पाठवू किंवा प्राप्त करू शकत नाही."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"कमी SMS संचयन. आपल्याला संदेश हटविण्याची आवश्यकता असू शकते."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"आपल्‍या फोन नंबरची पुष्‍टी करा"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"हे एक-वेळ चरण संदेशन आपले गट संदेश योग्यरित्या वितरीत करेल हे सुनिश्चित करेल."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"फोन नंबर"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"मीडिया असलेले सर्व संदेश हटवा"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> पेक्षा अधिक जुने संदेश हटवा"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> पेक्षा जुने संदेश स्वयं हटवा"</string>
+    <string name="ignore" msgid="7063392681130898793">"दुर्लक्ष करा"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"मीडिया असलेले सर्व संदेश हटवायचे?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> पेक्षा जुने संदेश हटवायचे?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> पेक्षा जुने संदेश हटवायचे आणि स्वयं-हटवा चालू करायचे?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> म्हणाले"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"आपण म्हटले"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> कडून संदेश"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"आपण एक संदेश पाठविला"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"पाठवित आहे..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"पाठविले नाही. पुन्हा प्रयत्न करण्यासाठी स्पर्श करा."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"पाठविले नाही. पुन्हा प्रयत्न करत आहे…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"पुन्हा पाठवा किंवा हटवा"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"कृपया आणीबाणी सेवांना एक व्हॉईस कॉल करा. यावेळी आपला मजकूर संदेश वितरीत केला जाऊ शकत नाही."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"अयशस्‍वी झाले"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"डाउनलोड करण्यासाठी नवीन MMS संदेश"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"नवीन MMS संदेश"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"डाउनलोड करू शकलो नाही"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"पुन्हा प्रयत्न करण्यासाठी स्पर्श करा"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"डाउनलोड करण्यासाठी स्पर्श करा"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"डाउनलोड करा किंवा हटवा"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"डाउनलोड करत आहे..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"संदेश कालबाह्य झाला किंवा उपलब्‍ध नाही"</string>
+    <string name="mms_info" msgid="3402311750134118165">"आकार: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, कालबाह्यता: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"पाठवू शकलो नाही. प्राप्तकर्ता वैध नाही."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"नेटवर्कवर सेवा सक्रिय केली नाही"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"नेटवर्क समस्येमुळे पाठवू शकलो नाही"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"संदेश कालबाह्य झाला किंवा उपलब्‍ध नाही"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(विषय नाही)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"अज्ञात प्रेषक"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"वितरित"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> कडील <xliff:g id="SUBJECT">%1$s</xliff:g> संदेश डाउनलोड करू शकलो नाही"</string>
+    <string name="low_memory" msgid="5300743415198486619">"कमी मेमरीमुळे डेटाबेस ऑपरेशन पूर्ण करू शकलो नाही"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"संदेश पाठविला नाही"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"काही संदेश संदेशन मध्ये पाठविले गेले नाहीत"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> संभाषणांमधील <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> संभाषणांमधील <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"संदेश डाउनलोड केला नाही"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"काही संदेश संदेशन मध्ये डाउनलोड झाले नाहीत"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="CONVERSATIONS">%d</xliff:g> संभाषणांमधील <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> संभाषणांमधील <xliff:g id="MESSAGES_1">%d</xliff:g> संदेश</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> वर संदेश पाठविला नाही"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"कृपया आणीबाणी सेवांना एक व्हॉईस कॉल करा. यावेळी आपला मजकूर संदेश <xliff:g id="NUMBER">%1$s</xliff:g> ला वितरीत केला जाऊ शकत नाही."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> नवीन संदेश</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> नवीन संदेश</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"प्रारंभ करा"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"कॅमेरा उपलब्ध नाही"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"कॅमेरा उपलब्ध नाही"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"व्हिडिओ कॅप्चर उपलब्ध नाही"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"मीडिया जतन करू शकत नाही"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"चित्र घेऊ शकत नाही"</string>
+    <string name="back" msgid="1477626055115561645">"परत"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"संग्रहित"</string>
+    <string name="action_delete" msgid="4076795795307486019">"हटवा"</string>
+    <string name="action_archive" msgid="5437034800324083170">"संग्रहण करा"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"संग्रहण रद्द करा"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"सूचना बंद करा"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"सूचना चालू करा"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"संपर्क जोडा"</string>
+    <string name="action_download" msgid="7786338136368564146">"डाउनलोड करा"</string>
+    <string name="action_send" msgid="377635240181672039">"पाठवा"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"हटवा"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"हा संदेश हटवायचा?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ही क्रिया पूर्ववत केली जाणे शक्य नाही."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"हटवा"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">हे संभाषण हटवायचे?</item>
+      <item quantity="other">ही संभाषणे हटवायची?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"हटवा"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"रद्द करा"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"प्रति"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"एकाधिक प्रतिमा निवडा"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"निवडीची पुष्टी करा"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ऑडिओ रेकॉर्ड करू शकत नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ऑडिओ प्ले करू शकत नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ऑडिओ जतन करू शकलो नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"स्पर्श करा आणि धरून ठेवा"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"चित्र"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ऑडिओ क्लिप"</string>
+    <string name="notification_video" msgid="4331423498662606204">"व्हिडिओ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"संपर्क कार्ड"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"डाउनलोड करा"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS द्वारे प्रत्युत्तर द्या"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS द्वारे प्रत्‍युत्तर द्या"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"प्रत्युत्तर द्या"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> सहभागी</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> सहभागी</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"मी"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"संपर्क अवरोधित आणि संग्रहित केला"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"संपर्क अनावरोधित केला आणि संग्रहण करणे रद्द केले"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> संग्रहित केले"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> संग्रहण करणे रद्द केले"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"सूचना बंद"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"सूचना चालू"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"सर्व सेट केले. पुन्हा पाठवा ला स्पर्श करा."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"डीफॉल्ट SMS अॅप म्हणून संदेशन यशस्वीरित्या सेट झाले."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">संलग्नक टाकून द्या</item>
+      <item quantity="other">संलग्नके टाकून द्या</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ऑडिओ संलग्नक"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ऑडिओ संलग्नक प्ले करा"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"विराम द्या"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> कडून संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> कडील अयशस्‍वी संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> कडील संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> ला न पाठविलेला संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> ला संदेश पाठवित आहे: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> चा अयशस्‍वी संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> चा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> कडील अयशस्‍वी संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> कडील संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> ला न पाठविलेला संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> ला संदेश पाठवित आहे: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> चा अयशस्‍वी संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> चा संदेश: <xliff:g id="MESSAGE">%2$s</xliff:g>. वेळ: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"संदेश अयशस्वी. पुन्हा प्रयत्न करण्यासाठी स्पर्श करा."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> सह संभाषण"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"विषय हटवा"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"व्‍हिडिओ कॅप्‍चर करा"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"एक स्थिर प्रतिमा कॅप्च करा"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"चित्र घ्या"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"व्हिडिओ रेकॉर्ड करणे प्रारंभ करा"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"पूर्ण स्क्रीन कॅमेर्‍यावर स्विच करा"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"पुढील आणि मागील कॅमेर्‍यात स्विच करा"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"रेकॉर्डिंग थांबवा आणि व्‍हिडिओ संलग्न करा"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"व्हिडिओ रेकॉर्ड करणे थांबवा"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"संदेशन फोटो"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> फोटो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केला</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> फोटो \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केले</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> व्हिडिओ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केला</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> व्हिडिओ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केले</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> संलग्नक \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केले</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> संलग्नके \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" अल्बममध्‍ये जतन केली</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नक \"डाउनलोड\" मध्‍ये जतन केले</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नके \"डाउनलोड\" मध्‍ये जतन केली</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नक जतन केले</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नके जतन केली</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नक जतन करणे शक्य झाले नाही</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नके जतन करणे शक्य झाले नाही</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS संलग्नक जतन केले"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"सेटिंग्ज"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"संग्रहित"</string>
+    <string name="action_close" msgid="1840519376200478419">"बंद करा"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"प्रगत"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"डीबग करणे"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"सूचना"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ध्वनी"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"मूक"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"कंपन"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"अवरोधित केले"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS वितरण अहवाल"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"आपण पाठविता त्या प्रत्‍येक SMS साठी वितरण अहवालाची विनंती करा"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"स्‍वयं-पुनर्प्राप्त करा"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS संदेश स्वयंचलितपणे पुनर्प्राप्त करा"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"रोमिंग स्‍वयं-पुनर्प्राप्त करा"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"रोमिंगमध्‍ये असताना स्वयंचलितपणे MMS पुनर्प्राप्त करा"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"गट संदेशन"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"एक संदेश एकाधिक प्राप्तकर्त्यांना पाठविण्‍यासाठी MMS चा वापर करा."</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"डीफॉल्ट SMS अॅप"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"डीफॉल्ट SMS अॅप"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"आपला फोन नंबर"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"अज्ञात"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"पाठविला जाणारा संदेश ध्वनी करतो"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS साचवा"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"प्राप्त केलेला SMS अविश्लेषित डेटा बाह्य संचयन फायलीमध्‍ये साचवा"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS साचवा"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"प्राप्त केलेला MMS अविश्लेषित डेटा बाह्य संचयन फायलीमध्‍ये साचवा"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"वायरलेस अॅलर्ट"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"संदेश पर्याय"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"मजकूर कॉपी करा"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"तपशील पहा"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"हटवा"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"अग्रेषित करा"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"संदेश तपशील"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"प्रकार: "</string>
+    <string name="text_message" msgid="7415419755252205721">"मजकूर संदेश"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"मल्‍टीमीडिया संदेश"</string>
+    <string name="from_label" msgid="1947831848146564875">"प्रेषक: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"प्रति: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"प्रेषित: "</string>
+    <string name="received_label" msgid="4442494712757995203">"प्राप्त झाले: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"विषय: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"आकार: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"प्राधान्य: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"सिम: "</string>
+    <string name="priority_high" msgid="728836357310908368">"उच्च"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"सामान्य"</string>
+    <string name="priority_low" msgid="7398724779026801851">"निम्न"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"सिम <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"लपविलेला प्रेषक पत्ता"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"संलग्नके लोड करताना संदेश पाठवू शकत नाही."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"संलग्नक लोड करू शकत नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"नेटवर्क सज्ज नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"मजकूर हटवा"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"मजकूर आणि संख्या प्रविष्ट करणे दरम्यान स्विच करा"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"अधिक सहभागी जोडा"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"सहभाग्यांची पुष्टी करा"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"नवीन संभाषण प्रारंभ करा"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"हा आयटम निवडा"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"व्हिडिओ प्ले करा"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"लोक आणि पर्याय"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"डीबग करणे"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"लोक आणि पर्याय"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"सामान्य"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"या संभाषणातील लोक"</string>
+    <string name="action_call" msgid="6596167921517350362">"एक कॉल करा"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"संदेश पाठवा"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> वरून&lt;/small&gt;संदेश पाठवा"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">फोटो पाठवा</item>
+      <item quantity="other">फोटो पाठवा</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ऑडिओ पाठवा</item>
+      <item quantity="other">ऑडिओ पाठवा</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">व्हिडिओ पाठवा</item>
+      <item quantity="other">व्हिडिओ पाठवा</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">संपर्क कार्ड पाठवा</item>
+      <item quantity="other">संपर्क कार्ड पाठवा</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">संलग्नक पाठवा</item>
+      <item quantity="other">संलग्नके पाठवा</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">पाठविण्‍यासाठी <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> संलग्नक सज्ज</item>
+      <item quantity="other">पाठविण्‍यासाठी <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> संलग्नक सज्ज</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"अभिप्राय पाठवा"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store मध्ये पहा"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"आवृत्ती माहिती"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"आवृत्ती %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"मुक्त स्त्रोत परवाने"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"सूचना"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"संलग्नक मर्यादेपर्यंत पोहोचले"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"संलग्नक लोड करण्यात अयशस्वी."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"संपर्कांवर जोडायचे?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"संपर्क जोडा"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"विषय"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"विषय: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"संपर्क कार्ड लोड करीत आहे"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"संपर्क कार्ड लोड करू शकलो नाही"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"संपर्क कार्ड पहा"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> संपर्क</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> संपर्क</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"संपर्क कार्ड"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"जन्मदिवस"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"टिपा"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"संदेश अग्रेषित करा"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"प्रत्युत्तर द्या"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS अक्षम"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"पाठविण्यासाठी, डीफॉल्ट SMS अॅप म्हणून संदेशन सेट करा"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"डीफॉल्ट SMS अॅप म्हणून संदेशन सेट करा"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"बदला"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"संदेश प्राप्त करण्यासाठी, डीफॉल्ट SMS अॅप म्हणून संदेशन सेट करा"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS संदेश पाठविण्यासाठी कोणतेही प्राधान्यकृत सिम निवडले नाही"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"या अॅप ला डिव्हाइस मालकाने अनुमती दिलेली नाही."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ठीक आहे"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"एका संभाषणात पुष्कळ सहभागी आहेत"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">अवैध संपर्क</item>
+      <item quantity="other">अवैध संपर्क</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"कॅमेरा प्रतिमा लोड करू शकलो नाही"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"आपण: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"मसुदा"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"आपण नवीन संभाषण प्रारंभ केल्यावर, आपल्याला तो येथे सूचीबद्ध केलेला दिसेल"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"संग्रहित केलेली संभाषणे येथे दिसतात"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"संभाषणे लोड करीत आहे…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"चित्र"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ऑडिओ क्लिप"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"व्हिडिओ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"संपर्क कार्ड"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"पूर्ववत करा"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"पुन्हा प्रयत्न करा"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"एक नवीन संदेश प्रारंभ करण्यासाठी एक संपर्क नाव किंवा फोन नंबर प्रविष्ट करा"</string>
+    <string name="action_block" msgid="9032076625645190136">"अवरोधित करा"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> अवरोधित करा"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> अनावरोधित करा"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> अवरोधित करायचे?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"आपण या नंबरवरून संदेश प्राप्त करणे सुरु ठेवाल परंतु आपल्याला आणखी सूचित केले जाणार नाही. हे संभाषम संग्रहित केले जाईल."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"अवरोधित संपर्क"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"अनावरोधित करा"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"अवरोधित संपर्क"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"दस्तऐवज लायब्ररीतून प्रतिमा निवडा"</string>
+    <string name="sending_message" msgid="6363584950085384929">"संदेश पाठवित आहे"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"संदेश पाठवला"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"सेल्युलर डेटा बंद आहे. आपल्या सेटिंग्ज तपासा."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"विमान मोडमध्ये संदेश पाठवू शकत नाही"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"संदेश पाठविला जाऊ शकला नाही"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"संदेश डाउनलोड केला"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"सेल्युलर डेटा बंद आहे. आपल्या सेटिंग्ज तपासा."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"विमान मोडमध्ये संदेश डाउनलोड करू शकत नाही"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"संदेश डाउनलोड करणे शक्य झाले नाही"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"शून्य"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"एक"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"दोन"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"तीन"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"चार"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"पाच"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"सहा"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"सात"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"आठ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"नऊ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> सह संदेश पाठवू शकत नाही, त्रुटी <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"अज्ञात वाहकासह संदेश पाठवू शकत नाही, त्रुटी <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"अग्रेषित: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"संदेश पाठविला नाही: नेटवर्क वर सेवा सक्रिय नाही"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"संदेश पाठविला नाही: अवैध गंतव्यस्‍थान पत्ता"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"संदेश पाठविला नाही: अवैध संदेश"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"संदेश पाठविला नाही: असमर्थित सामग्री"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"संदेश पाठविला नाही: असमर्थित संदेश"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"संदेश पाठविला नाही: खूप मोठा"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"नवीन संदेश"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"पहा"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"प्रतिमा"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"योग्य अनुप्रयोग शोधणे शक्य झाले नाही"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"प्राप्तकर्ता काढा"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"नवीन संदेश"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"रद्द करा"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"प्रवेश बिंदू संपादित करा"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"सेट केले नाही"</string>
+    <string name="apn_name" msgid="1572691851070894985">"नाव"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS प्रॉक्सी"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS पोर्ट"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN प्रकार"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN हटवा"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"नवीन APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"जतन करा"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"टाकून द्या"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"नाव फील्ड रिक्त असू शकत नाही."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN रिक्त असू शकत नाही."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC फील्ड 3 अंकी असणे आवश्यक आहे."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC फील्ड 2 किंवा 3 अंकी असणे आवश्यक आहे."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"डीफॉल्ट APN सेटिंग्ज पुनर्संचयित करत आहे."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"डीफॉल्टवर रीसेट करा"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"डीफॉल्ट APN सेटिंग्ज रीसेट करणे पूर्ण झाले."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"अशीर्षकांकित"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"प्रवेश बिंदू नावे"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"नवीन APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"या वापरकर्त्यासाठी प्रवेश बिंदू नाव सेटिंग्ज उपलब्ध नाहीत"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"क्लिपबोर्डवर कॉपी करायचे?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"कॉपी करा"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> वर"</string>
+    <string name="general_settings" msgid="5409336577057897710">"सामान्य"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"प्रगत"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"सामान्य सेटिंग्ज"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"प्रगत सेटिंग्ज"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" सिम"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"सर्व प्राप्तकर्त्यांना वैयक्तिक SMS संदेश पाठवा. केवळ आपणच कोणतीही प्रत्युत्तरे मिळवाल"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"सर्व प्राप्तकर्त्यांना एक एकल MMS पाठवा"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"अज्ञात नंबर"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"नवीन संदेश"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"नवीन संदेश."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"सिम निवडकर्ता"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> निवडले, सिम निवडकर्ता"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"विषय संपादित करा"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"सिम निवडा किंवा विषय संपादित करा"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ऑडिओ रेकॉर्ड करण्‍यासाठी स्पर्श करा आणि धरून ठेवा"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"नवीन संभाषण प्रारंभ करा"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"संदेशन"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"संदेशन सूची"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"संदेशन"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"नवीन संदेश"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"संभाषण सूची"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"संभाषणे लोड करीत आहे"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"संदेश लोड करत आहे"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"अधिक संभाषणे पहा"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"अधिक संदेश पहा"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"संभाषण हटवले"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"संभाषण हटविले. भिन्न संदेशन संभाषण दर्शविण्यासाठी स्पर्श करा"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"अवरोधित केले"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"अनावरोधित केले"</string>
+    <string name="db_full" msgid="8459265782521418031">"संचयन स्थान कमी आहे. काही डेटा गमावला जाऊ शकतो."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"संलग्नके निवडा"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"निवडीची पुष्टी करा"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> निवडली"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"कृपया एक किंवा अधिक संलग्नके काढा आणि पुन्हा प्रयत्न करा."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"आपण आपला संदेश पाठविण्याचा प्रयत्न करू शकता, परंतु आपण जोपर्यंत एक किंवा अधिक संलग्नके काढत नाही तोपर्यंत तो वितरित केला जाऊ शकत नाही."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"आपण प्रति संदेश केवळ एक व्हिडिओ पाठवू शकता. कृपया अतिरिक्त व्हिडिओ काढा आणि पुन्हा प्रयत्न करा."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"संलग्नक लोड करण्यात संदेशन अयशस्वी झाले."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"तरीही पाठवा"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"संभाषण प्रारंभ करू शकलो नाही"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> निवडले"</string>
+</resources>
diff --git a/res/values-ms/arrays.xml b/res/values-ms/arrays.xml
new file mode 100644
index 0000000..10f0c1c
--- /dev/null
+++ b/res/values-ms/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"tiada subjek"</item>
+    <item msgid="272485471009191934">"tiada subjek"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ya"</item>
+    <item msgid="6049132459802288033">"Tidak"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Terima kasih"</item>
+    <item msgid="4881335087096496747">"Saya bersetuju"</item>
+    <item msgid="2422296858597420738">"Nice"</item>
+    <item msgid="4805581752819452687">"Saya dalam perjalanan"</item>
+    <item msgid="4746700499431366214">"OK, saya akan hubungi anda semula"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
new file mode 100644
index 0000000..3094e1d
--- /dev/null
+++ b/res/values-ms/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Pemesejan"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Pemesejan"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Pilih perbualan"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Tetapan"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Hantar Mesej"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Tambah lampiran"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Bantuan"</string>
+    <string name="welcome" msgid="2857560951820802321">"Selamat datang"</string>
+    <string name="skip" msgid="7238879696319945853">"Langkau"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Seterusnya &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Seterusnya"</string>
+    <string name="exit" msgid="1905187380359981199">"Keluar"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Tetapan &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Tetapan"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Pemesejan memerlukan kebenaran untuk mengakses SMS, Telefon dan Kenalan."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Anda boleh menukar kebenaran dalam Tetapan &gt; Apl &gt; Pemesejan &gt; Kebenaran."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Anda boleh menukar kebenaran dalam Tetapan, Apl, Pemesejan, Kebenaran."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Kerap"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Semua kenalan"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Hantar ke <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Abadikan gambar atau video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Pilih imej dari peranti ini"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Rakam audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Pilih foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Media dipilih."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Media tidak dipilih."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> dipilih"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imej <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imej"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Rakam audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Kongsi"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Sebentar tadi"</string>
+    <string name="posted_now" msgid="867560789350406701">"Sekarang"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> jam</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> jam</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hari</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hari</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minggu</item>
+      <item quantity="one">seminggu</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> bulan</item>
+      <item quantity="one">sebulan</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tahun</item>
+      <item quantity="one">setahun</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mesej kelas 0"</string>
+    <string name="save" msgid="5081141452059463572">"Simpan"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Peranti kekurangan ruang. Pemesejan akan memadamkan mesej yang lebih lama secara automatik untuk mengosongkan ruang."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Ruang storan semakin berkurangan"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Pemesejan mungkin tidak akan menghantar atau menerima mesej sehingga lebih banyak ruang tersedia pada peranti anda."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Storan SMS kurang. Anda mungkin perlu memadamkan mesej."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Sahkan nombor telefon anda"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Langkah sekali ini akan memastikan Pemesejan menghantar mesej kumpulan anda dengan betul."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Nombor telefon"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Padamkan semua mesej dengan media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Padamkan mesej yang lebih lama daripada <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Auto padam mesej yang lebih lama daripada <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Abaikan"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Padam semua mesej dengan media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Padam mesej yang lebih lama daripada <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Padam mesej yang lebih lama daripada <xliff:g id="DURATION">%s</xliff:g> dan hidupkan autopadam?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> kata"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Anda kata"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mesej daripada <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Anda telah menghantar mesej"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Menghantar…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Tidak dihantar. Sentuh untuk mencuba lagi."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Tidak dihantar. Mencuba lagi..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Hantar semula atau padam"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Sila buat panggilan suara ke perkhidmatan kecemasan. Mesej teks anda tidak dapat dihantar pada masa ini."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Gagal"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Mesej MMS baharu untuk dimuat turun"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Mesej MMS baharu"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Tidak dapat memuat turun"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Sentuh untuk mencuba lagi"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Sentuh untuk memuat turun"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Muat turun atau padam"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Memuat turun..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mesej telah tamat tempoh atau tidak tersedia"</string>
+    <string name="mms_info" msgid="3402311750134118165">"saiz: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, tarikh luput: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Tidak dapat menghantar. Penerima tidak sah."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Perkhidmatan tidak diaktifkan pada rangkaian"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Tidak dapat menghantar kerana masalah rangkaian"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mesej telah tamat tempoh atau tidak tersedia"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Tiada subjek)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Pengirim tidak dikenali"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Dikirimkan"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Tidak dapat memuat turun <xliff:g id="SUBJECT">%1$s</xliff:g> daripada <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Tidak dapat menyelesaikan operasi pangkalan data akibat memori rendah"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mesej tidak dihantar"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Sesetengah mesej tidak dihantar dalam Pemesejan"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mesej dalam <xliff:g id="CONVERSATIONS">%d</xliff:g> perbualan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mesej dalam satu perbualan</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mesej tidak dimuat turun"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Sesetengah mesej tidak dimuat turun dalam Pemesejan"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mesej dalam <xliff:g id="CONVERSATIONS">%d</xliff:g> perbualan</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mesej dalam satu perbualan</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mesej ke <xliff:g id="NUMBER">%1$s</xliff:g> tidak dihantar"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Sila buat panggilan suara ke perkhidmatan kecemasan. Mesej teks anda ke <xliff:g id="NUMBER">%1$s</xliff:g> tidak dapat dihantar pada masa ini."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mesej baharu</item>
+      <item quantity="one">Mesej baharu</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Mula"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera tidak tersedia"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera tidak tersedia"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Pengabadian video tidak tersedia"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Tidak dapat menyimpan media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Tidak boleh mengambil gambar"</string>
+    <string name="back" msgid="1477626055115561645">"Kembali"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Diarkibkan"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Padam"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkib"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Nyaharkib"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Matikan pemberitahuan"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Hidupkan pemberitahuan"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Tambah kenalan"</string>
+    <string name="action_download" msgid="7786338136368564146">"Muat turun"</string>
+    <string name="action_send" msgid="377635240181672039">"Hantar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Padam"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Padamkan mesej ini?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tindakan ini tidak boleh dibuat asal."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Padam"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Padamkan perbualan ini?</item>
+      <item quantity="one">Padamkan perbualan ini?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Padam"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Batal"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Ke"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Pilih berbilang imej"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Sahkan pilihan"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Tidak dapat merakam audio. Cuba lagi."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Tidak dapat memainkan audio. Cuba lagi."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Tidak dapat menyimpan audio. Cuba lagi."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Sentuh &amp; tahan"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Gambar"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Klip audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video dalam strim"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kad kenalan"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Muat turun"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Balas melalui SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Balas melalui MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Balas"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> peserta</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> peserta</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Saya"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kenalan yang disekat &amp; diarkib"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kenalan dinyahsekat &amp; dinyaharkib"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> diarkibkan"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> dinyaharkib"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Pemberitahuan dimatikan"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Pemberitahuan dihidupkan"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Semuanya sedia. Sentuh Hantar lagi."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Pemesejan berjaya dijadikan sebagai apl SMS lalai."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Buang lampiran</item>
+      <item quantity="one">Buang lampiran</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Lampiran audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Mainkan lampiran audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Jeda"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mesej daripada <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mesej gagal daripada <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mesej daripada <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mesej tidak dihantar kepada <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Menghantar mesej kepada <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mesej gagal kepada <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mesej kepada <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mesej gagal daripada <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mesej daripada <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mesej tidak dihantar kepada <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Menghantar mesej kepada <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mesej gagal kepada <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mesej kepada <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Masa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mesej gagal. Sentuh untuk mencuba semula."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Perbualan dengan <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Padam subjek"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Rakam video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Abadikan imej pegun"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Ambil gambar"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Mula merakam video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Tukar kepada kamera skrin penuh"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Bertukar antara kamera hadapan dan belakang"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Berhenti merakam dan lampirkan video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Berhenti merakam video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto pemesejan"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> lampiran disimpan ke album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan ke album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> lampiran disimpan ke \"Muat Turun\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan ke \"Muat Turun\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> lampiran disimpan</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> lampiran disimpan</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Tidak dapat menyimpan <xliff:g id="QUANTITY_1">%d</xliff:g> lampiran</item>
+      <item quantity="one">Tidak dapat menyimpan <xliff:g id="QUANTITY_0">%d</xliff:g> lampiran</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Lampiran MMS yang disimpan"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Tetapan"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Diarkibkan"</string>
+    <string name="action_close" msgid="1840519376200478419">"Tutup"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Lanjutan"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Nyahpepijat"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Pemberitahuan"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Bunyi"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Senyap"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Bergetar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Disekat"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Laporan penghantaran SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Minta laporan penghantaran untuk setiap SMS yang anda hantar"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Auto dapat kembali"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Dapatkan semula mesej MMS secara automatik"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Dapatkan kembali perayauan secara automatik"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Dapatkan MMS secara automatik semasa merayau"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Pemesejan kumpulan"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Gunakan MMS untuk menghantar mesej tunggal apabila terdapat berbilang penerima"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Apl SMS lalai"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Apl SMS lalai"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Nombor telefon anda"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Tidak diketahui"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Bunyi mesej keluar"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Buang SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Buang data mentah SMS yang diterima ke dalam fail storan luaran"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Buang MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Buang data mentah MMS yang diterima ke dalam fail storan luaran"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Makluman wayarles"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Pilihan mesej"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Salin teks"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Lihat butiran"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Padam"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Kirim semula"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Butiran mesej"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Jenis: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mesej teks"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mesej multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"Daripada: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kepada: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Dihantar: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Diterima: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subjek: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Saiz: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Keutamaan: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Tinggi"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Biasa"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Rendah"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Alamat pengirim tersembunyi"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Tidak boleh menghantar mesej semasa memuatkan lampiran."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Tidak dapat memuatkan lampiran. Cuba lagi."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Rangkaian tidak sedia. Cuba lagi."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Padam teks"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Beralih antara memasukkan teks dan nombor"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Tambah peserta lagi"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Sahkan peserta"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Mulakan perbualan baharu"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Pilih item ini"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Mainkan video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Orang &amp; pilihan"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Nyahpepijat"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Orang &amp; pilihan"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Umum"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Orang dalam perbualan ini"</string>
+    <string name="action_call" msgid="6596167921517350362">"Buat panggilan"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Hantar mesej"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Hantar mesej&lt;br/&gt;&lt;small&gt;from <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Hantar foto</item>
+      <item quantity="one">Hantar foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Hantar audio</item>
+      <item quantity="one">Hantar audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Hantar video</item>
+      <item quantity="one">Hantar video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Hantar kad kenalan</item>
+      <item quantity="one">Hantar kad kenalan</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Hantar lampiran</item>
+      <item quantity="one">Hantar lampiran</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> lampiran sedia untuk dihantar</item>
+      <item quantity="one">Satu lampiran sedia untuk dihantar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Hantar maklum balas"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Lihat di Gedung Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Maklumat versi"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versi %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Lesen sumber terbuka"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Pemberitahuan"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Had lampiran dicapai"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Gagal memuatkan lampiran."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Tambah pada Kenalan?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Tambah Kenalan"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subjek"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subjek: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Memuatkan kad kenalan"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Tidak dapat memuatkan kad kenalan"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Lihat kad kenalan"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kenalan</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kenalan</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kad kenalan"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Tarikh lahir"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Nota"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Kirim semula mesej"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Balas"</string>
+    <string name="plus_one" msgid="9010288417554932581">"1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS dilumpuhkan"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Untuk menghantar, jadikan Pemesejan apl SMS lalai"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Jadikan Pemesejan apl SMS lalai"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Tukar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Untuk menerima mesej, jadikan Pemesejan apl SMS lalai"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Tiada SIM pilihan yang dipilih untuk menghantar mesej SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Apl ini tidak dibenarkan oleh pemilik peranti."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Terlalu ramai peserta dalam perbualan"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Kenalan tidak sah</item>
+      <item quantity="one">Kenalan tidak sah</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Tidak dapat memuatkan imej kamera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Anda: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draf"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Sebaik sahaja anda memulakan perbualan baharu, anda akan melihat perbualan itu disenaraikan di sini"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Perbualan diarkibkan dipaparkan di sini"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Memuatkan perbualan..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Gambar"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Klip audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kad kenalan"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Buat asal"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Cuba semula"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Masukkan nama kenalan atau nombor telefon untuk memulakan mesej baharu"</string>
+    <string name="action_block" msgid="9032076625645190136">"Sekat"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Sekat <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Nyahsekat <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Sekat <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Anda akan terus menerima mesej daripada nombor ini tetapi tidak akan dimaklumkan lagi. Perbualan ini akan diarkibkan."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Kenalan yang disekat"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"NYAHSEKAT"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Kenalan yang disekat"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Pilih imej dari perpustakaan dokumen"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Menghantar mesej"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mesej dihantar"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Data selular dimatikan. Periksa tetapan anda."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Tidak dapat menghantar mesej dalam mod Pesawat"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Mesej tidak dapat dihantar"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mesej dimuat turun"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Data selular dimatikan. Periksa tetapan anda."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Tidak dapat memuat turun mesej dalam mod Pesawat"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Mesej tidak dapat dimuat turun"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Sifar"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Satu"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dua"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tiga"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Empat"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Lima"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Enam"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Tujuh"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Lapan"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Sembilan"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Tidak dapat menghantar mesej dengan <xliff:g id="CARRIERNAME">%1$s</xliff:g>, ralat <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Tidak dapat menghantar mesej dengan pembawa yang tidak diketahui, ralat <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"K.S.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mesej tidak dihantar: perkhidmatan tidak diaktifkan di rangkaian"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mesej tidak dihantar: alamat destinasi tidak sah"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mesej tidak dihantar: mesej tidak sah"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mesej tidak dihantar: kandungan tidak disokong"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mesej tidak dihantar: mesej tidak disokong"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mesej tidak dihantar: terlalu besar"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mesej baharu"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Paparan"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imej"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Tidak menemui aplikasi yang sesuai"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Alih keluar penerima"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mesej baharu"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Batal"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edit titik capaian"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Tidak ditetapkan"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nama"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proksi MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Jenis APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Padam APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN Baharu"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Simpan"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Buang"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Medan Nama tidak boleh kosong."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN tidak boleh kosong."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Medan MCC mestilah 3 digit."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Medan MNC hendaklah mempunyai 2 atau 3 digit."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Memulihkan tetapan lalai APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Tetapkan semula kepada lalai"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Penetapan semula tetapan lalai APN selesai."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Tidak bertajuk"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nama Titik Capaian"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN Baharu"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Tetapan Nama Titik Capaian tidak tersedia untuk pengguna ini"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Salin ke papan keratan?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Salin"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ke <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Umum"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Lanjutan"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Tetapan umum"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Tetapan terperinci"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Hantar mesej SMS individu kepada semua penerima. Hanya anda yang akan menerima sebarang balasan"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Hantar MMS tunggal kepada semua penerima"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nombor tidak diketahui"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mesej baharu"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mesej baharu"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Pemilih SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> dipilih, pemilih SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edit subjek"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Pilih SIM atau edit subjek"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Sentuh dan tahan untuk merakam audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Mulakan perbualan baharu"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Pemesejan"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Senarai Pemesejan"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Pemesejan"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mesej baharu"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Senarai perbualan"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Memuatkan perbualan"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Memuatkan mesej"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Lihat lagi perbualan"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Lihat pesanan lagi"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Perbualan dipadamkan"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Perbualan dipadamkan. Sentuh untuk menunjukkan perbualan Pemesejan yang lain"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Disekat"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Dinyahsekat"</string>
+    <string name="db_full" msgid="8459265782521418031">"Ruang storan rendah. Sesetengah data mungkin hilang."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Pilih lampiran"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Sahkan pilihan"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> dipilih"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Sila alih keluar satu atau lebih lampiran, kemudian cuba lagi."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Anda boleh cuba menghantar mesej tetapi mesej itu mungkin tidak dihantar kecuali anda mengalih keluar satu atau beberapa lampiran."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Anda hanya boleh menghantar satu video bagi setiap mesej. Sila alih keluar video tambahan dan cuba lagi."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Pemesejan gagal memuatkan lampiran."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Hantar juga"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Tidak dapat memulakan perbualan"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> dipilih"</string>
+</resources>
diff --git a/res/values-my/arrays.xml b/res/values-my/arrays.xml
new file mode 100644
index 0000000..331ac85
--- /dev/null
+++ b/res/values-my/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"အကြောင်းအရာ မရှိ"</item>
+    <item msgid="272485471009191934">"အကြောင်းအရာမဲ့"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ဟုတ်"</item>
+    <item msgid="6049132459802288033">"မဟုတ်"</item>
+    <item msgid="3084376867445867895">"အိုကေ"</item>
+    <item msgid="3155097332660174689">"ဟဲဟဲ"</item>
+    <item msgid="2611328818571146775">"ကျေးဇူးပဲ"</item>
+    <item msgid="4881335087096496747">"ကျွန်ုပ် သဘောတူသည်"</item>
+    <item msgid="2422296858597420738">"ကောင်း"</item>
+    <item msgid="4805581752819452687">"ကျွန်ုပ်၏ လမ်းပေါ်မှာ"</item>
+    <item msgid="4746700499431366214">"အိုကေ၊ ကျွန်ုပ် နောက်မှာ ပြန်လာပါရစေ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
new file mode 100644
index 0000000..26df42e
--- /dev/null
+++ b/res/values-my/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"စာပို့ခြင်း"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"စာပို့ခြင်း"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"စကားဝိုင်း ရွေးချယ်ပါ"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ဆက်တင်များ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"စာ ပို့ရန်"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ပူးတွချက် တစ်ခု ထည့်ရန်"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"အကူအညီ"</string>
+    <string name="welcome" msgid="2857560951820802321">"မင်္ဂလာပါ"</string>
+    <string name="skip" msgid="7238879696319945853">"ကျော်ရန်"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"နောက်တစ်ခု"</string>
+    <string name="next" msgid="4496962051601713843">"နောက်တစ်ခု"</string>
+    <string name="exit" msgid="1905187380359981199">"ထွက်ရန်"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ချိန်ညှိချက်များ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ချိန်ညှိချက်များ"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"စာတိုပို့ခြင်က SMS၊ ဖုန်း နှင့် အဆက်အသွယ်များထံ ခွင့်ပြုချက် လိုအပ်သည်။"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"သင်သည် ခွင့်ပြုချက်များကို ဆက်တင်များထဲမှာ ပြောင်းလဲနိုင် &gt; အက်ပ်များ &gt; စာတိုပို့ခြင်း &gt; ခွင့်ပြုချက်များ။"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"သင်သည် ခွင့်ပြုချက်များကို ဆက်တင်များ၊ အက်ပ်များ၊ စာတိုပို့ခြင်း၊ ခွင့်ပြုချက်များထဲတွင် ပြောင်းလဲနိုင်သည်။"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"မကြာခဏ"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ဆက်သွယ်အားလုံး"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g>သို့ ပို့ရန်"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ပုံများ သို့မဟုတ် ဗီဒီယို ရိုက်ယူရန်"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ဤစက်ပစ္စည်းမှ ပုံများ ရွေးရန်"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"အသံကို ဖမ်းရန်"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ပုံရွေးရန်"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"မီဒီယာကိုရွေးချယ်ထားသည်။"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"မီဒီယာကို မရွေးချယ်ထားပါ။"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ခု ရွေးချယ်ထား"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ပုံ <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ပုံ"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"အသံကို ဖမ်းရန်"</string>
+    <string name="action_share" msgid="2143483844803153871">"မျှဝေရန်"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ယခုလေးတင်"</string>
+    <string name="posted_now" msgid="867560789350406701">"ယခု"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> မိနစ်</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> မိနစ်</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> နာရီ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> နာရီ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ရက်</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ရက်</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ပတ်</item>
+      <item quantity="one">၁ ပတ်</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> လ</item>
+      <item quantity="one">တစ်လ</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> နှစ်</item>
+      <item quantity="one">တစ်နှစ်</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"အဆင် ၀ စာတို"</string>
+    <string name="save" msgid="5081141452059463572">"သိမ်းဆည်းရန်"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ကိရိယာထဲတွင် နေရာ နည်းနေသည်။ နေရာလွတ်ပေးရန် စာတိုပို့ခြင်းက စာတို စာသား အဟောင်းကို အလိုအလျောက် ဖယ်ရှားပစ်မည်။"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"သိုလှောင်ခန်း နေရာ ကုန်ပါတော့မည်"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"သင်၏ ကိရိယာထဲတွင် နေရာလွတ် နောက်ထပ် ပေါ်မလာမချင်း စာတိုပို့ခြင်းက စာတိုများကို ပို့ခြင်း သို့မဟုတ် လက်ခံခြင်း လုပ်နိုင်မည် မဟုတ်ပါ။"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS သိုလှောင်ခန်း နည်းနေသည်။ သင်သည် စာများကို ဖျက်ချင် ဖျက်ရနိုင်သည်။"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"သင့် ဖုန်းနံပါတ်ကို အတည်ပြုပါ"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"တကြိမ် လုပ်ရသည့် ဒီခြေလှမ်းက စာတိုပို့ခြင်းမှ သင်၏ အုပ်စု စာတိုများကို စနစ်တကျ ပို့ပေးမှာကို စိတ်ချနိုင်ပါသည်။"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ဖုန်း နံပါတ်"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"မီဒီယာနှင့် စာများ အားလုံးကို ဖျက်မည်"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> ထက် ပိုကြာသော စာများကို ဖျက်မည်"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> မတိုင်ခင်က စာများအား အလိုအလျောက် ဖျက်ရန်"</string>
+    <string name="ignore" msgid="7063392681130898793">"လစ်လျှူရှုရန်"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"မီဒီယာနှင့် စာတိုများ ဖျက်မည်လား?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> ထက် ပိုကြာသော စာများ ဖျက်မည်လား?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> မတိုင်ခင်က စာများအား ဖျက်ပြီး စာများ အလိုအလျောက်ဖျက်နိုင်မှုကို ဖွင့်ထားမည်လား?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ပြောတာက"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"သင်ပြောတာက"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> ထံမှစာ"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"သင်စာပို့သည်"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"ပို့နေ၏…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"မပို့နိုင်ပါ။ ထပ်မံကြိုးစားရန် ထိပါ။"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"မပို့နိုင်ပါ။ ထပ်မံကြိုးစားနေ၏…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ပြန်ပို့ရန် သို့မဟုတ် ဖျက်ရန်"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"အရေးပေါ်ဝန်ဆောင်မှုများထံ အသံဖြင့် ခေါ်ပါ။ ယခုအချိန်တွင် သင့် စာတို မပို့နိုင်ပါ။"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"မအောင်မြင်ခဲ့"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"MMS စာအသစ်ကို ဒေါင်းလုဒ် လုပ်ရန်"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"MMS စာအသစ်"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ဒေါင်းလုဒ် မလုပ်နိုင်ခဲ့ပါ"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ထပ်စမ်းရန် ထိပါ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ဒေါင်းလုပ်ရယူရန် ထိပါ"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ဒေါင်းလုဒ် လုပ်ရန် သို့မဟုတ် ဖျက်ရန်"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ဒေါင်းလုပ် လုပ်နေစဉ်"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"စာသက်တမ်းကုန်ဆုံးသွား၏ သို့မဟုတ် စာမရှိတော့ပါ။"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ဆိုက်: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>၊ သက်တမ်း ကုန်ဆုံး: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"မပို့နိုင်ပါ။ လက်ခံမည့်သူ မရယူနိုင်ပါ။"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ကွန်ရက်တွင် ဝန်ဆောင်မှု စဖွင့်သတ်မှတ်ခြင်း မပြုရသေးပါ"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ကွန်ရက် ပြဿနာကြောင့် မပို့နိုင်ခဲ့ပါ။"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"စာ သက်တမ်းကုန်ဆုံးသွား၏ သို့မဟုတ် စာမရှိတော့ပါ။"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(အကြောင်းအရာမရှိ)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ပေးပို့သူ မသိရ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ပေးသွင်းပြီး"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="SUBJECT">%1$s</xliff:g>စာကို <xliff:g id="FROM">%2$s</xliff:g>မှ ဒေါင်းလုဒ် မလုပ်နိုင်ခဲ့ပါ"</string>
+    <string name="low_memory" msgid="5300743415198486619">"မှတ်ဉာဏ် နည်းနေ၍ ဒေတာဘေ့စ် လုပ်ကိုင်စရာ မပြီးဆုံးနိုင်ခဲ့ပါ။"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"စာ မပို့ခဲ့ပါ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"အချို့ စာတိုများကို စာပို့ခြင်းထဲတွင် မပို့ခဲ့ပါ။"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"> စာတိုများ <xliff:g id="MESSAGES_1">%d</xliff:g> ခုမှာ စကားပြောခန်း <xliff:g id="CONVERSATIONS">%d</xliff:g> ခု အတွင်းတွင် ဖြစ်၏</item>
+      <item quantity="one"> စကားပြောခန်းတစ်ခုတွင်းရှိ စာတိုများ <xliff:g id="MESSAGES_0">%d</xliff:g> ခု</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"စာကို ဒေါင်းလုပ်မလုပ်ထားပါ"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"အချို့ စာတိုများကို စာပို့ခြင်းထဲသို့ ဒေါင်းလုဒ် မလုပ်ခဲ့ပါ။"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"> စာတိုများ <xliff:g id="MESSAGES_1">%d</xliff:g> ခုမှာ စကားပြောခန်း <xliff:g id="CONVERSATIONS">%d</xliff:g> ခု အတွင်းတွင် ဖြစ်၏</item>
+      <item quantity="one"> စကားပြောခန်းတစ်ခုတွင်းရှိ စာတိုများ <xliff:g id="MESSAGES_0">%d</xliff:g> ခု</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> သို့ စာတို ပို့မရပါ"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"အရေးပေါ်ဝန်ဆောင်မှုများထံ အသံဖြင့် ခေါ်ပါ။ <xliff:g id="NUMBER">%1$s</xliff:g> သို့ ယခုအချိန်တွင် သင့် စာတို မပို့နိုင်ပါ။"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> စာအသစ်</item>
+      <item quantity="one">စာအသစ်</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"စတင်ရန်"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ကင်မရာ အသုံးမပြုနိုင်ပါ"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ကင်မရာ အသုံးမပြုနိုင်ပါ"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ဗွီဒီယို မရိုက်ယူနိုင်ပါ"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"မီဒီယာအား မသိမ်းဆည်းနိုင်ပါ"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ဓာတ်ပုံရိုက်၍ မရနိုင်ပါ"</string>
+    <string name="back" msgid="1477626055115561645">"နောက်သို့"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"မော်ကွန်းတင်ပြီး"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ဖျက်ရန်"</string>
+    <string name="action_archive" msgid="5437034800324083170">"မော်ကွန်း"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"မော်ကွန်းမှထုတ်ယူရန်"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"အက​ြောင်းကြားချက်များ ပိတ်ရန်"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"အကြောင်းကြားချက်များ ဖွင့်ရန်"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"အဆက်အသွယ် ထည့်ရန်"</string>
+    <string name="action_download" msgid="7786338136368564146">"ဒေါင်းလုဒ် လုပ်ရန်"</string>
+    <string name="action_send" msgid="377635240181672039">"ပို့ရန်"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ဖျက်ရန်"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ဤ စာကို ဖျက်မလား?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ဒီလုပ်ဆောင်ချက်ကို ြပန်ဖျက်မရနိုင်ပါ။"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ဖျက်ရန်"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ဤစကားဝိုင်းများအား ဖျက်မည်လား?</item>
+      <item quantity="one">ဤစကားဝိုင်းအား ဖျက်မည်လား?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ဖျက်ရန်"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ထားတော့"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"သို့"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"ပုံများစွာ ရွေးချယ်ရန်"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ရွေးချယ်မှုကို အတည်ပြုရန်"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"အသံ ဖမ်းမရပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"အသံဖွင့်မရပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"အသံ သိမ်းမရပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ထိပြီး &amp; ကိုင်ထားရန်"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ပုံ"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"အသံ ကလီပ်"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ဗီဒီယို"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"အဆက်အသွယ် ကဒ်"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ဒေါင်းလုဒ် လုပ်ရန်"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS မှတစ်ဆင့် ဖြေကြားရန်"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS ဖြင့် ဖြေကြားရန်"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ဖြေကြားရန်"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"> ပါဝင်သူ <xliff:g id="COUNT_1">%d</xliff:g> ယောက်</item>
+      <item quantity="one"> ပါဝင်သူ <xliff:g id="COUNT_0">%d</xliff:g> ယောက်</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ကျွန်ုပ်"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"အဆက်အသွယ်ဖြတ်တောက်ပြီး &amp; သိမ်းဆည်းပြီး"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"အဆက်အသွယ်အား မပိတ်ဆို့တော့ပါ &amp;amp မှော်ကွန်းမတင်တော့ပါ"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> မှတ်တမ်းတင်သိမ်းဆည်းခဲ့၏"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> သိမ်းထားခြင်းမှ ပြန်ထုတ်ယူသည်"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"အသိပေးချက်များ ပိတ်ထား"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"အသိပေးချက်များ ဖွင့်ထား"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"အဆင်သင့်ဖြစ်ပြီ။ Send အား ထိပါ။"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"စာတို့ပို့ခြင်းကို SMS ပုံသေ app အဖြစ် အောင်မြင်စွာ သတ်မှတ်လိုက်ပြီ။"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">ပူးတွဲပါဖိုင်များအား ဖယ်ရှားပါ</item>
+      <item quantity="one">ပူးတွဲပါဖိုင်အား ဖယ်ရှားပါ</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"အသံ ပူးတွဲဖိုင်"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ပူးတွဲပါအသံကိုဖွင့်ပါ"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ဆိုင်းငံ့ရန်"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> ထံမှ စာတို: <xliff:g id="MESSAGE">%2$s</xliff:g> ။"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> မှ စာတိုပို့ခြင်းမအောင်မြင်ပါ။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> မှ စာတို။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုမပို့ရသေးပါ။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုပို့နေသည်။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုပို့ခြင်းမအောင်မြင်ပါ။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတို။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> မှ စာပို့ခြင်းမအောင်မြင်ပါ။အချိန်: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>မှ စာတိုပို့နေသည်။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုမပို့ရသေးပါ။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုပို့ နေသည်။အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့စာတိုပို့ခြင်းမအောင်မြင်ပါ။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> သို့ စာတိုပို့နေသည်။ အချိန်: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"စာတိုပို့ခြင်းမအောင်မြင်ပါ။ ပြန်လည်ကြိုးစားရန် ထိပါ။"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g>နှင့် စကားဝိုင်းများ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"အကြောင်းအရာကို ဖျက်ရန်"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ဗီဒီယို ဖမ်းယူရန်"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ပုံသေ တစ်ခုကို ရိုက်ယူရန်"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ပုံ ရိုက်ယူရန်"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ဗီဒီယို ဖမ်းယူမှု စတင်ရန်"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"မျက်နှာပြင် အပြည့် ကင်မရာသို့ ပြောင်းရန်"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ကင်မရာ အရှေ့ဘက်နှင့် အနောက်ဘက် ပြောင်းရန်"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"မှတ်တမ်းတင်မှုရပ်ကာ ဗီဒီယို ချိတ်ရန်"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ဗွီဒီယိုရိုက်ကူးခြင်း ရပ်ရန်"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"ဓာတ်ပုံများကို စာတိုပို့ခြင်း"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ဓါတ်ပုံများကို \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ဓါတ်ပုံကို \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ဗီဒီယိုများကို \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ဗီဒီယိုကို \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ပူးတွဲပါဖိုင်များကို \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ပူးတွဲပါဖိုင်ကို \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" အယ်လ်ဘမ်သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ပူးတွဲပါဖိုင်များကို \"ဒေါင်းလုဒ်များ\" သို့ သိမ်းဆည်းပြီ:ပါပြီ</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ပူးတွဲပါဖိုင်ကို \"ဒေါင်းလုဒ်များ\" သို့ သိမ်းဆည်းပြီးပါပြီ</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"> ပူးတွဲပါဖိုင် <xliff:g id="QUANTITY_1">%d</xliff:g> ဖိုင် သိမ်းဆည်းပြီး၏</item>
+      <item quantity="one"> ပူးတွဲပါဖိုင် <xliff:g id="QUANTITY_0">%d</xliff:g> ဖိုင် သိမ်းဆည်းပြီး၏</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"> ပူးတွဲပါဖိုင် <xliff:g id="QUANTITY_1">%d</xliff:g> အား မသိမ်းဆည်းနိုင်ခဲ့ပါ</item>
+      <item quantity="one"> ပူးတွဲပါဖိုင် <xliff:g id="QUANTITY_0">%d</xliff:g> ဖိုင်အား မသိမ်းဆည်းနိုင်ခဲ့ပါ</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"သိမ်းဆည်းထားသည့် MMS ပူးတွဲချက်"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ဆက်တင်များ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"မော်ကွန်းတင်ပြီး"</string>
+    <string name="action_close" msgid="1840519376200478419">"ပိတ်ရန်"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"ရုပ်သံစာ"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"အဆင့်မြင့်"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ဒီဘာဂ်"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"အကြောင်းကြားချက်များ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"အသံ"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"အသံတိတ်ရန်"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"တုန်ခါရန်"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ပိတ်ဆို့ထား"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS ဖြန့်ဝေမှု အစီရင်ခံစာများ"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"သင် ပို့လိုက်သော စာတိုင်း အတွက် ပို့ပြီးကြောင်း အစီရင်ခံစာကို တောင်းဆိုမည်"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"အလိုအလျောက် ပြန်လည်ရယူမည်"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS စာများကို အလိုအလျောက် ရယူရန်"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ရုန်းမင်းလုပ်စဉ် အလိုအလျောက် ပြန်လည်ထုတ်ယူမည်"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ရုန်းမင်းသုံးစဉ် MMS အလိုအလျောက် ရယူရန်"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"အဖွဲ့လိုက် စာပို့ခြင်း"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"စာတစ်စောင်ပို့ရန် လက်ခံသူအမြောက်အမြားရှိနေလျှင် ရုပ်သံစာကို သုံးရန်"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"စာတိုပို့ရန်သုံး အပလီကေးရှင်း"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"စာတိုပို့ရန်သုံး အပလီကေးရှင်း"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"သင့် ဖုန်းနံပါတ်"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"မသိရ"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"အပြင်သို့စာပေးပို့သည့် အသံများ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"စိုစွတ် SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"စိုစွတ် SMS အချက်လက်အကြမ်းများကို ပြင်ပသိုလှောင်မှုဖိုင် သို့လက်ခံ ရရှိပါသည်"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"စိုစွတ် MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"စိုစွတ် MMS အချက်လက်အကြမ်းများကို ပြင်ပသိုလှောင်မှုဖိုင် သို့လက်ခံ ရရှိပါသည်"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ကြိုးမဲ့ သတိပေးချက်များ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"စာ အတွက် ရွေးစရာများ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"စာကူးယူရန်"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"အသေးစိတ်များကို ကြည့်မည်"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ဖျက်ရန်"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"တစ်ဆင့်ပို့ရန်"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"စာသေးစိတ်များ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"အမျိုးအစား: "</string>
+    <string name="text_message" msgid="7415419755252205721">"စာတို"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"မာလ်တီမီဒီယာ စာ"</string>
+    <string name="from_label" msgid="1947831848146564875">"မှ: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"သို့: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ပို့ပြီး: "</string>
+    <string name="received_label" msgid="4442494712757995203">"လက်ခံရရှိခဲ့: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"အကြောင်းအရာ: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"အရွယ်အစား: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ဦးစားပေးမှု: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"ဆင်းမ်: "</string>
+    <string name="priority_high" msgid="728836357310908368">"မြင့်"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ပုံမှန်"</string>
+    <string name="priority_low" msgid="7398724779026801851">"နိမ့်"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"ဆင်းမ် <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"ဝှက်ထားသော စာပို့သူ လိပ်စာ"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"ပူးတွဲချက်များဖွင့်စဉ် စာပို့၍မရပါ။"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ပူးတွဲဖိုင် မရယူနိုင်ပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ကွန်ရက်အဆင်သင့် မဖြစ်သေးပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"စာသားကို ဖျက်ရန်"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"စာသား နှင့် ဂဏန်းများ ရိုက်ထည့်မှု အကြားမှာ ပြောင်းလဲရန်"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"ပါဝင်သူများထပ်ထည့်မည်"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ပါဝင်သူများ အတည်ပြုရန်"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"ပြောဆိုမှု အသစ် စတင်ရန်"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ဒီအရာကို ရွေးရန်"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ဗီဒီယို ဖွင့်ရန်"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"လူများ &amp; ရွေးစရာများ"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ဒီဘာဂ်"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"လူများ &amp; ရွေးစရာများ"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"အထွေထွေ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ဒီစကားဝိုင်း ထဲက လူများ"</string>
+    <string name="action_call" msgid="6596167921517350362">"ခေါ်ဆိုမှု ပြုလုပ်ရန်"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"စာတို ပို့ရန်"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"စာတိုကို&lt;br/&gt;&lt;&gt; <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; ထံမှပို့ရန်"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ဓာတ်ပုံများ ပို့ရန်</item>
+      <item quantity="one">ဓာတ်ပုံ ပို့ရန်</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">အသံဖိုင်များ ပို့ရန်</item>
+      <item quantity="one">အသံဖိုင် ပို့ရန်</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ဗီဒီယိုများ ပို့ရန်</item>
+      <item quantity="one">ဗီဒီယို ပို့ရန်</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">အဆက်အသွယ်ကဒ်များ ပို့ရန်</item>
+      <item quantity="one">အဆက်အသွယ်ကဒ် ပို့ရန်</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">ပူးတွဲပါဖိုင်များ ပို့ရန်</item>
+      <item quantity="one">ပူးတွဲပါဖိုင် ပို့ရန်</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"> ပူးတွဲဖိုင် <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ဖိုင် ပို့ရန် အဆင်သင့်ဖြစ်၏</item>
+      <item quantity="one">ပူးတွဲဖိုင်တစ်ဖိုင် ပို့ရန် အဆင်သင့်ဖြစ်၏</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"တုံ့ပြန်ချက် ပို့ရန်"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google ပလေး စတိုးတွင် ကြည့်ရန်"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ဗားရှင်း အင်ဖို"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ဗားရှင်း %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"အခမဲ့ ရင်းမြစ် လိုင်စင်များ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"အကြောင်းကြားချက်များ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ချိတ်တွဲမှု ကန့်သတ်ချက်သို့ရောက်ရှိပါပြီ"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ချိတ်တွဲမှု ဖွင့်ရန်မအောင်မြင်ပါ။"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"အဆက်အသွယ်များသို့ ထည့်ရမလား?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"အဆက်အသွယ် ထည့်ရန်"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ဘာသာရပ်"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"အကြောင်းအရာ: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"အဆက်အသွယ် ကဒ်ကို တင်ပေးနေ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"နာမည်ကဒ် မရယူနိုင်ပါ"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"အဆက်အသွယ် ကဒ်ကို ကြည့်ရန်"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> အဆက်အသွယ်</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> အဆက်အသွယ်</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"နာမည် ကဒ်များ"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"မွေးနေ့"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"မှတ်စုများ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"စာကို တစ်ဆင့်ပို့ရန်"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"စာပြန်ရန်"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+၁"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS ပိတ်ထား"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ပို့ရန်အတွက် စာတိုပို့ခြင်းကို SMS ပုံသေ app အဖြစ် သတ်မှတ်ပေးပါ"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"စာတိုပို့ခြင်းကို SMS ပုံသေ app အဖြစ် သတ်မှတ်ရန်"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ပြောင်းရန်"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"စာတိုများကို လက်ခံရန်အတွက်၊ စာတိုပို့ခြင်းကို SMS ပုံသေ app အဖြစ် သတ်မှတ်ပေးပါ"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS စာများ ပို့ရန်အတွက် ဦးစားပေး ဆင်းမ်ကို မရွေးရသေးပါ"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ဒီappကို ကိရိယာ ပိုင်ရှင်က ခွင့် မပြုပါ။"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"အိုကေ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"စကားဝိုင်း တစ်ခုထဲမှာ ပါဝင်သူ များလွန်းနေ"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">အဆက်အသွယ်များ မမှန်ကန်ပါ</item>
+      <item quantity="one">အဆက်အသွယ် မမှန်ကန်ပါ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ကင်မရာ ပုံ မရယူနိုင်ပါ"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"သင်: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"မူကြမ်း"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"စကားပြောစတင်သည်နှင့်၊ ဤစာရင်းတွင် ပေါ်လာသည်ကို သင်မြင်ရလိမ့်မည်။"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ဤတွင်မြင်ရသည့် ပြောဆိုမှုများအား သိမ်းဆည်းရန်"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"ပြောဆိုမှုများကို တင်နေ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ပုံ"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"အသံ ကလီပ်"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ဗီဒီယို"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"အဆက်အသွယ် ကဒ်"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"ပြန်ဖျက်ရန်"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ထပ်စမ်းရန်"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"စာတို အသစ် စပို့ရန် အမည် သို့မဟုတ် ဖုန်းနံပါတ် ရိုက်ထည့်ပါ"</string>
+    <string name="action_block" msgid="9032076625645190136">"ပိတ်ဆို့ရန်"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"အဆက်အသွယ်ဖြတ်ရန် <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"အဆက်အသွယ်ပြန်လုပ် <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"ပိတ်ဆို့ရမလား<xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ဤနံပါတ်မှ စာတိုများ သင် ဆက်လက်ရရှိနေမည်ဖြစ်သော်လည်း အကြောင်းကြားချက်ပေးပို့တော့မည် မဟုတ်ပါ။ ဤပြောဆိုမှုများအား သိုလှောင်သိမ်းဆည်းထားမည်ဖြစ်၏။"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"အဆက်အသွယ် ဖြတ်ပြီး"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"အဆက်အသွယ်ပြန်လုပ်"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"အဆက်အသွယ် ဖြတ်ပြီး"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"စာကြည့်တိုက်မှ ပုံရွေးရန်"</string>
+    <string name="sending_message" msgid="6363584950085384929">"စာတိုပို့နေသည်"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"စာတိုပို့ပြီးပါပြီ"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ဆဲလူလာ ဒေတာ ပိတ်ထား၏။ ဆက်တင်တွင် စစ်ဆေးပါ။"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"လေယာဉ်ပျံပေါ်သုံးစနစ်တွင် စာများ မပို့နိုင်ပါ"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"စာများ ပို့၍မရပါ။"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"စာတိုအားဒေါင်းလုတ်လုပ်ပြီး"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ဆဲလူလာ ဒေတာ ပိတ်ထား၏။ ဆက်တင်တွင် စစ်ဆေးပါ။"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"လေယာဉ်ပျံမုဒ်တွင် စာတိုများကို ဒေါင်းလုပ်လုပ်၍မရနိုင်ပါ"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"စာတိုအား ဒေါင်းလုပ်လုပ်၍မရပါ"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"သုည"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"တစ်"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"နှစ်"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"သုံး"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"လေး"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ငါး"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ခြောက်"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ခုနစ်"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ရှစ်"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ကိုး"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g>ဖြင့် စာတိုမပို့နိုင်ပါ၊ အမှား <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"အမည်မသိသယ်ဆောင်သူဖြင့် စာတိုမပို့နိုင်ပါ၊ အမှား <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"တစ်ဆင့်ပို့: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"စာတိုကို မပို့ခဲ့: ဝန်ဆောင်မှုကို ကွန်ရက် ပေါ်မှာ စဖွင့်မသုံးရသေး"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"စာမပို့နိုင်ပါ − လက်ခံယူမည့် လိပ်စာ မှားနေ၏"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"စာမပို့နိုင်ပါ− စာ မမှန်ကန်ပါ။"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"စာမပို့နိုင်ပါ − ထောက်ပံ့မထားသော အကြောင်းအရာဖြစ်၏"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"စာမပို့နိုင်ပါ− ထောက်ပံ့မထားသော စာဖြစ်၏"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"စာပိုဒ်အလွန်ရှည်ပါက မက်ဆေ့ချ် ပို့မရပါ။"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"စာ အသစ်"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ကြည့်ရှုရန်"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ပုံ"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"သင့်တော်သည့် အပလီကေးရှင်းကို ရှာမရခဲ့"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"အဝေးမှ လက်ခံရရှိသူ"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"စာ အသစ်"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ဖျက်သိမ်းရန်"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ဝင်ရောက်မည့်ပွိုင့်အား ပြင်ဆင်ရန်"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"မသတ်မှတ်ထားပါ"</string>
+    <string name="apn_name" msgid="1572691851070894985">"အမည်"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ပရော့က်စီ"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS ပို့တ်နံပါတ်"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN အမျိုးအစား"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN ကိုဖျက်မည်"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN အသစ်"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"သိမ်းဆည်းရန်"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ဖျက်သိမ်းရန်"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"အမည်အကွက်မှာ ကွက်လပ်ဖြစ်မနေစေရပါ"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN မှာ ကွက်လပ်ဖြစ်မနေစေရပါ"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MNC အကွက်မှာ ဂဏန်း ၃ လုံးဖြစ်ရမည်"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC အကွက်မှာ ဂဏန်း ၂ လုံး သို့မဟုတ် ၃ လုံးဖြစ်ရမည်"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"မူရင်း APN ဆက်တင်များကိုပြန်လည်ရယူစေမည်"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"စနစ်အား မူလစက်ရုံအခြအေနေထံ ပြန်လည်သတ်မှတ်ရန်"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"APN ၏မူရင်းအပြင်အဆင်များကို အစသို့ပြန်လည်စတင်မှုအား ပြီးဆုံး၏။"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ခေါင်းစဉ်မဲ့"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ချိတ်ဆက်သောပွိုင့်အမည်များ"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN အသစ်"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ဤအသုံးပြုသူ အတွက် ချိတ်ဆက်သောပွိုင့်အမည်၏ ဆက်တင်များကို မရယူနိုင်"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ကလီပ်ဘုတ်သို့ ကူးရမလား?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ကူးယူရန်"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g>သို့"</string>
+    <string name="general_settings" msgid="5409336577057897710">"အထွေထွေ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"အဆင့်မြင့်သော"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"အထွေထွေ ဆက်တင်များ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"အဆင့်မြင့် ဆက်တင်များ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ရရှိသူ အားလုံးတို့ထံ တစ်ဦးချင်း SMS စာများကို ပို့ပါ။ သင်သည်သာလျှင် ​ဖြေကြားချက် မှန်သမျှကို ရရှိမည်။"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ရရှိသူ အားလုံးထံသို့ တစ်ခုတည်းသော MMS ကို ပို့ပါ"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"မသိရ နံပါတ်"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"စာ အသစ်"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"စာ အသစ်"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM ရွေးချယ်ပေးရေးလက္ခဏာရပ်"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ရွေးချယ်ပြီး၊ SIM ရွေးချယ်ပေးသူ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"အကြောင်းအရာကို တည်းဖြတ်ပါ။"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM ကို‌ရွေးချယ်ပါ သို့မဟုတ် အကြောင်းအရာတည်းဖြတ်ခြင်းကိုရွေးချယ်ပါ။"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"အသံအား ဖမ်းယူထားရန် ထိပြီးဖိထားပါ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"ပြောဆိုမှု အသစ် စတင်ရန်"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"စာတိုပို့ခြင်း"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"စာတိုပို့ခြင်း စာရင်း"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"စာတိုပို့ခြင်း"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"စာ အသစ်"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"ပြောဆိုမှုစာရင်း"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"စကားဝိုင်းများကို ဖွင့်နေသည်"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"စာများကို တင်နေ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"စကားပြောဆက်သွယ်မှုများကို ထပ်ပြီး ကြည့်မည်"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"နောက်ထပ် မက်ဆေ့များကြည့်ရန်"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"စကားဝိုင်းကို ဖျက်လိုက်ပြီ"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ပြောဆိုမှုကို ဖျက်ခဲ့သည်။ အခြား စာတိုပို့ခြင်း ပြောဆိုမှုကို ပြရန် တို့ထိပါ။"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ပိတ်ဆို့ထား"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"ပြန်ဖွင့်ထားခြင်း"</string>
+    <string name="db_full" msgid="8459265782521418031">"သိုလှောင်ထားသည့်နေရာ နည်းနေပါသည်။ ဒေတာတချို့ပျောက်ဆုံးပါလိမ့်မည်။"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ချိတ်တွဲမှုများ ရွေးချယ်မည်"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ရွေးချယ်မှုကို အတည်ပြုရန်"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ခရွေးချယ်ပြီး"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ကျေးဇူးပြု၍ တစ်ခု သို့မဟုတ် တစ်ခုထက်ပိုသော ချိတ်တွဲမှုများကို ဖယ်ရှားပြီး နောက်တစ်ကြိမ်ကြိုးစားပါ။"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"သင့်စာတိုကို ပေးပို့ရန် သင်ကြိုးစားနိုင်ပါသည်၊ သို့သော်သင်သည် တစ်ခုသို့မဟုတ် တစ်ခုထက်ပိုသော ချိတ်တွဲမှုများကို ဖယ်ရှားခြင်းမပြုပါက ၎င်းကို ပေးပို့မှုမရှိခြင်း ဖြစ်နိုင်သည်။"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"သင်သည် မက်ဆေ့ဂျ်တစ်ခုလျှင် ဗွီဒီယိုတကားသာ ပေးပို့နိုင်သည်။ အပိုဆောင်း ဗွီဒီယိုများအား ဖယ်ရှားပြီး ထပ်မံကြိုးစားပါ။"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"စာတိုကိုပို့စဉ် ပူးတွဲချက်ကို တင် မရခဲ့ပါ။"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"မည်သို့ပင်ဖြစ်စေ ပို့မည်"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"စကားဝိုင်းအား မစတင်နိုင်ပါ"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ရွေးချယ်ပြီး၏"</string>
+</resources>
diff --git a/res/values-nb/arrays.xml b/res/values-nb/arrays.xml
new file mode 100644
index 0000000..c9efc6f
--- /dev/null
+++ b/res/values-nb/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"emne mangler"</item>
+    <item msgid="272485471009191934">"ikke noe emne"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nei"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Takk"</item>
+    <item msgid="4881335087096496747">"Jeg er enig"</item>
+    <item msgid="2422296858597420738">"Bra"</item>
+    <item msgid="4805581752819452687">"Jeg er på vei"</item>
+    <item msgid="4746700499431366214">"OK, jeg tar kontakt med deg senere"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
new file mode 100644
index 0000000..ca04e94
--- /dev/null
+++ b/res/values-nb/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Meldinger"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Meldinger"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Markér samtalen"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Innstillinger"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Send meldingen"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Legg ved et vedlegg"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hjelp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Velkommen"</string>
+    <string name="skip" msgid="7238879696319945853">"Hopp over"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Neste &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Neste"</string>
+    <string name="exit" msgid="1905187380359981199">"Avslutt"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Innstillinger &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Innstillinger"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Meldinger trenger tillatelse til å bruke SMS, Telefon og Kontakter."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Du kan endre tillatelser i Innstillinger &gt; Apper &gt; Meldinger &gt; Tillatelser."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Du kan endre tillatelser i Innstillinger &gt; Apper &gt; Meldinger &gt; Tillatelser."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Ofte brukte"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alle kontakter"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Send til <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Ta bilder eller spill inn video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Velg bilder fra denne enheten"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Spill inn lyd"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Velg bilde"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Mediene er valgt."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Valget av mediene er fjernet."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> valgt"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"bilde <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"bilde"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Spill inn lyd"</string>
+    <string name="action_share" msgid="2143483844803153871">"Del"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Nå nettopp"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nå"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minutter</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minutt</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> timer</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> time</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"> dager</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> uker</item>
+      <item quantity="one">én uke</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> måneder</item>
+      <item quantity="one">én måned</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> år</item>
+      <item quantity="one">ett år</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Klasse 0-melding"</string>
+    <string name="save" msgid="5081141452059463572">"Lagre"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Enheten har lite lagringsplass. Meldinger-appen sletter eldre meldinger automatisk for å frigjøre lagringsplass."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Lite ledig lagringsplass"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Du kan kanskje ikke sende eller motta SMS i Meldinger før mer plass er tilgjengelig på enheten din."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Du har lite lagringsplass for SMS. Du må slette andre meldinger."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Bekreft telefonnummeret ditt"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Dette engangstrinnet sikrer at Meldinger leverer gruppemeldingene dine på riktig måte."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonnummer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Slett alle meldinger med medier"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Slett meldinger som er eldre enn <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Slett meldinger som er eldre enn <xliff:g id="DURATION">%s</xliff:g> automatisk"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorer"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Vil du slette alle meldinger med media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Vil du slette meldinger som er eldre enn <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Vil du slette meldinger som er eldre enn <xliff:g id="DURATION">%s</xliff:g> og slå av automatisk sletting?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sa"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Du sa"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Melding fra <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Du sendte en melding"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Sender ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ikke sendt. Trykk for å prøve på nytt."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ikke sendt. Prøver på nytt …"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Send på nytt eller slett"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Ring til alarmsentralen. Tekstmeldingen kunne ikke leveres for øyeblikket."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Mislykket"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Ny MMS-melding for nedlasting"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Ny MMS-melding"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Kan ikke laste ned"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Trykk for å prøve på nytt"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Trykk for å laste ned"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Last ned eller slett"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Laster ned …"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Meldingen er utløpt eller ikke tilgjengelig"</string>
+    <string name="mms_info" msgid="3402311750134118165">"størrelse: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, utløper: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Kan ikke sende. Mottaker er ikke gyldig."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Tjenesten er ikke aktivert på nettverket"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Kunne ikke sende på grunn av et nettverksproblem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Meldingen er utløpt eller ikke tilgjengelig"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Mangler emne)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Ukjent avsender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Levert"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Kunne ikke laste ned meldingen <xliff:g id="SUBJECT">%1$s</xliff:g> fra <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Databasehandlingen kunne ikke fullføres på grunn av lite minne."</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Meldingen er ikke sendt"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Enkelte meldinger er ikke sendt i Meldinger"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> meldinger i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> meldinger i én samtale</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Meldingen er ikke lastet ned"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Enkelte meldinger er ikke lastet ned i Meldinger"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> meldinger i <xliff:g id="CONVERSATIONS">%d</xliff:g> samtaler</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> meldinger i én samtale</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Melding til <xliff:g id="NUMBER">%1$s</xliff:g> ble ikke sendt"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Ring til alarmsentralen. Tekstmeldingen til <xliff:g id="NUMBER">%1$s</xliff:g> kunne ikke leveres for øyeblikket."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nye meldinger</item>
+      <item quantity="one">Ny melding</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Start"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kameraet er ikke tilgjengelig"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kameraet er ikke tilgjengelig"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Videoinnspilling er ikke tilgjengelig"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Kan ikke lagre media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Kan ikke ta bilde"</string>
+    <string name="back" msgid="1477626055115561645">"Tilbake"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arkivert"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Slett"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkivér"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Fjern fra arkivet"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Slå av varsler"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Slå på varsler"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Legg til kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Last ned"</string>
+    <string name="action_send" msgid="377635240181672039">"Send"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Slett"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vil du slette denne meldingen?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Denne handlingen kan ikke angres."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Slett"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Vil du slette disse samtalene?</item>
+      <item quantity="one">Vil du slette denne samtalen?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Slett"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Avbryt"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Til"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Velg flere bilder"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Bekreft utvalget"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Kan ikke ta opp lyd. Prøv på nytt."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Kan ikke spille av lyd. Prøv på nytt."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Kunne ikke lagre lydfil. Prøv på nytt."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Berør og hold nede"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Bilde"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Lydklipp"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktkort"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Last ned"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Svar via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Svar via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Svar"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> deltakere</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> deltaker</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Meg"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakten er blokkert og arkivert"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt ublokkerte &amp; uarkiverte"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> er arkivert"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> er fjernet fra arkivet"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Varsler er slått av"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Varsler er slått av"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Alt klart. Trykk på Send én gang til."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Meldinger er nå angitt som standard SMS-app."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Forkast vedlegg</item>
+      <item quantity="one">Forkast vedlegget</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Lydvedlegg"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Spill av lydvedlegg"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Sett på pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Melding fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mislykket melding fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Melding fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Usendt melding til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Sender melding til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mislykket melding til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Melding til <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mislykket melding fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Melding fra <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Usendt melding til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Sender melding til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mislykket melding til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Melding til <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidspunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Meldingen ble ikke sendt. Trykk for å prøve på nytt."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Samtale med <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Slett emnet"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Ta video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Ta et stillbilde"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Ta bilde"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Start et videoopptak"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Bytt til fullskjermkamera"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Bytt mellom for- og baksidekamera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stopp opptak og legg ved video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Slutt å filme"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Bilder i Meldinger"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> bilder er lagret i albumet «<xliff:g id="ALBUMNAME_3">%s</xliff:g>»</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bilde er lagret i albumet «<xliff:g id="ALBUMNAME_1">%s</xliff:g>»</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videoer er lagret i albumet «<xliff:g id="ALBUMNAME_3">%s</xliff:g>»</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video er lagret i albumet «<xliff:g id="ALBUMNAME_1">%s</xliff:g>»</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> tillegg er lagret i albumet «<xliff:g id="ALBUMNAME_3">%s</xliff:g>»</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> tillegg er lagret i albumet «<xliff:g id="ALBUMNAME_1">%s</xliff:g>»</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> tillegg er lagret i «Nedlastinger»</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> tillegg er lagret i «Nedlastinger»</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> vedlegg er lagret</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> vedlegg er lagret</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Kunne ikke lagre <xliff:g id="QUANTITY_1">%d</xliff:g> vedlegg</item>
+      <item quantity="one">Kunne ikke lagre <xliff:g id="QUANTITY_0">%d</xliff:g> vedlegg</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS-vedlegget er lagret"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Innstillinger"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arkivert"</string>
+    <string name="action_close" msgid="1840519376200478419">"Lukk"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avansert"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Feilsøk"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Varsler"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Lyd"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Stille"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrer"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokkert"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Leveringsrapporter for SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Be om leveringsrapport for hver SMS du sender"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatisk henting"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Hent MMS-meldinger automatisk"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatisk henting under roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Hent MMS automatisk ved romaning"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Gruppemeldinger"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Bruk MMS for å sende én melding med flere mottakere"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Standard SMS-app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Standard SMS-app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Telefonnummeret ditt"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Ukjent"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Lyder for utgående meldinger"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Dump SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Dump rådata fra mottatte SMS-er i en ekstern lagringsfil"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Dump MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dump rådata fra mottatte MMS-er i en ekstern lagringsfil"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Trådløse varsler"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Meldingsalternativer"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiér teksten"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Se detaljer"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Slett"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Videresend"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Meldingsinformasjon"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Bildemelding"</string>
+    <string name="from_label" msgid="1947831848146564875">"Fra: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Til: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Sendt: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Mottatt: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Emne: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Størrelse: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-kort: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Høy"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Vanlig"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Lav"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-kort <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skjult avsenderadresse"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Meldingen kan ikke sendes mens vedleggene lastes inn."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Kan ikke laste inn vedlegg. Prøv på nytt."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Nettverket er ikke klart. Prøv på nytt."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Slett teksten"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Veksle mellom å skrive inn tekst og tall"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Legg til flere deltakere"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Bekreft deltakere"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Start ny samtale"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Velg dette elementet"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Spill av videoen"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Personer-appen og alternativer"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Feilsøk"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Personer-appen og alternativer"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Generelt"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Folk i denne samtalen"</string>
+    <string name="action_call" msgid="6596167921517350362">"Start en samtale"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Send melding"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Send melding&lt;br/&gt;&lt;small&gt;fra <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Send bilder</item>
+      <item quantity="one">Send bilde</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Send lydklipp</item>
+      <item quantity="one">Send lydklipp</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Send videoer</item>
+      <item quantity="one">Send video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Send kontaktkort</item>
+      <item quantity="one">Send kontaktkort</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Send vedlegg</item>
+      <item quantity="one">Send vedlegg</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> vedlegg er klare til å sendes</item>
+      <item quantity="one">Ett vedlegg er klart til å sendes</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Send tilbakemelding"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Se i Google Play-butikken"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versjonsinformasjon"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versjon %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Lisenser for åpen kildekode"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Varsler"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Vedleggsgrensen er nådd"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Kunne ikke laste inn vedlegg."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Vil du legge til nummeret i kontakter?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Legg til kontakten"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Emne"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Emne: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Laster inn kontaktkortet"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kunne ikke laste kontaktkort"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Se kontaktkortet"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakter</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktkort"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Fødselsdag"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notater"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Videresend meldingen"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Svar"</string>
+    <string name="plus_one" msgid="9010288417554932581">"1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS er deaktivert"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"For å sende meldinger, angi Meldinger som standard SMS-app"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Angi Meldinger som standard SMS-app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Endre"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"For å motta meldinger, angi Meldinger som standard SMS-app"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ingen foretrukne SIM-kort er valgt for å sende SMS-meldinger"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Denne appen er ikke tillatt av enhetseieren."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"For mange deltakere i en samtale"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Ugyldige kontakter</item>
+      <item quantity="one">Ugyldig kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kunne ikke laste inn kamerabilde"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Du: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Utkast"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Når du starter en ny samtale, vises den her"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arkiverte samtaler vises her"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Laster inn samtaler ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Bilde"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Lydklipp"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Instream-video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktkort"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Angre"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Prøv på nytt"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Skriv inn et kontaktnavn eller -telefonnummer for å starte en ny melding"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokkér"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokkér <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Opphev blokkeringen av <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vil du blokkere <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Du fortsetter å motta meldinger fra dette nummeret, men blir ikke lenger varslet. Denne samtalen blir arkivert."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokkerte kontakter"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"OPPHEV BLOKKERING"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokkerte kontakter"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Velg et bilde fra dokumentbiblioteket"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Sender meldingen"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Meldingen er sendt"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobildata er slått av. Sjekk innstillingene dine."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Kan ikke sende meldinger i flymodus"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Kan ikke sende meldingen"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Meldingen er nedlastet"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobildata er slått av. Sjekk innstillingene dine."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Kan ikke laste ned meldinger i flymodus"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Meldingen kunne ikke lastes ned"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Null"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Én"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"To"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tre"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Fire"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Fem"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seks"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sju"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Åtte"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Ni"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Kan ikke sende meldinger med <xliff:g id="CARRIERNAME">%1$s</xliff:g> – feil <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Kan ikke sende meldinger med ukjent operatør – feil <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"V.send: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Meldingen er ikke sendt: Tjenesten er ikke aktivert på nettverket"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Meldingen ble ikke sendt: ugyldig måladresse"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Meldingen ble ikke sendt: ugyldig melding"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Meldingen ble ikke sendt: innholdet støttes ikke"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Meldingen ble ikke sendt: meldingen støttes ikke"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Meldingen ble ikke sendt: Den var for stor."</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Ny melding"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Se"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Bilde"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Kunne ikke finne en passende app"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Fjern mottakeren"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Ny melding"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Avbryt"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Rediger tilgangspunkt"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ikke angitt"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Navn"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN-navn"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy-tjener for MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-type"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Slett APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Ny APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Lagre"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Forkast"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Navnefeltet kan ikke være tomt."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN kan ikke være tomt."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-feltet må bestå av tre siffer."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-feltet må bestå av to eller tre siffer."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Gjenoppretter standard APN-innstillinger."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Tilbakestill til standard"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Tilbakestilling av standard APN-innstillinger er fullført."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Uten navn"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Navn på tilgangspunkt"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-er"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Ny APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Innstillingene for navn på tilgangspunkt er ikke tilgjengelig for denne brukeren"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Vil du kopiere til utklippstavlen?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiér"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"til <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Generelt"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avansert"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Generelle innstillinger"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Avanserte innstillinger"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"«<xliff:g id="SIM_NAME">%s</xliff:g>»-SIM-kort"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Send SMS-meldinger til alle mottakere. Bare du mottar svarene."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Send én enkelt MMS til alle mottakere"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Ukjent nummer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Ny melding"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Ny melding."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-kortvelger"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> er valgt – SIM-kortvelger"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Rediger emne"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Velg SIM-kort eller rediger emnet"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Trykk og hold inne for å ta opp lyd"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Start ny samtale"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Meldinger"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Samtaleliste"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Meldinger"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Ny melding"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Samtaleliste"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Laster inn samtaler"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Laster inn e-postmeldinger"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Se flere samtaler"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Se flere e-poster"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Samtalen er slettet"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Samtalen er slettet. Trykk for å se en annen samtale i Meldinger"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokkert"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blokkeringen er opphevet"</string>
+    <string name="db_full" msgid="8459265782521418031">"Lite lagringsplass ledig. Noen data kan gå tapt."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Velg vedlegg"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Bekreft utvalget"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> er valgt"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Fjern ett eller flere vedlegg og prøv på nytt."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Du kan prøve å sende meldingen din, men det er ikke sikkert at den kommer frem med mindre du fjerner ett eller flere vedlegg."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Du kan bare sende én video per melding. Fjern overflødige videoer og prøv igjen."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Meldinger kunne ikke laste inn vedlegget."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Send likevel"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Kunne ikke starte samtalen"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> er valgt"</string>
+</resources>
diff --git a/res/values-ne/arrays.xml b/res/values-ne/arrays.xml
new file mode 100644
index 0000000..614436d
--- /dev/null
+++ b/res/values-ne/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"शीर्षक नभएको"</item>
+    <item msgid="272485471009191934">"विषय छैन"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"हो"</item>
+    <item msgid="6049132459802288033">"हैन"</item>
+    <item msgid="3084376867445867895">"ठीक छ"</item>
+    <item msgid="3155097332660174689">"हाहा"</item>
+    <item msgid="2611328818571146775">"धन्यवाद"</item>
+    <item msgid="4881335087096496747">"म सहमत छु"</item>
+    <item msgid="2422296858597420738">"राम्रो"</item>
+    <item msgid="4805581752819452687">"मेरो बाटोमा"</item>
+    <item msgid="4746700499431366214">"ठीक छ, तपाईंलाई पछिको लागि मलाई अनुमति दिनुहोस्"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
new file mode 100644
index 0000000..b269345
--- /dev/null
+++ b/res/values-ne/strings.xml
@@ -0,0 +1,521 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"सन्देश पठाइदै"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"सन्देश पठाइदै"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"कुराकानी चयन गर्नुहोस्"</string>
+    <string name="action_settings" msgid="1329008122345201684">"सेटिङ्हरू"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"सन्देश पठाउनुहोस्"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"एक अनुलग्नक थप गर्नुहोस्"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"मद्दत"</string>
+    <string name="welcome" msgid="2857560951820802321">"स्वागतम"</string>
+    <string name="skip" msgid="7238879696319945853">"छोड्नुहोस्"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"अर्को &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"अर्को"</string>
+    <string name="exit" msgid="1905187380359981199">"बाहिर"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"सेटिङहरू &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"सेटिङहरू"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"सन्देश प्रवाहलाई SMS, फोन र सम्पर्क ठेगानाहरूमा अनुमतिको आवश्यक पर्छ।"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"तपाईँ अनुमतिहरूलाई सेटिङ अनुप्रयोगहरू &gt; सन्देश प्रवाह &gt; अनुमतिहरूमा परिवर्तन गर्न सक्नु हुनेछ।"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"तपाईँ अनुमतिहरूलाई सेटिङ अनुप्रयोगहरू, सन्देश प्रवाह, अनुमतिहरूमा परिवर्तन गर्न सक्नु हुनेछ।"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"नियमित"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"सबै सम्पर्कहरू"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> मा पठाउनुहोस्"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"तस्बिर वा भिडियो लिनुहोस्"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"यस उपकरणबाट तस्बिरहरू छान्नुहोस्"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ध्वनि रेकर्ड गर्नुहोस्"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"फोटो छान्नुहोस्"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"यस मिडिया चयन गरिएको छ।"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"यस मिडियाको चयन हटाइएको छ।"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> चयन गरियो"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"छवि <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"छवि"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ध्वनि रेकर्ड गर्नुहोस्"</string>
+    <string name="action_share" msgid="2143483844803153871">"साझेदारी गर्नुहोस्"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"अहिले भर्खर"</string>
+    <string name="posted_now" msgid="867560789350406701">"अब"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनेट</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> मिनेट</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> घन्टा</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> घन्टा</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> दिन</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> दिन</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> हप्ता</item>
+      <item quantity="one"> एक हप्ता</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> महिना</item>
+      <item quantity="one"> एक महिना</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> वर्ष</item>
+      <item quantity="one"> एक वर्ष</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"वर्ग ० सन्देश"</string>
+    <string name="save" msgid="5081141452059463572">"सुरक्षित गर्नुहोस्"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"यन्त्रमा ठाउँ कम छ। ठाउँ खाली गर्न सन्देश प्रवाहले पुराना सन्देशहरूलाई स्वचालित रूपमा मेट्ने छ।"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"भण्डारण ठाउँ सकिँदै छ"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"तपाईँको यन्त्रमा थप ठाउँ उपलब्ध नभएसम्म सन्देश प्रवाहले सन्देश पठाउन वा प्राप्त नगर्न सक्छ।"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS भण्डारणमा कमी। तपाईँले सन्देशहरु हटाउनु पर्नेहुन्छ।"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"आफ्नो फोन नम्बर पुष्टि गर्नुहोस्"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"यो एक पटके चरणले सन्देश प्रवाहले तपाईँको समूह सन्देशहरू उचित रूपमा डेलिभर गर्ने छ भन्ने सुनिश्चित गर्ने छ।"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"फोन नम्बर"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"मीडियाको साथमा सबै सन्देशहरु मेटाउनुहोस्"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> भन्दा पुराना सन्देशहरुलाई मेट्नुहोस्"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> भन्दा पुरानो सन्देशहरू स्वत: मेट्नुहोस्"</string>
+    <string name="ignore" msgid="7063392681130898793">"बेवास्ता गर्नुहोस्"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"मिडिया भएको सन्देशहरू मेट्ने?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> भन्दा पुरानो सन्देशहरू मेट्ने?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> भन्दा पुरानो सन्देशहरू मेटाउनुहुन्छ र स्वचालित-मेट्ने सक्षम गर्नुहुन्छ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ले भन्नुभयो"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"तपाईंले भन्नुभयो"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g>  बाट सन्देश"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"तपाईंले एक सन्देश पठाउनुभयो"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"पठाउँदै..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"पठाइएको छैन। पुन: प्रयास गर्न छुनुहोस्।"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"पठाइएको छैन। पुन: प्रयास गर्दै ..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"पुन: पठाउनुहोस् वा मेट्नुहोस्"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"कृपया आकस्मिक सेवाहरूमा आवाज कल गर्नुहोस्। तपाईंको पाठ सन्देश यो समयमा डेलिभर हुन सक्दैन।"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"विफल भयो"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"डाउनलोड गर्न नयाँ MMS सन्देश"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"नयाँ MMS सन्देश"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"डाउनलोड गर्न सकिएन"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"पुनः प्रयास गर्न छुनुहोस्"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"डाउनलोड गर्न छुनुहोस्"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"डाउनलोड वा मेट्नुहोस्"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"डाउनलोड हुँदै..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"सन्देशको अवधि सकियो वा उपलब्ध छैन"</string>
+    <string name="mms_info" msgid="3402311750134118165">"आकार: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, समाप्ति: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"पठाउन सकिएन। प्रापक मान्य छैन।"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"नेटवर्कमा सेवा सक्रिय छैन"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"नेटवर्कको समस्याको कारण पठाउन सकिएन"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"सन्देशको अवधि सकियो वा उपलब्ध छैन"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(कुनै विषय छैन)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"अज्ञात प्रेषक"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"पुर्याइयो"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> बाट सन्देश <xliff:g id="SUBJECT">%1$s</xliff:g> डाउनलोड गर्न सकिएन।"</string>
+    <string name="low_memory" msgid="5300743415198486619">"कम मेमोरीका कारण डेटाबेस कार्य पुरा गर्न सकिएन।"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"सन्देश पठाइएन"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"केही सन्देशहरू सन्देश प्रवाहमा पठाइएनन्"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापमा <xliff:g id="MESSAGES_1">%d</xliff:g> सन्देशहरू</item>
+      <item quantity="one"> एउटा वार्तालापमा <xliff:g id="MESSAGES_0">%d</xliff:g> सन्देशहरू</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"सन्देश डाउनलोड भएन"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"सन्देशहरू सन्देश प्रवाहमा डाउनलोड भएनन्"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> वार्तालापमा <xliff:g id="MESSAGES_1">%d</xliff:g> सन्देशहरू</item>
+      <item quantity="one"> एउटा वार्तालापमा <xliff:g id="MESSAGES_0">%d</xliff:g> सन्देशहरू</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> मा सन्देश पठाइएन"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"कृपया आकस्मिक सेवाहरूमा आवाज कल गर्नुहोस्। <xliff:g id="NUMBER">%1$s</xliff:g> मा तपाईंको पाठ सन्देश यो समयमा डेलिभर हुन सक्दैन।"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> नयाँ सन्देशहरू</item>
+      <item quantity="one"> नयाँ सन्देश</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"सुरु गर्नुहोस्"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"क्यामेरा उपलब्ध छैन"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"क्यामेरा उपलब्ध छैन"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"भिडियो क्याप्चर उपलब्ध छैन"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"मिडिया बचत गर्न सकिँदैन"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"तस्वीर लिन सक्दैन"</string>
+    <string name="back" msgid="1477626055115561645">"पछाडि"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"अभिलेख बनाइयो"</string>
+    <string name="action_delete" msgid="4076795795307486019">"मेटाउनुहोस्"</string>
+    <string name="action_archive" msgid="5437034800324083170">"अभिलेख"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"अभिलेखबाट निकाल्नुहोस्"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"सूचनाहरू बन्द गर्नुहोस्"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"सूचनाहरू सुचारु गर्नुहोस्"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"सम्पर्क थप्नुहोस्"</string>
+    <string name="action_download" msgid="7786338136368564146">"डाउनलोड गर्नुहोस्"</string>
+    <string name="action_send" msgid="377635240181672039">"पठाउनुहोस्"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"मेटाउनुहोस्"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"यस सन्देश मेटाउने हो?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"यो कार्य पूर्ववत् पार्न सकिँदैन।"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"मेटाउनुहोस्"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other"> यी वार्तालापहरू मेटाउने हो?</item>
+      <item quantity="one"> यो वार्तालाप मेटाउने हो?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"मेटाउनुहोस्"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"रद्द गर्नुहोस्"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"प्रापक"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"बहु तस्बिर चयन गर्नुहोस्"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"चयन यकिन गर्नुहोस्"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"अडियो रेकर्ड गर्न सकिँदैन। पुन: प्रयास गर्नुहोस्।"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"अडियो बजाउन सकिएन। पुन: प्रयास गर्नुहोस्।"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"अडियो सुरक्षित गर्न सकेन। फेरी प्रयास गर्नुहोस्।"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"छुनुहोस् र होल्ड गर्नुहोस्"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"चित्र"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ध्वनि क्लिप"</string>
+    <string name="notification_video" msgid="4331423498662606204">"भिडियो"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"सम्पर्क कार्ड"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"डाउनलोड गर्नुहोस्"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS मार्फत जवाफ दिनुहोस्"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS मार्फत जवाफ दिनुहोस्"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"जवाफ पठाउनुहोस्"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> सहभागीहरू</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> सहभागी</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"म"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"सम्पर्क अवरुद्ध; अभिलेख राखियो"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"सम्पर्क खुल्ला गरियो &amp;amp अभिलेख हटाइयो"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g>अभिलेख गरियो"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> अभिलेख हटाउनुहोस्"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"सूचनाहरू निष्क्रिय पारिए"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"सूचनाहरू सक्रिय पारिए"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"सबै ठीक छ। पुन: पठाउन छुनुहोस्।"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"सन्देश प्रवाह सफलतापूर्वक पूर्वनिर्धारित SMS अनुप्रयोगको रूपमा सेट भयो।"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other"> संलग्नकहरू खारेज गर्नुहोस्</item>
+      <item quantity="one"> संलग्नक खारेज गर्नुहोस्</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"अडियो संलग्नक"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"अडियो संलग्नक प्ले गर्नुहोस्"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"पज गर्नुहोस्"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> बाट प्राप्त सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>।"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> बाट विफल सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> बाट सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> मा नपठाइएको सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> मा सन्देश पठाउँदै: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> मा विफल सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> मा सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> बाट विफल सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> बाट सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> मा नपठाइएको सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> मा सन्देश पठाउँदै: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> मा विफल सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> मा सन्देश: <xliff:g id="MESSAGE">%2$s</xliff:g>. समय: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"असफल सन्देश। पुन: प्रयास गर्न छुनुहोस्।"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> सँग कुराकानी"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"विषय मेट्नुहोस्"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"भिडियो खिच्नुहोस्"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"स्थिर छाँया लिदै"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"फोटो लिनुहोस्"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"भिडियो रेकर्ड सुरु गर्नुहोस्"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"पूरा पर्दा क्यामेरा  खोल्नुहोस्"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"अगाडि र पछाडि क्यामेरा बीच बदल्नुहोस्"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"भिडियो रेकर्ड गर्न र संलग्न रोक्नुहोस्"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"भिडियो रेकर्ड रोक्नुहोस्"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"सन्देश प्रवाह तस्बिरहरू"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> तस्बिरहरू \"<xliff:g id="ALBUMNAME_3">%s</xliff:g> \" एल्बममा सुरक्षित गरियो</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> तस्बिर \"<xliff:g id="ALBUMNAME_1">%s</xliff:g> \" एल्बममा सुरक्षित गरियो</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> भिडियोहरू \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" एल्बममा सुरक्षित गरियो</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> भिडियो \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" एल्बममा सुरक्षित गरियो</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> संलग्नकहरू \" <xliff:g id="ALBUMNAME_3">%s</xliff:g> \" एल्बममा सुरक्षित गरियो</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> संलग्नक \" <xliff:g id="ALBUMNAME_1">%s</xliff:g> \" एल्बममा सुरक्षित गरियो</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नकहरू \"डाउनलोडहरू\" मा सुरक्षित गरियो</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> संलग्नक \"डाउनलोडहरू\" मा सुरक्षित गरियो</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नकहरू सुरक्षित गरियो</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> संलग्नक सुरक्षित गरियो</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"> <xliff:g id="QUANTITY_1">%d</xliff:g> संलग्नकहरू सुरक्षित गर्न सकेन</item>
+      <item quantity="one"> <xliff:g id="QUANTITY_0">%d</xliff:g> संलग्नक सुरक्षित गर्न सकेन</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"संलग्न MMS सुरक्षित गरियो"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"सेटिङहरू"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"अभिलेख बनाइयो"</string>
+    <string name="action_close" msgid="1840519376200478419">"बन्द गर्नुहोस्"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"उन्नत"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"डिबग"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"सूचनाहरू"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"आवाज"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"मौन"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"कम्पन गर्नुहोस्"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"अवरूद्ध गरियो"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS वितरण प्रतिवेदनहरू"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"तपाईँले पठाउनु हुने हरेक SMS को लागि पुगेको खबर अनुरोध गर्नुहोस्"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"स्वत:प्राप्ति"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS सन्देशहरु स्वत: रूपमा पुनः प्राप्त गर्नुहोस्"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"रोमिङ स्वतः पुनः प्राप्ति"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"रोमिङमा हुँदा MMS स्वचालित रूपमा प्राप्त गर्नुहोस्"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"समूहिक सन्देश पठाइँदै"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"जब त्यहाँ बहुप्राप्तकर्ताहरू हुन्छन् तब सन्देश पठाउनको लागि MMS प्रयोग गर्नुहोस्।"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"पूर्वनिर्धारित SMS अनुप्रयोग"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"पूर्वनिर्धारित SMS अनुप्रयोग"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"तपाईँको फोन नम्बर"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"अज्ञात"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"बाहिर जाने सन्देशका लागि ध्वनिहरू"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS फाल्नुहोस्"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"प्राप्त भएको MMS अप्रशोधित डेटा बाह्य भण्डारण फाइलमा फाल्नुहोस्"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS फाल्दिनुहोस्"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"प्राप्त भएको MMS अप्रशोधित डेटा बाह्य भण्डारण फाइलमा फाल्नुहोस्"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ताररहित सतर्कताहरू"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"सन्देश विकल्पहरू"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"पाठ प्रतिलिपि गर्नुहोस्"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"विवरणहरू हेर्नुहोस्"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"मेटाउनुहोस्"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"फर्वार्ड गर्नुहोस्"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"सन्देश विवरणहरू"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"प्रकार: "</string>
+    <string name="text_message" msgid="7415419755252205721">"पाठ सन्देश"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"मल्टिमिडिया सन्देश"</string>
+    <string name="from_label" msgid="1947831848146564875">"प्रेषक: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"प्रापक: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"पठाइयो: "</string>
+    <string name="received_label" msgid="4442494712757995203">"प्राप्त: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"विषय: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"आकार: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"प्राथमिकता: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"उच्च"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"सामान्य"</string>
+    <string name="priority_low" msgid="7398724779026801851">"कम"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"प्रेषकको ठेगाना लुकेको"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"संलग्नहरू लोड गर्दा सन्देश पठाउन सक्दैन।"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"संलग्नक लोड गर्न सकिएन। पुन: प्रयास गर्नुहोस्।"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"नेटवर्क तयार छैन। पुन: प्रयास गर्नुहोस्।"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"पाठ मेट्नुहोस्"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"पाठ र संख्या बीच प्रविष्टि गर्न स्विच गर्नुहोस्"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"थप सहभागी थप्नुहोस्"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"सहभागीहरूको पुष्टि गर्नुहोस्"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"नयाँ कुराकानी सुरू गर्नुहोस्"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"यो वस्तु चयन गर्नुहोस्"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"भिडियो चलाउनुहोस्"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"मानिस र विकल्पहरू"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"डिबग"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"मानिसहरू र विकल्पहरु"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"सामान्य"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"यस कुराकानीमा मानिसहरू"</string>
+    <string name="action_call" msgid="6596167921517350362">"कल गर्नुहोस्"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"सन्देश पठाउनुहोस्"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"सन्देश पठाउनुहोस्&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&amp;gt बाट"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other"> तस्बिरहरू पठाउनुहोस्</item>
+      <item quantity="one"> तस्बिर पठाउनुहोस्</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other"> अडियोहरू पठाउनुहोस्</item>
+      <item quantity="one"> अडियो पठाउनुहोस्</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other"> भिडियोहरू पठाउनुहोस्</item>
+      <item quantity="one"> भिडियो पठाउनुहोस्</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other"> सम्पर्क कार्डहरू पठाउनुहोस्</item>
+      <item quantity="one"> सम्पर्क कार्ड पठाउनुहोस्</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other"> संलग्नक पठाउनुहोस्</item>
+      <item quantity="one"> संलग्नक पठाउनुहोस्</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> संलग्नकहरू पठाउनको लागि तयार</item>
+      <item quantity="one">एउटा संलग्नक पठाउनको लागि तयार</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"प्रतिक्रिया पठाउनुहोस्"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store मा हेर्नुहोस्"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"संस्करण जानकारी"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for subtitle_format_for_version_number (446082111129170749) -->
+    <skip />
+    <string name="menu_license" msgid="1157954180701135202">"खुला स्रोत इजाजतपत्रहरू"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"अधिसूचनाहरू"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"संलग्नकको सीमा पुग्यो"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"संलग्नक लोड गर्न असफल।"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"सम्पर्कहरूमा थप्नुहुन्छ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"सम्पर्क थप्नुहोस्"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"विषय"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"विषय: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"सम्पर्क कार्ड लोड गर्दै"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"सम्पर्क कार्ड लोड गर्न सकिएन"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"सम्पर्क कार्ड हेर्नुहोस्"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> सम्पर्कहरू</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> सम्पर्क</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"सम्पर्क कार्डहरू"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"जन्मदिन"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"टिप्पणीहरू"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"सन्देश फर्वार्ड गर्नुहोस्"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"जवाफ पठाउनुहोस्"</string>
+    <string name="plus_one" msgid="9010288417554932581">"‌+१"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS असक्षम गरियो"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"पठाउनका लागि सन्देश प्रवाहलाई पूर्वनिर्धारित SMS अनुप्रयोगको रूपमा सेट गर्नुहोस्"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"सन्देश प्रवाहलाई पूर्वनिर्धारित SMS अनुप्रयोगको रूपमा सेट गर्नुहोस्"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"परिवर्तन गर्नुहोस्"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"सन्देशहरू प्राप्त गर्न, सन्देश प्रवाहलाई पूर्वनिर्धारित SMS अनुप्रयोगको रूपमा सेट गर्नुहोस्"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS सन्देशहरू पठाउनको लागि मान्यता प्राप्त SIM चयन गरिएको छैन।"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"यो अनुप्रयोग उपकरण मालिकद्वारा अनुमति छैन।"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ठीक छ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"कुराकानीमा धेरै सहभागीहरू"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">अमान्य सम्पर्कहरू</item>
+      <item quantity="one"> अमान्य सम्पर्क</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"क्यामेराको तस्बिर लोड गर्न सकिएन"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"तपाईँ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"मस्यौदा"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"तपाईँ नयाँ कुराकानी सुरु भएपछि, तपाईँ यसलाई यहाँ सूचीबद्ध देख्नुहुने छ"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"अभिलेख कुराकानी यहाँ देखा पर्नेछ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"कुराकानीहरू लोड हुँदै..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"तस्बिर"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"अडियो क्लिप"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"भिडियो"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"सम्पर्क कार्ड"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"अनडु गर्नुहोस्"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"पुनःप्रयास गर्नुहोस्"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"सम्पर्क नाम वा फोन नम्बर प्रविष्ट गरी नयाँ सन्देश सुरु गर्नुहोस्"</string>
+    <string name="action_block" msgid="9032076625645190136">"रोक्नुहोस्"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"अवरुद्ध <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"अनब्लक <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"अवरुद्ध गर्नुस् <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"तपाईँ यो नम्बरबाट सन्देश प्राप्त गरिरहनु हुनेछ तर तपाईँलाई सूचीत गरिने छैन। यो कुराकानीलाई संग्रह गरिने छ।"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"अवरुद्ध सम्पर्कहरू"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"UNBLOCK"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"अवरुद्ध सम्पर्कहरू"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"कागजात लाइब्रेरीबाट तस्बिर छान्नुहोस्"</string>
+    <string name="sending_message" msgid="6363584950085384929">"सन्देश पठाउँदै"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"सन्देश पठाइयो"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"सेलुलर डेटा बन्द छ। आफ्नो सेटिङ जाँच गर्नुहोस्।"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"हवाइजहाज मोडमा सन्देश पठाउन सक्नुहुन्‍न्"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"सन्देश पठाउन सकिएन"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"सन्देश डाउनलोड गरियो"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"सेलुलर डाटा बन्द गरिएको छ। आफ्नो सेटिङहरू जाँच्नुहोस्।"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"हवाइजहाज मोडमा सन्देशहरू डाउनलोड गर्न सक्दैन"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"सन्देश डाउनलोड गर्न सकिएन"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"शून्य"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"एक"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"दुई"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"तीन"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"चार"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"पाँच"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"छ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"सात"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"आठ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"नौ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> मार्फत सन्देश पठाउन सक्दैन, त्रुटि <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"अज्ञात वाहकमार्फत सन्देश पठाउन सक्दैन, त्रुटि <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"फर्वाड गर्नुहोस्: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"सन्देश पठाइएको छैन: सञ्जालमा सेवा सक्रिय छैन"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"सन्देश पठाइएको छैन: अवैध गन्तव्य ठेगाना"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"सन्देश पठाइएको छैन: अमान्य सन्देश"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"सन्देश पठाइएको छैन: असमर्थित सामाग्री"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"सन्देश पठाइएको छैन: असमर्थित सन्देश"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"सन्देश पठाइएन: निकै ठूलो छ"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"नयाँ सन्देश"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"हेर्नुहोस्"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"तस्बिर"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"उपयुक्त अनुप्रयोग फेला पार्न सकिएन"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"प्राप्तकर्ता हटाउनुहोस्"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"नयाँ सन्देश"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"रद्द गर्नुहोस्"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"पहुँच बिन्दु सम्पादन गर्नुहोस्"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"सेट गरेको छैन"</string>
+    <string name="apn_name" msgid="1572691851070894985">"नाम"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS प्रोक्सी"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS पोर्ट"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN प्रकार"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN मेटाउनुहोस्"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"नयाँ APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"सुरक्षित गर्नुहोस्"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"त्याग्नुहोस्"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"नाम क्षेत्र खाली हुन सक्दैन।"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN खाली हुन सक्दैन।"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC क्षेत्र कम्तिमा ३ अङ्कको हुनु पर्छ।"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC क्षेत्रमा २ वा ३ अंकहरू हुनु पर्दछ।"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"पूर्वनिर्धारित APN सेटिङ्हरू पुनःप्राप्त गर्दै।"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"पूर्वनिर्धारितमा पुनःसेट गर्नुहोस्"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"पूर्वनिर्धारित APN सेटिङ्हरू पुनः सेट गर्ने काम पूरा भयो।"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"शीर्षक विहिन"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"पहुँच बिन्दु नामहरू"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"नयाँ APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"पहुँच बिन्दु नामको सेटिङ्हरू यो प्रयोगकर्ताको लागि उपलब्ध छैन"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"क्लिपबोर्डमा प्रतिलिपि गर्ने?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"प्रतिलिपि गर्नुहोस्"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> लाई"</string>
+    <string name="general_settings" msgid="5409336577057897710">"सामान्य"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"उन्नत"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"साधारण सेटिङ्हरू"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"उन्नत सेटिङ्हरू"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"सबै प्रापकलाई व्यक्तिगत SMS सन्देशहरू पठाउनुहोस्। केवल तपाईँले कुनै पनि उत्तर प्राप्त गर्नुहुने छ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"सबै प्रापकलाई एउटा एकल MMS पठाउनुहोस्"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"अज्ञात संख्या"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"नयाँ सन्देश"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"नयाँ सन्देश।"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"सिम चयनकर्ता"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> चयन गरियो, SIM चयनकर्ता"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"विषय सम्पादन गर्नुहोस्"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"सिम चयन गर्नुहोस् वा विषय सम्पादन गर्नुहोस्"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"अडियो रेकर्ड गर्न छुनुहोस् र होल्ड गर्नुहोस्"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"नयाँ कुराकानी सुरू गर्नुहोस्"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"सन्देश प्रवाह"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"सन्देश प्रवाह सूची"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"सन्देश प्रवाह"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"नयाँ सन्देश"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"कुराकानी सूची"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"कुराकानीहरू लोड हुँदै..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"सन्देशहरू लोड हुँदै"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"थप कुराकानीहरू हेर्नुहोस्"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"थप सन्देशहरू हेर्नुहोस्"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"कुराकानी मेटिएको छ"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"वार्तालाप मेटियो। एउटा फरक सन्देश प्रवाह वार्तालाप देखाउन छुनुहोस्"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"अवरूद्ध गरियो"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"अवरोध हटाइयो"</string>
+    <string name="db_full" msgid="8459265782521418031">"भण्डारण ठाउँ कम छ। केही डाटा हराउन सक्छ।"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"संलग्नकहरू चयन गर्नुहोस्"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"चयन पुष्टि गर्नुहोस्"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> चयन गरियो"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"कृपया एक वा बढी संलग्नकहरू हटाउनुहोस् र फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"तपाईं आफ्नो सन्देश पठाउन प्रयास गर्न सक्नुहुन्छ, तर तपाईंले एक वा बढी संलग्नकहरू नहटाएसम्म यो डेलिभर नहुन सक्छ।"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"तपाईँले  प्रति सन्देश एउटा मात्र भिडियो पठाउन सक्नुहुन्छ। अतिरिक्त भिडियो हटाउनुहोस् र फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"संलग्नक लोड गर्न सन्देश प्रवाह असफल भयो।"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"जसरी  भए पनि पठाउनुहोस्"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"कुराकानी सुरु गर्न सकेन"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> चयन गरियो"</string>
+</resources>
diff --git a/res/values-nl/arrays.xml b/res/values-nl/arrays.xml
new file mode 100644
index 0000000..adfdcbe
--- /dev/null
+++ b/res/values-nl/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"geen onderwerp"</item>
+    <item msgid="272485471009191934">"geenonderwerp"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nee"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Haha"</item>
+    <item msgid="2611328818571146775">"Hartelijk dank"</item>
+    <item msgid="4881335087096496747">"Ik ga akkoord"</item>
+    <item msgid="2422296858597420738">"Mooi"</item>
+    <item msgid="4805581752819452687">"Ik ben onderweg"</item>
+    <item msgid="4746700499431366214">"Hier kom ik later op terug"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
new file mode 100644
index 0000000..8312dcc
--- /dev/null
+++ b/res/values-nl/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Berichten"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Berichten"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Gesprek selecteren"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Instellingen"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Bericht verzenden"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Een bijlage toevoegen"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Help"</string>
+    <string name="welcome" msgid="2857560951820802321">"Welkom"</string>
+    <string name="skip" msgid="7238879696319945853">"Overslaan"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Volgende &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Volgende"</string>
+    <string name="exit" msgid="1905187380359981199">"Sluiten"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Instellingen &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Instellingen"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Berichten heeft toegang tot Sms, Telefoon en Contacten nodig."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"U kunt rechten wijzigen via \'Instellingen\' &gt; \'Apps\' &gt; \'Berichten\' &gt; \'Rechten\'."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"U kunt rechten wijzigen via \'Instellingen\' &gt; \'Apps\' &gt; \'Berichten\' &gt; \'Rechten\'."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Veelgebruikt"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alle contacten"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Verzenden naar <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Foto\'s of video vastleggen"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Afbeeldingen kiezen op dit apparaat"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Audio opnemen"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Foto kiezen"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Het medium is geselecteerd."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Het medium is gedeselecteerd."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> geselecteerd"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"afbeelding <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"afbeelding"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Audio opnemen"</string>
+    <string name="action_share" msgid="2143483844803153871">"Delen"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Zojuist"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nu"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> uur</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> uur</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dagen</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> weken</item>
+      <item quantity="one">één week</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> maanden</item>
+      <item quantity="one">één maand</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> jaar</item>
+      <item quantity="one">één jaar</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Berichtklasse 0"</string>
+    <string name="save" msgid="5081141452059463572">"Opslaan"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Er is weinig ruimte vrij op het apparaat. Oudere berichten worden automatisch verwijderd om ruimte vrij te maken."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Opslagruimte is bijna vol"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Berichten verzendt of ontvangt mogelijk geen berichten totdat er meer ruimte beschikbaar is op uw apparaat."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Weinig opslagruimte voor sms-berichten beschikbaar. Je moet mogelijk berichten verwijderen."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Uw telefoonnummer bevestigen"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Deze eenmalige stap zorgt ervoor dat Berichten uw groepsberichten correct aflevert."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefoonnummer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Alle berichten met media verwijderen"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Berichten ouder dan <xliff:g id="DURATION">%s</xliff:g> verwijderen"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Berichten ouder dan <xliff:g id="DURATION">%s</xliff:g> automatisch verwijderen"</string>
+    <string name="ignore" msgid="7063392681130898793">"Negeren"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Alle berichten met media verwijderen?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Berichten ouder dan <xliff:g id="DURATION">%s</xliff:g> verwijderen?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Berichten ouder dan <xliff:g id="DURATION">%s</xliff:g> verwijderen en automatisch verwijderen inschakelen?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> zei"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"U zei"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Bericht van <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"U heeft een bericht verzonden"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Verzenden…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Niet verzonden. Tik om het opnieuw te proberen."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Niet verzonden. Nieuwe poging…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Opnieuw verzenden of verwijderen"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Bel de hulpdiensten. Uw sms kan momenteel niet worden afgeleverd."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Mislukt"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nieuw mms-bericht downloaden"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nieuw mms-bericht"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Kan niet downloaden"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tik voor nieuwe poging"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Tik om te downloaden"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Downloaden of verwijderen"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Downloaden..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Bericht verlopen of niet beschikbaar"</string>
+    <string name="mms_info" msgid="3402311750134118165">"grootte: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, verloopt: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Kan niet verzenden. Ontvanger niet geldig."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Service niet geactiveerd in netwerk"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Kan niet verzenden wegens een netwerkprobleem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Bericht verlopen of niet beschikbaar"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Geen onderwerp)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Onbekende afzender"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Bezorgd"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Kan bericht <xliff:g id="SUBJECT">%1$s</xliff:g> niet downloaden van <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Kan databasebewerking niet voltooien wegens onvoldoende geheugen"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Bericht niet verzonden"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Sommige berichten niet verzonden in Berichten"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> berichten in <xliff:g id="CONVERSATIONS">%d</xliff:g> gesprekken</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> berichten in één gesprek</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Bericht niet gedownload"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Sommige berichten zijn niet gedownload in Berichten"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> berichten in <xliff:g id="CONVERSATIONS">%d</xliff:g> gesprekken</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> berichten in één gesprek</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Bericht naar <xliff:g id="NUMBER">%1$s</xliff:g> niet verzonden"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Bel de hulpdiensten. Uw sms aan <xliff:g id="NUMBER">%1$s</xliff:g> kan momenteel niet worden afgeleverd."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nieuwe berichten</item>
+      <item quantity="one">Nieuw bericht</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Starten"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Camera niet beschikbaar"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Camera niet beschikbaar"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video-opname niet beschikbaar"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Kan media niet opslaan"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Kan geen foto maken"</string>
+    <string name="back" msgid="1477626055115561645">"Terug"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Gearchiveerd"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Verwijderen"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archiveren"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Terugzetten uit archief"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Meldingen uitschakelen"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Meldingen inschakelen"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Contact toevoegen"</string>
+    <string name="action_download" msgid="7786338136368564146">"Downloaden"</string>
+    <string name="action_send" msgid="377635240181672039">"Verzenden"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Verwijderen"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Dit bericht verwijderen?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Deze actie kan niet ongedaan worden gemaakt."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Verwijderen"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Deze gesprekken verwijderen?</item>
+      <item quantity="one">Dit gesprek verwijderen?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Verwijderen"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Annuleren"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Aan"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Meerdere afbeeldingen selecteren"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Selectie bevestigen"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Kan audio niet opnemen. Probeer het opnieuw."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Kan audio niet afspelen. Probeer het opnieuw."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Kan audio niet opslaan. Probeer het opnieuw."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Blijven aanraken"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Afbeelding"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audioclip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Visitekaartje"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Downloaden"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Reageren via sms"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Reageren via mms"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Beantwoorden"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> deelnemers</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> deelnemer</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ik"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contact geblokkeerd en gearchiveerd"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Blokkering van contact opgeheven en teruggezet uit archief"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> gearchiveerd"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> teruggezet uit archief"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Meldingen uitgeschakeld"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Meldingen ingeschakeld"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Alles is ingesteld. Tik nogmaals op \'Verzenden\'."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Berichten is ingesteld als de standaard sms-app"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Bijlagen verwijderen</item>
+      <item quantity="one">Bijlage verwijderen</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Audiobijlage"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Audiobijlage afspelen"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Onderbreken"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Bericht van <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mislukt bericht van <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Bericht van <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Niet-verzonden bericht aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Bericht verzenden naar <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mislukt bericht aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Bericht aan <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mislukt bericht van <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Bericht van <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Niet-verzonden bericht aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Bericht verzenden naar <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mislukt bericht aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Bericht aan <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tijd: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Bericht mislukt. Tik om het opnieuw te proberen."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Gesprek met <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Onderwerp verwijderen"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video opnemen"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Een stilstaand beeld opnemen"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Foto maken"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Video opnemen"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Overschakelen naar camera op volledig scherm"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Schakelen tussen camera aan voorzijde en camera aan achterzijde"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Opname stoppen en video bijvoegen"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Video-opname stoppen"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto\'s in Berichten"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foto\'s opgeslagen in het album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto opgeslagen in het album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video\'s opgeslagen in het album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video opgeslagen in het album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> bijlagen opgeslagen in het album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bijlage opgeslagen in het album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bijlagen opgeslagen in \"Downloads\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bijlage opgeslagen in \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bijlagen opgeslagen</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bijlage opgeslagen</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Kan <xliff:g id="QUANTITY_1">%d</xliff:g> bijlagen niet opslaan</item>
+      <item quantity="one">Kan <xliff:g id="QUANTITY_0">%d</xliff:g> bijlage niet opslaan</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Opgeslagen mms-bijlage"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Instellingen"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Gearchiveerd"</string>
+    <string name="action_close" msgid="1840519376200478419">"Sluiten"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Mms"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Geavanceerd"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Fouten opsporen"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Meldingen"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Geluid"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Stil"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Trillen"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Geblokkeerd"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Bezorgingsrapporten voor sms"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Ontvangstbevestiging vragen voor elke verzonden sms"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatisch ophalen"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Mms-berichten automatisch ophalen"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatisch ophalen tijdens roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatisch MMS ophalen tijdens roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Groepsberichten"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Mms gebruiken om één bericht te verzenden wanneer er meerdere ontvangers zijn"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Standaard sms-app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Standaard sms-app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Uw telefoonnummer"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Onbekend"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Geluiden voor uitgaand bericht"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Sms dumpen"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Onbewerkte gegevens voor ontvangen sms\'jes in een extern opslagbestand dumpen"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Mms dumpen"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Onbewerkte gegevens voor ontvangen mms\'jes in een extern opslagbestand dumpen"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Waarschuwingen voor draadloos"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Berichtopties"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Tekst kopiëren"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Details weergeven"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Verwijderen"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Doorsturen"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Berichtdetails"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Type: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Sms-bericht"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mms-bericht"</string>
+    <string name="from_label" msgid="1947831848146564875">"Van: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Aan: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Verzonden: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Ontvangen: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Onderwerp: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Grootte: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioriteit: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"Simkaart: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Hoog"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normaal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Laag"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"Simkaart <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Verborgen adres verzender"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Kan bericht niet verzenden terwijl bijlagen worden geladen."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Kan bijlage niet laden. Probeer het opnieuw."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Netwerk is niet gereed. Probeer het opnieuw."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Tekst verwijderen"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Schakelen tussen letters en cijfers invoeren"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Meer deelnemers toevoegen"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Deelnemers bevestigen"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Nieuw gesprek starten"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Dit item selecteren"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Video afspelen"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Mensen en opties"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Fouten opsporen"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Mensen en opties"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Algemeen"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Mensen in dit gesprek"</string>
+    <string name="action_call" msgid="6596167921517350362">"Bellen"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Bericht verzenden"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Bericht verzenden&lt;br/&gt;&lt;small&gt;via <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Foto\'s verzenden</item>
+      <item quantity="one">Foto verzenden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Audio-opnamen verzenden</item>
+      <item quantity="one">Audio-opname verzenden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Video\'s verzenden</item>
+      <item quantity="one">Video verzenden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Contactkaarten verzenden</item>
+      <item quantity="one">Contactkaart verzenden</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Bijlagen verzenden</item>
+      <item quantity="one">Bijlage verzenden</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> bijlagen klaar voor verzenden</item>
+      <item quantity="one">Eén bijlage klaar voor verzenden</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Feedback verzenden"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Bekijken in de Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versie-informatie"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versie %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Open-sourcelicenties"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Meldingen"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Bijlagelimiet bereikt"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Kan bijlage niet laden."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Toevoegen aan contacten?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Contact toevoegen"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Onderwerp"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Onderwerp: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Contactkaart laden"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kan visitekaartje niet laden"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Contactkaart weergeven"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contacten</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Visitekaartjes"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Verjaardag"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notities"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Bericht doorsturen"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Beantwoorden"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Sms uitgeschakeld"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Stel Berichten in als standaard sms-app om berichten te verzenden"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Berichten instellen als standaard sms-app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Wijzigen"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Stel Berichten in als standaard sms-app om berichten te ontvangen"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Geen voorkeurs-simkaart geselecteerd voor het verzenden van sms\'jes"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Deze app is niet toegestaan door de eigenaar van het apparaat."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Te veel deelnemers in een gesprek"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Ongeldige contacten</item>
+      <item quantity="one">Ongeldig contact</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kan camera-afbeelding niet laden"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"U: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Concept"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Zodra u een nieuw gesprek start, wordt dit hier vermeld"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Gearchiveerde gesprekken worden hier weergegeven"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Gesprekken laden..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Afbeelding"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audioclip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Visitekaartje"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Mms"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Ongedaan maken"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Opnieuw proberen"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Geef de naam of het telefoonnummer van een contact op om een nieuw bericht te starten"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokkeren"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> blokkeren"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Blokkering van <xliff:g id="DESTINATION">%s</xliff:g> opheffen"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> blokkeren?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"U blijft berichten van dit nummer ontvangen, maar krijgt geen meldingen meer. Dit gesprek wordt gearchiveerd."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Geblokkeerde contacten"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"BLOKKERING OPHEFFEN"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Geblokkeerde contacten"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Afbeelding kiezen uit documentbibliotheek"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Bericht wordt verzonden"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Bericht verzonden"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobiele gegevens zijn ingeschakeld. Controleer uw instellingen."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Kan geen berichten verzenden in vliegtuigmodus"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Kan bericht niet verzenden"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Bericht gedownload"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobiele gegevens zijn uitgeschakeld. Controleer uw instellingen."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Kan geen berichten downloaden in de vliegtuigmodus"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Bericht kan niet worden gedownload"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nul"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Eén"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Twee"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Drie"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Vier"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Vijf"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Zes"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Zeven"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Acht"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Negen"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Kan bericht niet verzenden via <xliff:g id="CARRIERNAME">%1$s</xliff:g>, fout <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Kan bericht niet verzenden via onbekende provider, fout <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Bericht niet verzonden: service niet geactiveerd in netwerk"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Bericht niet verzonden: ongeldig bestemmingsadres"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Bericht niet verzonden: ongeldig bericht"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Bericht niet verzonden: niet-ondersteunde inhoud"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Bericht niet verzonden: niet-ondersteund bericht"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Bericht niet verzonden: te groot"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nieuw bericht"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Weergeven"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Afbeelding"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Kan geen geschikte applicatie vinden"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Ontvanger verwijderen"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nieuw bericht"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Annuleren"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Toegangspunt bewerken"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Niet ingesteld"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Naam"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-poort"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-type"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN verwijderen"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nieuwe APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Opslaan"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Verwijderen"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Het veld \'Naam\' mag niet leeg zijn."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"De APN mag niet leeg zijn."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-veld moet drie cijfers bevatten."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-veld moet twee of drie cijfers bevatten."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Standaard-APN-instellingen herstellen."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Standaardinstellingen herstellen"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Herstellen van standaard-APN-instellingen voltooid."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Naamloos"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Namen toegangspunten"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN\'s"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nieuwe APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Instellingen voor toegangspuntnamen zijn niet beschikbaar voor deze gebruiker"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopiëren naar klembord?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiëren"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"naar <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Algemeen"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Geavanceerd"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Algemene instellingen"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Geavanceerde instellingen"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Sim van \'<xliff:g id="SIM_NAME">%s</xliff:g>\'"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Afzonderlijke sms\'jes verzenden naar alle ontvangers. U bent de enige die eventuele reacties ontvangt"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Eén mms verzenden naar alle ontvangers"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Onbekend nummer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nieuw bericht"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nieuw bericht."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Simkaart selecteren"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> geselecteerd, simkaartkiezer"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Onderwerp bewerken"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Simkaart selecteren of onderwerp bewerken"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Blijf aanraken om audio op te nemen"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Nieuw gesprek starten"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Berichten"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lijst in Berichten"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Berichten"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nieuw bericht"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Gesprekslijst"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Gesprekken laden"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Berichten laden"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Meer gesprekken bekijken"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Meer berichten bekijken"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Gesprek verwijderd"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Gesprek verwijderd. Tik om een ander Berichten-gesprek weer te geven"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Geblokkeerd"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blokkering opgeheven"</string>
+    <string name="db_full" msgid="8459265782521418031">"Er is weinig opslagruimte beschikbaar. Er kunnen gegevens verloren gaan."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Bijlagen selecteren"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Selectie bevestigen"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> geselecteerd"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Verwijder een of meer bijlagen en probeer het opnieuw."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"U kunt proberen uw bericht te verzenden, maar het bericht wordt mogelijk niet bezorgd, tenzij u een of meer bijlagen verwijdert."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"U kunt slechts één video verzenden per bericht. Verwijder extra video\'s en probeer het opnieuw."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Berichten kan de bijlage niet laden."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Toch verzenden"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Kan gesprek niet starten"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> geselecteerd"</string>
+</resources>
diff --git a/res/values-pa/arrays.xml b/res/values-pa/arrays.xml
new file mode 100644
index 0000000..1cf23e9
--- /dev/null
+++ b/res/values-pa/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ਕੋਈ ਵਿਸ਼ਾ ਨਹੀਂ"</item>
+    <item msgid="272485471009191934">"ਕੋਈ ਵਿਸ਼ਾ ਨਹੀਂ"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ਹਾਂ"</item>
+    <item msgid="6049132459802288033">"ਨਹੀਂ"</item>
+    <item msgid="3084376867445867895">"ਠੀਕ"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"ਧੰਨਵਾਦ"</item>
+    <item msgid="4881335087096496747">"ਮੈਂ ਸਹਿਮਤ ਹਾਂ"</item>
+    <item msgid="2422296858597420738">"ਵਧੀਆ"</item>
+    <item msgid="4805581752819452687">"ਰਸਤੇ ਵਿੱਚ ਹਾਂ"</item>
+    <item msgid="4746700499431366214">"ਠੀਕ, ਮੈਂ ਤੁਹਾਨੂੰ ਬਾਅਦ ਵਿੱਚ ਸੰਪਰਕ ਕਰਾਂਗਾ"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
new file mode 100644
index 0000000..3ccc046
--- /dev/null
+++ b/res/values-pa/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Messaging"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Messaging"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"ਗੱਲਬਾਤ ਚੁਣੋ"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"ਸੁਨੇਹਾ ਭੇਜੋ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ਇੱਕ ਅਟੈਚਮੈਂਟ ਜੋੜੋ"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"ਸਹਾਇਤਾ"</string>
+    <string name="welcome" msgid="2857560951820802321">"ਸੁਆਗਤ ਹੈ"</string>
+    <string name="skip" msgid="7238879696319945853">"ਛੱਡੋ"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ਅਗਲਾ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"ਅਗਲਾ"</string>
+    <string name="exit" msgid="1905187380359981199">"ਬਾਹਰ ਜਾਓ"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ਸੈਟਿੰਗਾਂ &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Messaging ਨੂੰ SMS, ਫੋਨ ਅਤੇ ਸੰਪਰਕਾਂ ਲਈ ਅਨੁਮਤੀ ਦੀ ਲੋੜ ਹੈ।"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ &gt; ਐਪਸ &gt; Messaging &gt; ਅਨੁਮਤੀਆਂ ਵਿੱਚ ਅਨੁਮਤੀਆਂ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ, ਐਪਸ, Messaging, ਅਨੁਮਤੀਆਂ ਵਿੱਚ ਅਨੁਮਤੀਆਂ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ਫ੍ਰੀਕਵੈਂਟਸ"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"ਸਾਰੇ ਸੰਪਰਕ"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> ਨੂੰ ਭੇਜੋ"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"ਤਸਵੀਰਾਂ ਜਾ ਵੀਡੀਓ ਕੈਪਚਰ ਕਰੋ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ਇਸ ਡਿਵਾਈਸ ਤੋਂ ਚਿੱਤਰ ਚੁਣੋ"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ਫੋਟੋ ਚੁਣੋ"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"ਮੀਡੀਆ ਚੁਣਿਆ ਗਿਆ ਹੈ।"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ਮੀਡੀਆ ਅਚੋਣਵਾਂ ਕੀਤਾ ਗਿਆ ਹੈ।"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ਚੁਣਿਆ ਗਿਆ"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ਚਿੱਤਰ <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ਚਿੱਤਰ"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string>
+    <string name="action_share" msgid="2143483844803153871">"ਸ਼ੇਅਰ ਕਰੋ"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ਬਿਲਕੁਲ ਹੁਣੇ"</string>
+    <string name="posted_now" msgid="867560789350406701">"ਹੁਣ"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ਮਿੰਟ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਮਿੰਟ</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ਘੰਟੇ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਘੰਟੇ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ਦਿਨ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਦਿਨ</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ਹਫ਼ਤੇ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ਹਫ਼ਤੇ</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ਮਹੀਨੇ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ਮਹੀਨੇ</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ਸਾਲ</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ਸਾਲ</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ਕਲਾਸ 0 ਸੁਨੇਹਾ"</string>
+    <string name="save" msgid="5081141452059463572">"ਸੁਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"ਡਿਵਾਈਸ ਵਿੱਚ ਘੱਟ ਸਪੇਸ ਹੈ। Messaging ਆਟੋਮੈਟਿਕਲੀ ਸਪੇਸ ਖਾਲੀ ਕਰਨ ਲਈ ਪੁਰਾਣੇ ਸੁਨੇਹੇ ਮਿਟਾ ਦੇਵੇਗਾ।"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"ਸਟੋਰੇਜ ਸਪੇਸ ਖ਼ਤਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Messaging ਸੁਨੇਹੇ ਭੇਜ ਜਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਕਰ ਸਕਦਾ ਜਦੋਂ ਤੱਕ ਕਿ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਹੋਰ ਸਪੇਸ ਉਪਲਬਧ ਨਾ ਹੋਵੇ।"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"ਘੱਟ SMS ਸਟੋਰੇਜ। ਤੁਹਾਨੂੰ ਸੁਨੇਹੇ ਮਿਟਾਉਣ ਦੀ ਲੋੜ ਪੈ ਸਕਦੀ ਹੈ।"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ਆਪਣੇ ਫੋਨ ਨੰਬਰ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ਇਹ ਵਨ-ਟਾਈਮ ਸਟੈਪ ਯਕੀਨੀ ਬਣਾਏਗਾ ਕਿ Messaging ਤੁਹਾਡੇ ਸਮੂਹ ਦੇ ਸੁਨੇਹੇ ਸਹੀ ਢੰਗ ਨਾਲ ਡਿਲੀਵਰ ਕਰੇਗਾ।"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ਫੋਨ ਨੰਬਰ"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ਮੀਡੀਆ ਵਾਲੇ ਸਾਰੇ ਸੁਨੇਹੇ ਮਿਟਾਓ"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> ਤੋਂ ਪੁਰਾਣੇ ਸੁਨੇਹੇ ਮਿਟਾਓ"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> ਤੋਂ ਪੁਰਾਣੇ ਸੁਨੇਹੇ ਆਟੋ-ਮਿਟਾਓ"</string>
+    <string name="ignore" msgid="7063392681130898793">"ਅਣਡਿੱਠ ਕਰੋ"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"ਕੀ ਮੀਡੀਆ ਵਾਲੇ ਸਾਰੇ ਸੁਨੇਹੇ ਮਿਟਾਉਣੇ ਹਨ?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"ਕੀ <xliff:g id="DURATION">%s</xliff:g> ਤੋਂ ਪੁਰਾਣੇ ਸੁਨੇਹੇ ਮਿਟਾਉਣੇ ਹਨ?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"ਕੀ <xliff:g id="DURATION">%s</xliff:g> ਤੋਂ ਪੁਰਾਣੇ ਸੁਨੇਹੇ ਮਿਟਾਉਣੇ ਹਨ ਅਤੇ ਆਟੋ-ਮਿਟਾਓ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> ਨੇ ਕਿਹਾ"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"ਤੁਸੀਂ ਕਿਹਾ"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> ਦਾ ਸੁਨੇਹਾ"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"ਤੁਸੀਂ ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਿਆ"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"ਭੇਜ ਰਿਹਾ ਹੈ..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ਨਹੀਂ ਭੇਜਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ਨਹੀਂ ਭੇਜਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ਦੁਬਾਰਾ ਭੇਜੋ ਜਾਂ ਮਿਟਾਓ"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"ਕਿਰਪਾ ਕਰਕੇ ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਨੂੰ ਇੱਕ ਵੌਇਸ ਕਾਲ ਕਰੋ। ਤੁਹਾਡਾ ਟੈਕਸਟ ਸੁਨੇਹਾ ਇਸ ਵੇਲੇ ਡਿਲੀਵਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕੇਗਾ।"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ਅਸਫਲ"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਨਵਾਂ MMS ਸੁਨੇਹਾ"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"ਨਵਾਂ MMS ਸੁਨੇਹਾ"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ਡਾਊਨਲੋਡ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਛੋਹਵੋ"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਛੋਹਵੋ"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ਡਾਊਨਲੋਡ ਕਰੋ ਜਾਂ ਮਿਟਾਓ"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"ਸੁਨੇਹੇ ਦੀ ਮਿਆਦ ਪੁੱਗੀ ਜਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ਆਕਾਰ: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, ਮਿਆਦ ਪੁੱਗਣ ਦਾ ਸਮਾਂ: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"ਭੇਜ ਨਹੀਂ ਸਕਦਾ। ਪ੍ਰਾਪਤਕਰਤਾ ਪ੍ਰਮਾਣਿਕ ਨਹੀਂ ਹੈ।"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ਨੈਟਵਰਕ ਤੇ ਸੇਵਾ ਸਕਿਰਿਆ ਨਹੀਂ ਕੀਤੀ"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ਨੈਟਵਰਕ ਸਮੱਸਿਆ ਦੇ ਕਾਰਨ ਨਹੀਂ ਭੇਜ ਸਕਿਆ"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"ਸੁਨੇਹੇ ਦੀ ਮਿਆਦ ਪੁੱਗੀ ਜਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ਕੋਈ ਵਿਸ਼ਾ ਨਹੀਂ)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ਅਗਿਆਤ ਭੇਜਣ ਵਾਲਾ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ਡਿਲੀਵਰ ਕੀਤਾ"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> ਦਾ <xliff:g id="SUBJECT">%1$s</xliff:g> ਸੁਨੇਹਾ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
+    <string name="low_memory" msgid="5300743415198486619">"ਘੱਟ ਮੈਮਰੀ ਦੇ ਕਾਰਨ ਡਾਟਾਬੇਸ ਓਪਰੇਸ਼ਨ ਪੂਰਾ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"ਕੁਝ ਸੁਨੇਹੇ Messaging ਵਿੱਚ ਨਹੀਂ ਭੇਜੇ ਗਏ ਹਨ"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"> <xliff:g id="CONVERSATIONS">%d</xliff:g> ਗੱਲਬਾਤਾਂ ਵਿੱਚ <xliff:g id="MESSAGES_1">%d</xliff:g> ਸੁਨੇਹੇ</item>
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> ਗੱਲਬਾਤਾਂ ਵਿੱਚ <xliff:g id="MESSAGES_1">%d</xliff:g> ਸੁਨੇਹੇ</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"ਸੁਨੇਹਾ ਡਾਉਨਲੋਡ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"ਕੁਝ ਸੁਨੇਹੇ Messaging ਵਿੱਚ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੇ ਗਏ ਹਨ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"> <xliff:g id="CONVERSATIONS">%d</xliff:g> ਗੱਲਬਾਤਾਂ ਵਿੱਚ <xliff:g id="MESSAGES_1">%d</xliff:g> ਸੁਨੇਹੇ</item>
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> ਗੱਲਬਾਤਾਂ ਵਿੱਚ <xliff:g id="MESSAGES_1">%d</xliff:g> ਸੁਨੇਹੇ</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"ਕਿਰਪਾ ਕਰਕੇ ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਨੂੰ ਇੱਕ ਵੌਇਸ ਕਾਲ ਕਰੋ। ਤੁਹਾਡਾ ਟੈਕਸਟ ਸੁਨੇਹਾ ਇਸ ਵੇਲੇ <xliff:g id="NUMBER">%1$s</xliff:g> ਨੂੰ ਡਿਲੀਵਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕੇਗਾ।"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> ਨਵੇਂ ਸੁੁਨੇਹੇ</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ਨਵੇਂ ਸੁੁਨੇਹੇ</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ਚਾਲੂ ਕਰੋ"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"ਕੈਮਰਾ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"ਕੈਮਰਾ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ਵੀਡੀਓ ਕੈਪਚਰ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"ਮੀਡੀਆ ਨੂੰ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ਤਸਵੀਰ ਨਹੀਂ ਲੈ ਸਕਦਾ"</string>
+    <string name="back" msgid="1477626055115561645">"ਪਿੱਛੇ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ਆਰਕਾਈਵ ਕੀਤਾ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ਮਿਟਾਓ"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ਆਰਕਾਈਵ ਕਰੋ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ਅਨਆਰਕਾਈਵ ਕਰੋ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"ਸੰਪਰਕ ਜੋੜੋ"</string>
+    <string name="action_download" msgid="7786338136368564146">"ਡਾਊਨਲੋਡ ਕਰੋ"</string>
+    <string name="action_send" msgid="377635240181672039">"ਭੇਜੋ"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ਮਿਟਾਓ"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ਕੀ ਇਹ ਸੁਨੇਹਾ ਮਿਟਾਉਣਾ ਹੈ?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ਇਹ ਕਿਰਿਆ ਨਸ਼ਟ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ਮਿਟਾਓ"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">ਕੀ ਇਹ ਗੱਲਬਾਤਾਂ ਮਿਟਾਉਣੀਆਂ ਹਨ?</item>
+      <item quantity="other">ਕੀ ਇਹ ਗੱਲਬਾਤਾਂ ਮਿਟਾਉਣੀਆਂ ਹਨ?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ਮਿਟਾਓ"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ਰੱਦ ਕਰੋ"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ਵੱਲ"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"ਮਲਟੀਪਲ ਚਿੱਤਰ ਚੁਣੋ"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ਚੋਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ਔਡੀਓ ਰਿਕਾਰਡ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ਔਡੀਓ ਪਲੇ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ਔਡੀਓ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ਛੋਹਵੋ &amp; ਹੋਲਡ ਕਰੋ"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ਤਸਵੀਰ"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ਔਡੀਓ ਕਲਿਪ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ਵੀਡੀਓ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"ਸੰਪਰਕ ਕਾਰਡ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ਡਾਊਨਲੋਡ ਕਰੋ"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ਰਾਹੀਂ ਜਵਾਬ"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS ਰਾਹੀਂ ਜਵਾਬ"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ਜਵਾਬ"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ਭਾਗੀਦਾਰ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਭਾਗੀਦਾਰ</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ਮੈਂ"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"ਬਲੌਕ ਕੀਤਾ &amp; ਆਰਕਾਈਵ ਕੀਤਾ ਸੰਪਰਕ"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"ਸੰਪਰਕ ਅਨਬਲੌਕ ਕੀਤਾ &amp; ਅਨਆਰਕਾਈਵ ਕੀਤਾ"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ਆਰਕਾਈਵ ਕੀਤੀਆਂ"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ਅਨਆਰਕਾਈਵ ਕੀਤੀਆਂ"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕੀਤੀਆਂ"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕੀਤੀਆਂ"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"ਸਾਰੇ ਸੈਟ ਕੀਤੇ। ਭੇਜੋ ਨੂੰ ਦੁਬਾਰਾ ਛੋਹਵੋ।"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Messaging ਡਿਫੌਲਟ SMS ਐਪਸ ਦੇ ਤੌਰ ਤੇ ਸਫਲਤਾਪੂਰਵਕ ਸੈਟ ਕੀਤਾ ਗਿਆ।"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">ਅਟੈਚਮੈਂਟਾਂ ਬਰਖਾਸਤ ਕਰੋ</item>
+      <item quantity="other">ਅਟੈਚਮੈਂਟਾਂ ਬਰਖਾਸਤ ਕਰੋ</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ਔਡੀਓ ਅਟੈਚਮੈਂਟ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ਔਡੀਓ ਅਟੈਚਮੈਂਟ ਪਲੇ ਕਰੋ"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"ਰੋਕੋ"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> ਦਾ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>।"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> ਦਾ ਸੁਨੇਹਾ ਅਸਫਲ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> ਦਾ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> ਨੂੰ ਨਾ ਭੇਜਿਆ ਗਿਆ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>। Time: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ ਭੇਜ ਰਿਹਾ ਹੈ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ ਭੇਜਣਾ ਅਸਫਲ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> ਦਾ ਸੁਨੇਹਾ ਅਸਫਲ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>। <xliff:g id="GROUPINFO">%4$s</xliff:g>।"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> ਦਾ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>. ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>। <xliff:g id="GROUPINFO">%4$s</xliff:g>।"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> ਨੂੰ ਨਾ ਭੇਜਿਆ ਗਿਆ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ ਭੇਜ ਰਿਹਾ ਹੈ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ ਭੇਜਣਾ ਅਸਫਲ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> ਨੂੰ ਸੁਨੇਹਾ: <xliff:g id="MESSAGE">%2$s</xliff:g>। ਸਮਾਂ: <xliff:g id="TIME">%3$s</xliff:g>।"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ਸੁਨੇਹਾ ਅਸਫਲ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> ਨਾਲ ਗੱਲਬਾਤ ਕਰੋ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"ਵਿਸ਼ਾ ਹਟਾਓ"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ਵੀਡੀਓ ਕੈਪਚਰ ਕਰੋ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ਇੱਕ ਸਟਿਲ ਚਿੱਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ਤਸਵੀਰ ਲਓ"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨਾ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਕੈਮਰਾ ਤੇ ਸਵਿਚ ਕਰੋ"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ਫ੍ਰੰਟ ਅਤੇ ਬੈਕ ਕੈਮਰਾ ਵਿਚਕਾਰ ਸਵਿਚ ਕਰੋ"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"ਰਿਕਾਰਡਿੰਗ ਰੋਕੋ ਅਤੇ ਵੀਡੀਓ ਅਟੈਚ ਕਰੋ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨਾ ਰੋਕੋ"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Messaging ਫੋਟੋਆਂ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ਫੋਟੋਆਂ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ਫੋਟੋਆਂ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ਵੀਡਿਓ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ਵੀਡਿਓ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਨੂੰ \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ਐਲਬਮ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਡਾਊਨਲੋਡਸ\" ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤੀਆਂ ਗਈਆਂ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਡਾਊਨਲੋਡਸ\" ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕੀਤੀਆਂ ਗਈਆਂ</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਸੁਰੱਖਿਅਤ ਕੀਤੀਆਂ</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਸੁਰੱਖਿਅਤ ਕੀਤੀਆਂ</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"> <xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਨੂੰ ਸੁੁਰੱਖਿਅਤ ਨਹੀਂ ਕਰ ਸਕਿਆ</item>
+      <item quantity="other"> <xliff:g id="QUANTITY_1">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਨੂੰ ਸੁੁਰੱਖਿਅਤ ਨਹੀਂ ਕਰ ਸਕਿਆ</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"ਸੁਰੱਖਿਅਤ ਕੀਤੀ MMS ਅਟੈਚਮੈਂਟ"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ਆਰਕਾਈਵ ਕੀਤਾ"</string>
+    <string name="action_close" msgid="1840519376200478419">"ਬੰਦ ਕਰੋ"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"ਉੱਨਤ"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ਡੀਬਗ ਕਰੋ"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"ਸੂਚਨਾਵਾਂ"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ਅਵਾਜ਼"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"ਸਾਈਲੈਂਟ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"ਵਾਈਬ੍ਰੇਟ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ਬਲੌਕ ਕੀਤਾ"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS ਡਿਲੀਵਰੀ ਰਿਪੋਰਟਾਂ"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ਤੁਸੀਂ ਜੋ ਵੀ SMS ਭੇਜੋ ਉਸ ਹਰੇਕ ਲਈ ਇੱਕ ਡਿਲੀਵਰੀ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"ਆਟੋ-ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"ਆਟੋਮੈਟਿਕਲੀ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ਰੋਮਿੰਗ ਆਟੋ-ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ਰੋਮਿੰਗ ਵੇਲੇ MMS ਆਟੋਮੈਟਿਕਲੀ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"ਸਮੂਹ ਮੈਸੇਂਜ਼ਿੰਗ"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ਜਦੋਂ ਮਲਟੀਪਲ ਪ੍ਰਾਪਤਕਰਤਾ ਹੋਣ ਤਾਂ ਇੱਕ ਸਿੰਗਲ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ MMS ਵਰਤੋ"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"ਡਿਫੌਲਟ SMS ਐਪ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"ਡਿਫੌਲਟ SMS ਐਪ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"ਤੁਹਾਡਾ ਫੋਨ ਨੰਬਰ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"ਅਗਿਆਤ"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"ਆਊਟਗੋਇੰਗ ਸੁਨੇਹਾ ਅਵਾਜ਼ਾਂ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS ਡੰਪ ਕਰੋ"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਫਾਈਲ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕੀਤਾ SMS ਅਧੂਰਾ ਡਾਟਾ ਡੰਪ ਕਰੋ"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS ਡੰਪ ਕਰੋ"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਫਾਈਲ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕੀਤਾ MMS ਅਧੂਰਾ ਡਾਟਾ ਡੰਪ ਕਰੋ"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"ਵਾਇਰਲੈਸ ਚਿਤਾਵਨੀਆਂ"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"ਸੁਨੇਹਾ ਚੋਣਾਂ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"ਟੈਕਸਟ ਕਾਪੀ ਕਰੋ"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"ਵੇਰਵੇ ਦੇਖੋ"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ਮਿਟਾਓ"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"ਸੁਨੇਹਾ ਵੇਰਵੇ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ਟਾਈਪ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ਟੈਕਸਟ ਸੁਨੇਹਾ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ਮਲਟੀਮੀਡੀਆ ਸੁਨੇਹਾ"</string>
+    <string name="from_label" msgid="1947831848146564875">"ਇਸ ਤੋਂ: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ਵੱਲ: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ਭੇਜਿਆ: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ਪ੍ਰਾਪਤ ਕੀਤਾ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"ਵਿਸ਼ਾ: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ਆਕਾਰ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ਤਰਜੀਹ: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"ਉੱਚ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ਸਧਾਰਨ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"ਘੱਟ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"ਭੇਜਣ ਵਾਲੇ ਦਾ ਪਤਾ ਲੁਕਾਇਆ ਗਿਆ"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"ਅਟੈਚਮੈਂਟਾਂ ਲੋਡ ਕਰਨ ਵੇਲੇ ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜ ਸਕਦਾ।"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ਅਟੈਚਮੈਂਟ ਲੋਡ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ਨੈੱਟਵਰਕ ਤਿਆਰ ਨਹੀਂ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ਟੈਕਸਟ ਮਿਟਾਓ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"ਟੈਕਸਟ ਅਤੇ ਨੰਬਰ ਦਰਜ ਕਰਨ ਵਿਚਕਾਰ ਸਵਿਚ ਕਰੋ"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"ਹੋਰ ਭਾਗੀਦਾਰ ਜੋੜੋ"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ਭਾਗੀਦਾਰਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"ਨਵੀਂ ਗੱਲਬਾਤ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ਇਹ ਆਈਟਮ ਚੁਣੋ"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ਵੀਡੀਓ ਪਲੇ ਕਰੋ"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ਲੋਕ &amp; ਚੋਣਾਂ"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ਡੀਬਗ ਕਰੋ"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ਲੋਕ &amp; ਚੋਣਾਂ"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ਸਧਾਰਨ"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ਇਸ ਗੱਲਬਾਤ ਵਿੱਚ ਲੋਕ"</string>
+    <string name="action_call" msgid="6596167921517350362">"ਇੱਕ ਕਾਲ ਕਰੋ"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ਸੁਨੇਹਾ ਭੇਜੋ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"ਸੁਨੇਹਾ ਭੇਜੋ&lt;br/&gt;&lt;ਛੋਟਾ&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/ਤੋਂ ਛੋਟਾ&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ਫੋਟੋਆਂ ਭੇਜੋ</item>
+      <item quantity="other">ਫੋਟੋਆਂ ਭੇਜੋ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ਔਡੀਓ ਭੇਜੋ</item>
+      <item quantity="other">ਔਡੀਓ ਭੇਜੋ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">ਵੀਡਿਓ ਭੇਜੋ</item>
+      <item quantity="other">ਵੀਡਿਓ ਭੇਜੋ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">ਸੰਪਰਕ ਕਾਰਡ ਭੇਜੋ</item>
+      <item quantity="other">ਸੰਪਰਕ ਕਾਰਡ ਭੇਜੋ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">ਅਟੈਚਮੈਂਟਾਂ ਭੇਜੋ</item>
+      <item quantity="other">ਅਟੈਚਮੈਂਟਾਂ ਭੇਜੋ</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਭੇਜਣ ਲਈ ਤਿਆਰ</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ਅਟੈਚਮੈਂਟਾਂ ਭੇਜਣ ਲਈ ਤਿਆਰ</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ਫੀਡਬੈਕ ਭੇਜੋ"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play ਸਟੋਰ ਵਿੱਚ ਦੇਖੋ"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ਵਰਜਨ ਜਾਣਕਾਰੀ"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"ਵਰਜਨ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ਓਪਨ ਸ੍ਰੋਤ ਲਸੰਸ"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"ਸੂਚਨਾਵਾਂ"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ਅਟੈਚਮੈਂਟ ਸੀਮਾ ਪੂਰੀ ਹੋਈ"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ਅਟੈਚਮੈਂਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ।"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"ਕੀ ਸੰਪਰਕ ਜੋੜਨੇ ਹਨ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"ਸੰਪਰਕ ਜੋੜੋ"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"ਵਿਸ਼ਾ"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"ਵਿਸ਼ਾ: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"ਸੰਪਰਕ ਕਾਰਡ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"ਸੰਪਰਕ ਕਾਰਡ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"ਸੰਪਰਕ ਕਾਰਡ ਦੇਖੋ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ਸੰਪਰਕ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਸੰਪਰਕ</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"ਸੰਪਰਕ ਕਾਰਡ"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"ਜਨਮਦਿਨ"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"ਸੂਚਨਾਵਾਂ"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"ਸੁਨੇਹਾ ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ਜਵਾਬ ਦਿਓ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS ਅਸਮਰਥਿਤ"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ਭੇਜਣ ਲਈ, Messaging ਨੂੰ ਡਿਫੌਲਟ SMS ਐਪ ਦੇ ਤੌਰ ਤੇ ਸੈਟ ਕਰੋ"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Messaging ਨੂੰ ਡਿਫੌਲਟ SMS ਐਪ ਦੇ ਤੌਰ ਤੇ ਸੈਟ ਕਰੋ"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"ਬਦਲੋ"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, Messaging ਨੂੰ ਡਿਫੌਲਟ SMS ਐਪਸ ਦੇ ਤੌਰ ਤੇ ਸੈਟ ਕਰੋ"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ ਕੋਈ ਤਰਜੀਹੀ SIM ਨਹੀਂ ਚੁਣਿਆ ਗਿਆ"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ਡਿਵਾਈਸ ਮਾਲਕ ਵੱਲੋਂ ਇਸ ਐਪ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ਠੀਕ"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"ਇੱਕ ਗੱਲਬਾਤਾ ਵਿੱਚ ਬਹੁਤ ਜ਼ਿਆਦਾ ਪ੍ਰਾਪਤਕਰਤਾ"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">ਅਪ੍ਰਮਾਣਿਕ ਸੰਪਰਕ</item>
+      <item quantity="other">ਅਪ੍ਰਮਾਣਿਕ ਸੰਪਰਕ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ਕੈਮਰਾ ਚਿੱਤਰ ਲੋਡ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"ਤੁਸੀਂ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ਡ੍ਰਾਫਟ"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵੀਂ ਗੱਲਬਾਤ ਚਾਲੂ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ ਇਸਨੂੰ ਇੱਥੇ ਸੂਚੀਬੱਧ ਦੇਖੋਗੇ"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ਆਰਕਾਈਵ ਕੀਤੀਆਂ ਗੱਲਬਾਤਾਂ ਇੱਥੇ ਪ੍ਰਗਟ ਹੋਣਗੀਆਂ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"ਗੱਲਬਾਤਾਂ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ਤਸਵੀਰ"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ਔਡੀਓ ਕਲਿਪ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ਵੀਡੀਓ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"ਸੰਪਰਕ ਕਾਰਡ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"ਪਹਿਲਾਂ ਵਰਗਾ ਕਰੋ"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ਇੱਕ ਨਵਾਂ ਸੁਨੇਹਾ ਚਾਲੂ ਕਰਨ ਲਈ ਇੱਕ ਸੰਪਰਕ ਨਾਮ ਜਾਂ ਫੋਨ ਨੰਬਰ ਦਰਜ ਕਰੋ"</string>
+    <string name="action_block" msgid="9032076625645190136">"ਬਲੌਕ ਕਰੋ"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> ਨੂੰ ਬਲੌਕ ਕਰੋ"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> ਨੂੰ ਅਨਬਲੌਕ ਕਰੋ"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"ਕੀ <xliff:g id="DESTINATION">%s</xliff:g> ਨੂੰ ਬਲੌਕ ਕਰਨਾ ਹੈ?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"ਤੁਸੀਂ ਇਸ ਨੰਬਰ ਤੋਂ ਲਗਾਤਾਰ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰੋਗੇ ਪਰੰਤੂ ਹੁਣ ਤੁਹਾਨੂੰ ਸੂਚਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾਏਗਾ। ਇਹ ਗੱਲਬਾਤ ਆਰਕਾਈਵ ਕੀਤੀ ਜਾਏਗੀ।"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"ਬਲੌਕ ਕੀਤੇ ਸੰਪਰਕ"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ਅਨਬਲੌਕ ਕਰੋ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"ਬਲੌਕ ਕੀਤੇ ਸੰਪਰਕ"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ਦਸਤਾਵੇਜ਼ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚੋਂ ਚਿੱਤਰ ਚੁਣੋ"</string>
+    <string name="sending_message" msgid="6363584950085384929">"ਸੁਨੇਹਾ ਭੇਜ ਰਿਹਾ ਹੈ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"ਸੁਨੇਹਾ ਭੇਜਿਆ ਗਿਆ"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ਸੈਲਿਊਲਰ ਡਾਟਾ ਬੰਦ ਹੈ। ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"ਏਅਰਪਲੇਨ ਮੋਡ ਵਿੱਚ ਸੁਨੇਹੇ ਨਹੀਂ ਭੇਜ ਸਕਦਾ"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ ਜਾ ਸਕੇਗਾ"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"ਸੁਨੇਹਾ ਡਾਊਨਲੋਡ ਕੀਤਾ"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ਸੈਲਿਊਲਰ ਡਾਟਾ ਬੰਦ ਹੈ। ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ਏਅਰਪਲੇਨ ਮੋਡ ਵਿੱਚ ਸੁਨੇਹੇ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"ਸੁਨੇਹਾ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕੇਗਾ"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"ਸਿਫਰ"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ਇੱਕ"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"ਦੋ"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"ਤਿੰਨ"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"ਚਾਰ"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ਪੰਜ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ਛੇ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ਸੱਤ"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ਅੱਠ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ਨੌ"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> ਨਾਲ ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜ ਸਕਦਾ, ਅਸ਼ੁੱਧੀ <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"ਅਗਿਆਤ ਕੈਰੀਅਰ ਨਾਲ ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜ ਸਕਦਾ, ਅਸ਼ੁੱਧੀ <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ: ਨੈਟਵਰਕ ਤੇ ਸੇਵਾ ਸਕਿਰਿਆ ਨਹੀਂ"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ: ਅਪ੍ਰਮਾਣਿਕ ਡੈਸਟੀਨੇਸ਼ਨ ਪਤਾ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ: ਅਪ੍ਰਮਾਣਿਤ ਸੁਨੇਹਾ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ: ਅਸਮਰਥਿਤ ਸਮੱਗਰੀ"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ: ਅਸਮਰਥਿਤ ਸੁਨੇਹਾ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ: ਬਹੁਤ ਜ਼ਿਆਦਾ ਵੱਡਾ"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"ਨਵਾਂ ਸੁਨੇਹਾ"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ਦੇਖੋ"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"ਚਿੱਤਰ"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"ਇੱਕ ਅਨੁੁਕੂਲ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਲੱਭ ਸਕਿਆ"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"ਪ੍ਰਾਪਤਕਰਤਾ ਹਟਾਓ"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"ਨਵਾਂ ਸੁਨੇਹਾ"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ਰੱਦ ਕਰੋ"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ਪਹੁੰਚ ਬਿੰਦੂ ਸੰਪਾਦਿਤ ਕਰੋ"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"ਸੈਟ ਨਹੀਂ ਕੀਤਾ"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ਨਾਮ"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ਪ੍ਰੌਕਸੀ"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS ਪੋਰਟ"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN ਪ੍ਰਕਾਰ"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN ਮਿਟਾਓ"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"ਨਵਾਂ APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"ਸੁਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ਅਣਡਿੱਠਾ"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"ਨਾਮ ਖੇਤਰ ਨੂੰ ਖਾਲੀ ਨਹੀਂ ਛੱਡਿਆ ਜਾ ਸਕਦਾ।"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ਨੂੰ ਖਾਲੀ ਨਹੀਂ ਛੱਡਿਆ ਜਾ ਸਕਦਾ।"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ਖੇਤਰ 3 ਅੰਕਾਂ ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ।"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ਖੇਤਰ 2 ਜਾਂ 3 ਅੰਕਾਂ ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ।"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"ਡਿਫੌਲਟ APN ਸੈਟਿੰਗਾਂ ਰੀਸਟੋਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ਡਿਫੌਲਟਸ ਤੇ ਰੀਸੈਟ ਕਰੋ"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"ਡਿਫੌਲਟ APN ਸੈਟਿੰਗਾਂ ਰੀਸੈਟ ਕਰਨਾ ਪੂਰਾ ਹੋਇਆ।"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ਬਿਨਾਂ ਨਾਮ"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ਪਹੁੰਚ ਬਿੰਦੂ ਨਾਮ"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"ਨਵਾਂ APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ਪਹੁੰਚ ਬਿੰਦੂ ਨਾਮ ਸੈਟਿੰਗਾਂ ਇਸ ਉਪਭੋਗਤਾ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"ਕੀ ਕਲਿਪਬੋਰਡ ਤੇ ਕਾਪੀ ਕਰਨਾ ਹੈ?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"ਕਾਪੀ ਕਰੋ"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> ਨੂੰ"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ਸਧਾਰਨ"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"ਉੱਨਤ"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"ਸਧਾਰਨ ਸੈਟਿੰਗਾਂ"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"ਉੱਨਤ ਸੈਟਿੰਗਾਂ"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ਸਾਰੇ ਪ੍ਰਾਪਤਕਰਤਾਵਾਂ ਨੂੰ ਵੱਖ-ਵੱਖ SMS ਸੁਨੇਹੇ ਭੇਜੋ। ਕੇਵਲ ਤੁਸੀਂ ਹੀ ਕੋਈ ਜਵਾਬ ਪ੍ਰਾਪਤ ਕਰੋਗੇ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ਸਾਰੇ ਪ੍ਰਾਪਤਕਰਤਾਵਾਂ ਨੂੰ ਇੱਕ ਸਿੰਗ MMS ਭੇਜੋ।"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"ਅਗਿਆਤ ਨੰਬਰ"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"ਨਵਾਂ ਸੁਨੇਹਾ"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"ਨਵਾਂ ਸੁਨੇਹਾ।"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM ਚੋਣਕਾਰ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ਚੁਣਿਆ ਗਿਆ, SIM ਚੋਣਕਰਤਾ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"ਵਿਸ਼ਾ ਸੰਪਾਦਿਤ ਕਰੋ"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM ਚੁਣੋ ਜਾਂ ਵਿਸ਼ਾ ਸੰਪਾਦਿਤ ਕਰੋ"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਛੋਹਵੋ ਅਤੇ ਹੋਲਡ ਕਰੋ"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"ਨਵੀਂ ਗੱਲਬਾਤ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Messaging"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Messaging ਸੂਚੀ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Messaging"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"ਨਵਾਂ ਸੁਨੇਹਾ"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"ਗੱਲਬਾਤ ਸੂਚੀ"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"ਗੱਲਬਾਤਾਂ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"ਸੁਨੇਹੇ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"ਹੋਰ ਗੱਲਬਾਤਾਂ ਦੇਖੋ"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"ਹੋਰ ਸੁਨੇਹੇ ਦੇਖੋ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"ਗੱਲਬਾਤ ਮਿਟਾਈ ਗਈ"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ਗੱਲਬਾਤ ਮਿਟਾਈ ਗਈ। ਇੱਕ ਵੱਖਰੀ Messaging ਗੱਲਬਾਤ ਦਿਖਾਉਣ ਲਈ ਛੋਹਵੋ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ਬਲੌਕ ਕੀਤਾ"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"ਅਨਬਲੌਕ ਕੀਤਾ"</string>
+    <string name="db_full" msgid="8459265782521418031">"ਸਟੋਰੇਜ ਸਪੇਸ ਘੱਟ ਹੈ। ਕੁਝ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ਅਟੈਚਮੈਂਟਾਂ ਚੁਣੋ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ਚੋਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ਚੁਣਿਆ ਗਿਆ"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਜਾਂ ਵੱਧ ਅਟੈਚਮੈਂਟਾਂ ਹਟਾਓ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"ਤੁਸੀਂ ਆਪਣਾ ਸੁਨੇਹਾ ਭੇਜਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਇਹ ਸ਼ਾਇਦ ਨਾ ਭੇਜਿਆ ਜਾ ਸਕੇ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇੱਕ ਜਾਂ ਵੱਧ ਅਟੈਚਮੈਂਟਾਂ ਨਹੀਂ ਹਟਾਉਂਦੇ।"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ਤੁਸੀਂ ਪ੍ਰਤੀ ਸੁਨੇਹਾ ਕੇਵਲ ਇੱਕ ਵੀਡੀਓ ਭੇਜ ਸਕਦੇ ਹੋ। ਕਿਰਪਾ ਕਰਕੇ ਵਾਧੂ ਵੀਡੀਓ ਹਟਾਓ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Messaging ਅਟੈਚਮੈਂਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ।"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ਫੇਰ ਵੀ ਭੇਜੋ"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"ਗੱਲਬਾਤ ਚਾਲੂ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ਚੁਣਿਆ ਗਿਆ"</string>
+</resources>
diff --git a/res/values-pl/arrays.xml b/res/values-pl/arrays.xml
new file mode 100644
index 0000000..2bd82e4
--- /dev/null
+++ b/res/values-pl/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"brak tematu"</item>
+    <item msgid="272485471009191934">"braktematu"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Tak"</item>
+    <item msgid="6049132459802288033">"Nie"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Ha ha"</item>
+    <item msgid="2611328818571146775">"Dzięki"</item>
+    <item msgid="4881335087096496747">"Zgadzam się"</item>
+    <item msgid="2422296858597420738">"Super"</item>
+    <item msgid="4805581752819452687">"Jestem w drodze"</item>
+    <item msgid="4746700499431366214">"Skontaktuję się z Tobą później"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
new file mode 100644
index 0000000..1f21955
--- /dev/null
+++ b/res/values-pl/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Wiadomości"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Wiadomości"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Wybierz wątek"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ustawienia"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Wyślij wiadomość"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Dodaj załącznik"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Pomoc"</string>
+    <string name="welcome" msgid="2857560951820802321">"Witamy"</string>
+    <string name="skip" msgid="7238879696319945853">"Pomiń"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Dalej &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Dalej"</string>
+    <string name="exit" msgid="1905187380359981199">"Zakończ"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Ustawienia &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ustawienia"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Aplikacja SMS/MMS potrzebuje uprawnień do SMS-ów, telefonu i kontaktów."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Uprawnienia możesz zmienić, klikając Ustawienia &gt; Aplikacje &gt; SMS/MMS &gt; Uprawnienia."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Uprawnienia możesz zmienić, klikając Ustawienia, Aplikacje, SMS/MMS, Uprawnienia."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Częste kontakty"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Wszystkie kontakty"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Wyślij pod numer <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Zrób zdjęcia lub nagraj film"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Wybierz obrazy z tego urządzenia"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Nagraj dźwięk"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Wybierz zdjęcie"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Plik multimedialny został wybrany."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Plik multimedialny nie został wybrany."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Wybrano: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"obraz – <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"obraz"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Nagraj dźwięk"</string>
+    <string name="action_share" msgid="2143483844803153871">"Udostępnij"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"W tej chwili"</string>
+    <string name="posted_now" msgid="867560789350406701">"Teraz"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> godziny</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> godzin</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> godziny</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> godzina</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dnia</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dzień</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> tygodnie</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> tygodni</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tygodnia</item>
+      <item quantity="one">tydzień</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> miesiące</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> miesięcy</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> miesiąca</item>
+      <item quantity="one">miesiąc</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> lata</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> lat</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> roku</item>
+      <item quantity="one">rok</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Wiadomość klasy 0"</string>
+    <string name="save" msgid="5081141452059463572">"Zapisz"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Na urządzeniu jest mało miejsca. Aplikacja SMS/MMS automatycznie usunie starsze SMS-y, by zwolnić miejsce."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Kończy się miejsce"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Aplikacja SMS/MMS może nie wysyłać i nie odbierać wiadomości do momentu zwolnienia miejsca na urządzeniu."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Mało miejsca na SMS-y. Może usuniesz niektóre wiadomości?"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Potwierdź swój numer telefonu"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Dzięki tej jednorazowej czynności aplikacja SMS/MMS będzie poprawnie dostarczać Twoje wiadomości grupowe."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numer telefonu"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Usuń wszystkie MMS-y"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Usuń wiadomości starsze niż <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automatycznie usuwaj wiadomości starsze niż <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignoruj"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Usunąć wszystkie MMS-y?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Usunąć wiadomości starsze niż <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Usunąć wiadomości starsze niż <xliff:g id="DURATION">%s</xliff:g> i włączyć automatyczne usuwanie?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> pisze"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Treść Twojej wiadomości"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Wiadomość od użytkownika <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Wysłałeś wiadomość"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Wysyłam…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nie wysłano. Kliknij, by spróbować ponownie."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nie wysłano. Próbuję ponownie…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Wyślij ponownie lub usuń"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Zadzwoń do służb ratunkowych. Tym razem nie udało się dostarczyć SMS-a."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Błąd"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nowa wiadomość MMS do pobrania"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nowa wiadomość MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nie udało się pobrać"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Kliknij, by spróbować ponownie"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Kliknij, by pobrać"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Pobierz lub usuń"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Pobieram…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Wiadomość wygasła lub jest niedostępna"</string>
+    <string name="mms_info" msgid="3402311750134118165">"rozmiar: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, termin ważności: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nie można wysłać. Nieprawidłowy adresat."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Usługa nie została aktywowana w sieci"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Nie udało się wysłać z powodu problemu z siecią"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Wiadomość wygasła lub jest niedostępna"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Brak tematu)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Nieznany nadawca"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Dostarczono"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nie udało się pobrać wiadomości <xliff:g id="SUBJECT">%1$s</xliff:g> od użytkownika <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Nie można dokończyć operacji na bazie danych z powodu zbyt małej ilości pamięci"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Wiadomość nie została wysłana"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Niektóre wiadomości nie zostały wysłane w aplikacji SMS/MMS"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątkach</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątkach</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątku</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> wiadomości w jednym wątku</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Wiadomość nie została pobrana"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Niektóre wiadomości nie zostały pobrane w aplikacji SMS/MMS"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątkach</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątkach</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> wiadomości w <xliff:g id="CONVERSATIONS">%d</xliff:g> wątku</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> wiadomości w jednym wątku</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Wiadomość do <xliff:g id="NUMBER">%1$s</xliff:g> nie została wysłana"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Zadzwoń do służb ratunkowych. Tym razem nie udało się dostarczyć SMS-a pod numer <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nowe wiadomości</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> nowych wiadomości</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nowej wiadomości</item>
+      <item quantity="one">Nowa wiadomość</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Rozpocznij"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Aparat jest niedostępny"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Aparat jest niedostępny"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Nagrywanie filmu jest niedostępne"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nie można zapisać pliku multimedialnego"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nie można zrobić zdjęcia"</string>
+    <string name="back" msgid="1477626055115561645">"Wstecz"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archiwum"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Usuń"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archiwizuj"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Przywróć z archiwum"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Wyłącz powiadomienia"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Włącz powiadomienia"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Dodaj kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Pobierz"</string>
+    <string name="action_send" msgid="377635240181672039">"Wyślij"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Usuń"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Usunąć tę wiadomość?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Nie można tego cofnąć."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Usuń"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="few">Usunąć te wątki?</item>
+      <item quantity="many">Usunąć te wątki?</item>
+      <item quantity="other">Usunąć te wątki?</item>
+      <item quantity="one">Usunąć ten wątek?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Usuń"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Anuluj"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Do"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Wybierz wiele obrazów"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Potwierdź wybór"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"Jeszcze <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Nie można nagrać dźwięku. Spróbuj ponownie."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Nie można odtworzyć dźwięku. Spróbuj ponownie."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Nie można zapisać dźwięku. Spróbuj ponownie."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Kliknij i przytrzymaj"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Zdjęcie"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Klip dźwiękowy"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Film"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Wizytówka"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Pobierz"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Odpowiedz SMS-em"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Wyślij MMS-a"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Odpowiedz"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> uczestników</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> uczestników</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> uczestnika</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> uczestnik</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ja"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt został zablokowany i zarchiwizowany"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt odblokowany i rozpakowany"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Zarchiwizowano: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Przywrócone z archiwum: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Powiadomienia wyłączone"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Powiadomienia włączone"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Wszystko gotowe. Ponownie kliknij Wyślij."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"SMS/MMS to teraz domyślna aplikacja do SMS-ów."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="few">Odrzuć załączniki</item>
+      <item quantity="many">Odrzuć załączniki</item>
+      <item quantity="other">Odrzuć załączniki</item>
+      <item quantity="one">Odrzuć załącznik</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Załącznik audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Odtwórz załącznik audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pauza"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Wiadomość od użytkownika <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Nieudane odbieranie wiadomości od: <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Wiadomość od: <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Niewysłana wiadomość do: <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Wysyłanie wiadomości do: <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Nieudane wysyłanie wiadomości do: <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Wiadomość do: <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Nieudane odbieranie wiadomości od: <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Wiadomość od: <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Niewysłana wiadomość do: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Wysyłanie wiadomości do: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Nieudane wysyłanie wiadomości do: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Wiadomość do: <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Godzina: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Niedostarczona wiadomość. Kliknij, aby ponowić próbę."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Rozmowa z: <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Usuń temat"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Nagraj film"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Zrób zdjęcie"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Zrób zdjęcie"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Zacznij nagrywać film"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Włącz aparat pełnoekranowy"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Przełącz między kamerą z przodu i z tyłu"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Zatrzymaj nagrywanie i dołącz film"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Zatrzymaj nagrywanie filmu"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Zdjęcia z aplikacji SMS/MMS"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> zdjęcia zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> zdjęć zapisanych w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> zdjęcia zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> zdjęcie zapisane w albumie „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> filmy zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> filmów zapisanych w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> filmu zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> film zapisany w albumie „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> załączniki zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> załączników zapisanych w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> załącznika zapisane w albumie „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> załącznik zapisany w albumie „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> załączniki zapisane w folderze „Pobrane pliki”</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> załączników zapisanych w folderze „Pobrane pliki”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> załącznika zapisane w folderze „Pobrane pliki”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> załącznik zapisany w folderze „Pobrane pliki”</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> załączniki zapisane</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> załączników zapisanych</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> załącznika zapisane</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> załącznik zapisany</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="few">Nie udało się zapisać <xliff:g id="QUANTITY_1">%d</xliff:g> załączników</item>
+      <item quantity="many">Nie udało się zapisać <xliff:g id="QUANTITY_1">%d</xliff:g> załączników</item>
+      <item quantity="other">Nie udało się zapisać <xliff:g id="QUANTITY_1">%d</xliff:g> załącznika</item>
+      <item quantity="one">Nie udało się zapisać <xliff:g id="QUANTITY_0">%d</xliff:g> załącznika</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Zapisany załącznik MMS-a"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ustawienia"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Zarchiwizowane"</string>
+    <string name="action_close" msgid="1840519376200478419">"Zamknij"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Zaawansowane"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Debugowanie"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Powiadomienia"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Dźwięk"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Cichy"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Wibracje"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Zablokowany"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Raporty doręczeń SMS-ów"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Otrzymuj raport o dostarczeniu każdego wysłanego SMS-a"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Autopobieranie"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automatycznie pobieraj MMS-y"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Autopobieranie w roamingu"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automatycznie pobieraj MMS-y w roamingu"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Wiadomości grupowe"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Używaj MMS-ów, gdy chcę wysłać jedną wiadomość do wielu odbiorców"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Domyślna aplikacja do SMS-ów"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Domyślna aplikacja do SMS-ów"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Twój numer telefonu"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Nieznany"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Dźwięki przy wysyłaniu wiadomości"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Zrzuć SMS-y"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Zrzuć odebrane nieprzetworzone dane SMS-ów do pliku w pamięci zewnętrznej"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Zrzuć MMS-y"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Zrzuć odebrane nieprzetworzone dane MMS-ów do pliku w pamięci zewnętrznej"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alerty o zagrożeniach"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opcje wiadomości"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Skopiuj tekst"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Wyświetl szczegóły"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Usuń"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Przekaż dalej"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Szczegóły wiadomości"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Typ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Wiadomość multimedialna"</string>
+    <string name="from_label" msgid="1947831848146564875">"Od: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Do: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Wysłano: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Odebrane: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Temat: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Rozmiar: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorytet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Wysoki"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normalny"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Niski"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Ukryty adres nadawcy"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Nie można wysłać wiadomości w czasie ładowania załączników."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nie można załadować załącznika. Spróbuj ponownie."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Sieć nie jest gotowa. Spróbuj ponownie."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Usuń tekst"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Przełącz się między wpisywaniem tekstu i cyfr"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Dodaj uczestników"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Potwierdź uczestników"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Rozpocznij nowy wątek"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Wybierz ten element"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Odtwórz film"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Osoby i opcje"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Debuguj"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Osoby i opcje"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Ogólne"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Uczestnicy tej rozmowy"</string>
+    <string name="action_call" msgid="6596167921517350362">"Zadzwoń"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Wyślij wiadomość"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Wyślij wiadomość&lt;br/&gt;&lt;small&gt;z <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="few">Wyślij zdjęcia</item>
+      <item quantity="many">Wyślij zdjęcia</item>
+      <item quantity="other">Wyślij zdjęcia</item>
+      <item quantity="one">Wyślij zdjęcie</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="few">Wyślij pliki audio</item>
+      <item quantity="many">Wyślij pliki audio</item>
+      <item quantity="other">Wyślij pliki audio</item>
+      <item quantity="one">Wyślij plik audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="few">Wyślij filmy</item>
+      <item quantity="many">Wyślij filmy</item>
+      <item quantity="other">Wyślij filmy</item>
+      <item quantity="one">Wyślij film</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="few">Wyślij wizytówki</item>
+      <item quantity="many">Wyślij wizytówki</item>
+      <item quantity="other">Wyślij wizytówki</item>
+      <item quantity="one">Wyślij wizytówkę</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="few">Wyślij załączniki</item>
+      <item quantity="many">Wyślij załączniki</item>
+      <item quantity="other">Wyślij załączniki</item>
+      <item quantity="one">Wyślij załącznik</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> załączniki gotowe do wysłania</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> załączników gotowych do wysłania</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> załącznika gotowe do wysłania</item>
+      <item quantity="one">Jeden załącznik gotowy do wysłania</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Prześlij opinię"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Zobacz w Sklepie Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informacje o wersji"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Wersja %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licencje open source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Powiadomienia"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Osiągnięto limit załączników"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Nie udało się załadować załącznika."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Dodać do kontaktów?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Dodaj kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Temat"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Temat: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Ładowanie wizytówki"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nie można załadować wizytówki"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Wyświetl wizytówkę"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> kontakty</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> kontaktów</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktu</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Wizytówki"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Urodziny"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notatki"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Przekaż wiadomość dalej"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Odpowiedz"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-y wyłączone"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Aby wysyłać wiadomości, ustaw SMS/MMS jako domyślną aplikację do SMS-ów"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Ustaw SMS/MMS jako domyślną aplikację do SMS-ów"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Zmień"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Aby odbierać wiadomości, ustaw SMS/MMS jako domyślną aplikację do SMS-ów"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nie wybrano preferowanej karty SIM do wysyłania SMS-ów"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Właściciel urządzenia nie zezwolił na działanie tej aplikacji."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Zbyt wielu uczestników rozmowy"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="few">Nieprawidłowe kontakty</item>
+      <item quantity="many">Nieprawidłowe kontakty</item>
+      <item quantity="other">Nieprawidłowe kontakty</item>
+      <item quantity="one">Nieprawidłowy kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nie udało się załadować zdjęcia z aparatu"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ty: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Wersja robocza"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Po rozpoczęciu nowej rozmowy zobaczysz ją tutaj"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Tutaj będą widoczne zarchiwizowane wątki"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Ładuję wątki…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Zdjęcie"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Klip dźwiękowy"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Film"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Wizytówka"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Cofnij"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Ponów"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Wpisz nazwę kontaktu lub numer telefonu, by rozpocząć nową wiadomość"</string>
+    <string name="action_block" msgid="9032076625645190136">"Zablokuj"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Zablokuj: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Odblokuj: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Zablokować <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Będziesz nadal otrzymywać wiadomości z tego numeru, ale nie będzie już powiadomień o nich. Ten wątek zostanie zarchiwizowany."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Zablokowane kontakty"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ODBLOKUJ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Zablokowane kontakty"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Wybierz obraz z biblioteki dokumentów"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Wysyłam wiadomość"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Wiadomość wysłana"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Komórkowa transmisja danych jest wyłączona. Sprawdź ustawienia."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"W trybie samolotowym nie można wysyłać wiadomości"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Nie można wysłać wiadomości"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Wiadomość pobrana"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Komórkowa transmisja danych jest wyłączona. Sprawdź ustawienia."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Wiadomości nie można pobierać w trybie samolotowym"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Nie udało się pobrać wiadomości"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Jeden"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dwa"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trzy"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Cztery"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pięć"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sześć"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Siedem"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Osiem"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Dziewięć"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nie można wysłać wiadomości w sieci <xliff:g id="CARRIERNAME">%1$s</xliff:g> (błąd <xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nie można wysłać wiadomości w sieci nieznanego operatora (błąd <xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"PD: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Nie wysłano wiadomości: usługa nie została aktywowana w sieci"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Wiadomość nie została wysłana: nieprawidłowy adres docelowy"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Wiadomość nie została wysłana: nieprawidłowa wiadomość"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Wiadomość nie została wysłana: nieobsługiwane treści"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Wiadomość nie została wysłana: nieobsługiwana wiadomość"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Wiadomość nie została wysłana: jest za duża"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nowa wiadomość"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Wyświetl"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Obraz"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nie udało się znaleźć stosownej aplikacji"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Usuń odbiorcę"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nowa wiadomość"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Anuluj"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Edytuj punkt dostępu"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nie ustawiono"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nazwa"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy dla MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Typ APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Usuń APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nowy APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Zapisz"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Odrzuć"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Pole Nazwa nie może być puste."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Nazwa APN nie może być pusta."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Pole MCC musi zawierać 3 cyfry."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Pole MNC musi zawierać 2 lub 3 cyfry."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Przywracam domyślne ustawienia APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Przywróć domyślne"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Przywrócono domyślne ustawienia APN."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Bez nazwy"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nazwy punktów dostępu"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-y"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nowy APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Ustawienia nazwy punktu dostępu są niedostępne dla tego użytkownika"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Skopiować do schowka?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiuj"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"do <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Ogólne"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Zaawansowane"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Ustawienia ogólne"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Ustawienia zaawansowane"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Karta SIM „<xliff:g id="SIM_NAME">%s</xliff:g>”"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Wyślij osobne SMS-y do wszystkich odbiorców. Odpowiedzi trafią tylko do Ciebie"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Wysyłaj jednego MMS-a do wszystkich odbiorców"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nieznany numer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nowa wiadomość"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nowa wiadomość."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Przełącznik SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Przełącznik SIM, wybrana karta: <xliff:g id="SIM_0">%1$s</xliff:g>"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Edytuj temat"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Wybierz SIM lub edytuj temat"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Dotknij i przytrzymaj, aby nagrać dźwięk"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Zacznij nową rozmowę"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Wiadomości"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista wiadomości"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Wiadomości"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nowa wiadomość"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista wątków"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Ładuję wątki"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Wczytuję wiadomości"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Wyświetl więcej wątków"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Wyświetl więcej wiadomości"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Wątek został usunięty"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Rozmowa usunięta. Kliknij, by zobaczyć inną rozmowę w aplikacji SMS/MMS"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Zablokowano"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Odblokowano"</string>
+    <string name="db_full" msgid="8459265782521418031">"Mała ilość miejsca. Część danych może zostać utracona."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Wybierz załączniki"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Potwierdź wybór"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Wybrano <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Usuń co najmniej jeden załącznik i spróbuj ponownie."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Możesz spróbować wysłać wiadomość, ale może ona nie zostać dostarczona, dopóki nie usuniesz przynajmniej jednego załącznika."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"W jednej wiadomości możesz wysłać tylko jeden film. Usuń dodatkowe filmy i spróbuj ponownie."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Nie udało się załadować załącznika w aplikacji SMS/MMS."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Wyślij mimo wszystko"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Nie udało się rozpocząć rozmowy"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Wybrano <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-pt-rPT/arrays.xml b/res/values-pt-rPT/arrays.xml
new file mode 100644
index 0000000..3f99811
--- /dev/null
+++ b/res/values-pt-rPT/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sem assunto"</item>
+    <item msgid="272485471009191934">"sem assunto"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sim"</item>
+    <item msgid="6049132459802288033">"Não"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Eh eh"</item>
+    <item msgid="2611328818571146775">"Obrigado"</item>
+    <item msgid="4881335087096496747">"Aceito"</item>
+    <item msgid="2422296858597420738">"Boa"</item>
+    <item msgid="4805581752819452687">"Estou a caminho"</item>
+    <item msgid="4746700499431366214">"OK, ligo mais tarde"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..5c64052
--- /dev/null
+++ b/res/values-pt-rPT/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mensagens"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mensagens"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Selecionar conversa"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Definições"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Enviar mensagem"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Adicionar um anexo"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ajuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Bem-vindo"</string>
+    <string name="skip" msgid="7238879696319945853">"Ignorar"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Seguinte &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Seguinte"</string>
+    <string name="exit" msgid="1905187380359981199">"Sair"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Definições &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Definições"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"A aplicação Mensagens necessita de autorização para SMS, Telefone e Contactos."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Pode alterar as autorizações em Definições &gt; Aplicações &gt; Mensagens &gt; Autorizações."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Pode alterar as autorizações em Definições, Aplicações, Mensagens, Autorizações."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequentes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Todos os contactos"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Enviar para <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capturar imagens ou vídeo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Escolher imagens deste dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Gravar áudio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Escolher fotografia"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"O ficheiro multimédia está selecionado."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"O ficheiro multimédia está desselecionado."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selecionado(s)"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imagem de <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imagem"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Gravar áudio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Partilhar"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Agora mesmo"</string>
+    <string name="posted_now" msgid="867560789350406701">"Agora"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+      <item quantity="one">uma semana</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+      <item quantity="one">um mês</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> anos</item>
+      <item quantity="one">um ano</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mensagem de classe 0"</string>
+    <string name="save" msgid="5081141452059463572">"Guardar"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"O dispositivo tem pouco espaço disponível. A aplicação Mensagens elimina automaticamente mensagens mais antigas para libertar espaço."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Está quase sem espaço de armazenamento"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"A aplicação Mensagens pode não enviar ou receber mensagens até que exista mais espaço disponível no dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Armazenamento SMS reduzido. Pode ter de eliminar mensagens."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirmar número de telefone"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Este passo único assegura que a aplicação Mensagens fornece as suas mensagens de grupo corretamente."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de telefone"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Eliminar todas as mensagens com multimédia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Eliminar mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Eliminar automaticamente mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorar"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Eliminar todas as mensagens com multimédia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Eliminar mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Eliminar mensagens com mais de <xliff:g id="DURATION">%s</xliff:g> e ativar eliminação automática?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> disse"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Você disse"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensagem de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Enviou uma mensagem"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"A enviar..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Não enviado. Toque para tentar novamente."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Não enviado. A tentar novamente..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Reenviar ou eliminar"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Faça uma chamada de voz para os serviços de emergência. Neste momento, não foi possível entregar a sua mensagem de texto."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Falha"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nova mensagem MMS para transferir"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nova mensagem MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Não foi possível transferir"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Toque para tentar novamente"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Toque para transferir"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Transferir ou eliminar"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"A transferir..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mensagem expirada ou não disponível"</string>
+    <string name="mms_info" msgid="3402311750134118165">"tamanho: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, data de validade: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Não é possível enviar. O destinatário não é válido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Serviço não ativado na rede"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Não foi possível enviar devido a um problema de rede"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mensagem expirada ou não disponível"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sem assunto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Remetente desconhecido"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregue"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Não foi possível transferir a mensagem <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Não foi possível concluir a operação da base de dados devido a pouca memória"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mensagem não enviada"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Algumas mensagens não enviadas na aplicação Mensagens"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensagens numa conversa</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mensagem não transferida"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Algumas mensagens não transferidas na aplicação Mensagens"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mensagens numa conversa</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mensagem para <xliff:g id="NUMBER">%1$s</xliff:g> não enviada"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Faça uma chamada de voz para os serviços de emergência. Neste momento, não foi possível entregar a sua mensagem de texto para o número <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> novas mensagens</item>
+      <item quantity="one">Nova mensagem</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Iniciar"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Câmara não disponível"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Câmara não disponível"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Captura de vídeo não disponível"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Não é possível guardar multimédia"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Não é possível tirar a fotografia"</string>
+    <string name="back" msgid="1477626055115561645">"Anterior"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arquivadas"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Eliminar"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arquivar"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Retirar do arquivo"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desativar as notificações"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Ativar notificações"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Adicionar contacto"</string>
+    <string name="action_download" msgid="7786338136368564146">"Transferir"</string>
+    <string name="action_send" msgid="377635240181672039">"Enviar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Eliminar"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Pretende eliminar esta mensagem?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Esta ação não pode ser anulada."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Eliminar"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Pretende eliminar estas conversas?</item>
+      <item quantity="one">Pretende eliminar esta conversa?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Eliminar"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancelar"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Selecionar várias imagens"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmar seleção"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Não é possível gravar áudio. Tente novamente."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Não é possível reproduzir áudio. Tente novamente."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Não foi possível guardar áudio. Tente novamente."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Toque sem largar"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imagem"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clipe de áudio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vídeo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Cartão de contacto"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Transferir"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Responder por SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Responder por MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Responder"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participante</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Eu"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contacto bloqueado e arquivado"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contacto desbloqueado e não arquivado"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arquivada(s)"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> não arquivada(s)"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificações desativadas"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificações ativadas"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Tudo definido. Toque novamente em Enviar."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"A aplicação Mensagens foi definida com êxito como a aplicação de SMS predefinida."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Rejeitar anexos</item>
+      <item quantity="one">Rejeitar anexo</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Anexo de áudio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproduzir anexo de áudio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Interromper"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mensagem falhada de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mensagem não enviada para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"A enviar mensagem para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mensagem falhada para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensagem para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mensagem falhada de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mensagem não enviada para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"A enviar mensagem para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mensagem falhada para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensagem para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mensagem falhada. Toque para tentar novamente."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversa com <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Eliminar assunto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capturar vídeo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturar uma imagem fixa"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Tirar fotografia"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Começar a gravar vídeo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Mudar para a câmara de ecrã completo"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Alternar entre as câmaras frontal e traseira"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Parar gravação e anexar vídeo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Parar a gravação de vídeo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos das Mensagens"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotos guardadas no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto guardada no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vídeos guardados no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> vídeo guardado no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> anexos guardados no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> anexo guardado no álbum \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos guardados em \"Transferências\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> anexo guardado em \"Transferências\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos guardados</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> anexo guardado</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Não foi possível guardar <xliff:g id="QUANTITY_1">%d</xliff:g> anexos</item>
+      <item quantity="one">Não foi possível guardar <xliff:g id="QUANTITY_0">%d</xliff:g> anexo</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Anexo de MMS guardado"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Definições"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arquivadas"</string>
+    <string name="action_close" msgid="1840519376200478419">"Fechar"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avançadas"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depurar"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificações"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Som"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silencioso"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrar"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqueado"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Relatórios de entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicitar um relatório de entrega para cada SMS enviada"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperação automática"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recuperar automaticamente mensagens MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recuperar automat. em roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Obter automaticamente MMS em roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mensagens de grupo"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utilizar MMS para enviar uma única mensagem quando houver vários destinatários"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicação de SMS predefinida"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicação de SMS predefinida"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"O seu número de telefone"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Desconhecido"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons de mensagem enviada"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Criar cópia de segurança de SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"A cópia de segurança recebeu dados SMS não processados no ficheiro de armazenamento externo"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Criar cópia de segurança de MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"A cópia de segurança recebeu dados MMS não processados no ficheiro de armazenamento externo"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertas sem fios"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opções da mensagem"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiar texto"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ver detalhes"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Eliminar"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Encaminhar"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalhes da mensagem"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mensagem de texto"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mensagem multimédia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Para: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviadas: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Recebidas: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Assunto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamanho: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioridade: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baixa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Endereço do remetente oculto"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Não é possível enviar a mensagem enquanto os anexos estiverem a ser carregados."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Não é possível carregar o anexo. Tente novamente."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"A rede não está pronta. Tente novamente."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Eliminar texto"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alternar entre a introdução de texto e números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Adicionar mais participantes"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmar participantes"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Iniciar nova conversa"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selecionar este item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproduzir vídeo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Pessoas e opções"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depurar"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Pessoas e opções"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Geral"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Pessoas nesta conversa"</string>
+    <string name="action_call" msgid="6596167921517350362">"Efetuar uma chamada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Enviar mensagem"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Enviar mensagem&lt;br/&gt;&lt;small&gt;de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Enviar fotos</item>
+      <item quantity="one">Enviar foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Enviar ficheiros de áudio</item>
+      <item quantity="one">Enviar ficheiro de áudio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Enviar vídeos</item>
+      <item quantity="one">Enviar vídeo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Enviar cartões de contacto</item>
+      <item quantity="one">Enviar cartão de contacto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Enviar anexos</item>
+      <item quantity="one">Enviar anexo</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> anexos prontos a enviar</item>
+      <item quantity="one">Um anexo pronto a enviar</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Enviar comentários"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ver na Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informações da versão"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versão %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenças de código aberto"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificações"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Foi atingido o limite de anexos"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Falha ao carregar o anexo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Adicionar a Contactos?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Adicionar contacto"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Assunto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Assunto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"A carregar o cartão de contacto"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Não foi possível carregar o cartão de contacto"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ver cartão de contacto"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contactos</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> contacto</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Cartões de contacto"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Aniversário"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Encaminhar mensagem"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Responder"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS desativado"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Para enviar, defina a aplicação Mensagens como a aplicação de SMS predefinida"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Defina a aplicação Mensagens como a aplicação de SMS predefinida"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Alterar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Para receber mensagens, defina a aplicação Mensagens como a aplicação de SMS predefinida"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nenhum SIM preferido selecionado para o envio de mensagens SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Esta aplicação não é permitida pelo proprietário do dispositivo."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Demasiados participantes numa conversa"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Contactos inválidos</item>
+      <item quantity="one">Contacto inválido</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Não foi possível carregar a imagem da câmara"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Utilizador: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Rascunho"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Ao iniciar uma nova conversa, esta será listada aqui"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"As conversas arquivadas aparecem aqui"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"A carregar conversações..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imagem"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clipe de áudio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vídeo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Cartão de contacto"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Anular"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Tentar novamente"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Introduza um nome ou número de telefone do contacto para iniciar uma nova mensagem"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquear"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Pretende bloquear <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"O utilizador continuará a receber mensagens deste número, mas deixará de ser notificado. Esta conversa será arquivada."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contactos bloqueados"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEAR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contactos bloqueados"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Escolher imagem da biblioteca de documentos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"A enviar mensagem"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mensagem enviada"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Os dados celulares estão desligados. Verifique as suas definições."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Não é possível enviar mensagens no modo de avião"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Não foi possível enviar a mensagem"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mensagem transferida"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Os dados celulares estão desligados. Verifique as suas definições."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Não é possível transferir mensagens no modo de avião"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Não foi possível transferir a mensagem"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Um"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dois"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Três"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quatro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinco"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sete"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Oito"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nove"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Não é possível enviar a mensagem com <xliff:g id="CARRIERNAME">%1$s</xliff:g>, erro <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Não é possível enviar a mensagem com operador desconhecido, erro <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Enc: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mensagem não enviada: serviço não ativado na rede"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mensagem não enviada: endereço de destino inválido"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mensagem não enviada: mensagem inválida"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mensagem não enviada: conteúdo não suportado"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mensagem não enviada: a mensagem não é compatível"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mensagem não enviada: demasiado grande"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nova mensagem"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ver"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imagem"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Não foi possível encontrar uma aplicação adequada"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Remover o destinatário"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nova mensagem"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancelar"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editar ponto de acesso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Não definido"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nome"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy de MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Porta MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo de APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Eliminar APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Novo APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Guardar"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Rejeitar"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"O campo Nome não pode estar vazio."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"O APN não pode estar vazio."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"O campo MCC tem de ter 3 dígitos."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"O campo MNC tem de ter 2 ou 3 dígitos."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"A restaurar as predefinições do APN"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Repor as predefinições"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Reposição das predefinições do APN concluída."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sem nome"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nomes dos Pontos de Acesso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Novo APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"As definições de Nome do Ponto de Acesso não estão disponíveis para este utilizador"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Pretende copiar para a área de transferência?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiar"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"em <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Geral"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avançadas"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Definições gerais"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Definições avançadas"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Enviar mensagens SMS individuais para todos os destinatários. Apenas o utilizador recebe as respostas"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Enviar uma única MMS para todos os destinatários"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número desconhecido"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nova mensagem"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nova mensagem."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Seletor de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> selecionado, seletor de SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editar assunto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Selecionar SIM ou editar assunto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Tocar sem soltar para gravar áudio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Iniciar nova conversa"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mensagens"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista de mensagens"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mensagens"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nova mensagem"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversas"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"A carregar conversas"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"A carregar mensagens"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ver mais conversas"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ver mais mensagens"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversa eliminada"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversa eliminada. Toque para mostrar uma conversa das Mensagens diferente"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloqueado"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Desbloqueado"</string>
+    <string name="db_full" msgid="8459265782521418031">"O espaço de armazenamento é reduzido. Alguns dados podem ser perdidos."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Selecionar anexos"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmar seleção"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selecionado(s)"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Remova um ou mais anexos e tente novamente."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Pode tentar enviar a sua mensagem, mas esta pode não ser entregue se não remover um ou mais anexos."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Apenas pode enviar um vídeo por mensagem. Remova os vídeos adicionais e tente novamente."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Falha da aplicação Mensagens ao carregar o anexo."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Enviar mesmo assim"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Não foi possível iniciar a conversa"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selecionado"</string>
+</resources>
diff --git a/res/values-pt/arrays.xml b/res/values-pt/arrays.xml
new file mode 100644
index 0000000..0ab0334
--- /dev/null
+++ b/res/values-pt/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"sem assunto"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Sim"</item>
+    <item msgid="6049132459802288033">"Não"</item>
+    <item msgid="3084376867445867895">"Ok"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Obrigado"</item>
+    <item msgid="4881335087096496747">"Concordo"</item>
+    <item msgid="2422296858597420738">"Legal"</item>
+    <item msgid="4805581752819452687">"Estou a caminho"</item>
+    <item msgid="4746700499431366214">"OK, falo com você mais tarde"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
new file mode 100644
index 0000000..bd60502
--- /dev/null
+++ b/res/values-pt/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mensagens"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mensagens"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Selecionar uma conversa"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Configurações"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Enviar mensagem"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Adicionar um anexo"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ajuda"</string>
+    <string name="welcome" msgid="2857560951820802321">"Bem-vindo"</string>
+    <string name="skip" msgid="7238879696319945853">"Pular"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Próxima &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Próximo"</string>
+    <string name="exit" msgid="1905187380359981199">"Sair"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Configurações &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Configurações"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"O app Mensagens precisa de permissão para SMS, telefone e contatos."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"É possível alterar as permissões em \"Config. &gt; Apps &gt; Mensagens &gt; Permissões\"."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"É possível alterar as permissões em \"Config. &gt; Apps &gt; Mensagens &gt; Permissões\"."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frequentes"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Todos os contatos"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Enviar para <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Capturar fotos ou vídeos"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Escolher imagens do dispositivo"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Gravar áudio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Escolher foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"A mídia foi selecionada."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"A mídia foi desmarcada."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> selecionado"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imagem <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imagem"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Gravar áudio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Compartilhar"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Há pouco"</string>
+    <string name="posted_now" msgid="867560789350406701">"Agora"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> semanas</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> meses</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> anos</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> anos</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mensagem classe 0"</string>
+    <string name="save" msgid="5081141452059463572">"Salvar"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"O dispositivo está com pouco espaço. As mensagens mais antigas serão excluídas automaticamente para liberar espaço."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Pouco espaço de armazenamento"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"O app Mensagens talvez não envie ou receba mensagens até que mais espaço esteja disponível no seu dispositivo."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Pouco espaço para SMS. Pode ser necessário excluir mensagens."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirme seu número de telefone"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Esta etapa única garantirá que o app Mensagens entregue suas mensagens em grupo corretamente."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Número de telefone"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Excluir todas as mensagens com mídia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Excluir mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Excluir automaticamente mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorar"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Excluir todas as mensagens com mídia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Excluir mensagens com mais de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Excluir mensagens com mais de <xliff:g id="DURATION">%s</xliff:g> e ativar a exclusão automática?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> disse"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Você disse"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensagem de <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Você enviou uma mensagem"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Enviando…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Não enviado. Toque para tentar novamente."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Não enviado. Tentando novamente…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Reenviar ou excluir"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Faça uma chamada de voz para os serviços de emergência. Não foi possível entregar sua mensagem de texto no momento."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Falhou"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nova mensagem MMS para fazer o download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nova mensagem MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Falha no download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tocar para tentar novamente"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Tocar para fazer o download"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Fazer o download ou excluir"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Fazendo o download…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"A mensagem expirou ou não está disponível"</string>
+    <string name="mms_info" msgid="3402311750134118165">"tamanho: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, validade: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Falha ao enviar. Destinatário inválido."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Serviço não ativado na rede"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Falha ao enviar devido a um problema de rede"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"A mensagem expirou ou não está disponível"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Sem assunto)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Remetente desconhecido"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Entregue"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Não foi possível fazer o download da mensagem <xliff:g id="SUBJECT">%1$s</xliff:g> de <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Não foi possível concluir a operação do banco de dados devido a memória insuficiente"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mensagem não enviada"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Algumas mensagens não foram enviadas no app Mensagens"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Download da mensagem não realizado"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Não foi feito o download de algumas mensagens no app Mensagens"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mensagens em <xliff:g id="CONVERSATIONS">%d</xliff:g> conversas</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mensagem para <xliff:g id="NUMBER">%1$s</xliff:g> não enviada"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Faça uma chamada de voz para os serviços de emergência. Não foi possível entregar sua mensagem de texto para <xliff:g id="NUMBER">%1$s</xliff:g> no momento."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> novas mensagens</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> novas mensagens</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Iniciar"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Câmera não disponível"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Câmera não disponível"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Captura de vídeo não disponível"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Falha ao salvar a mídia"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Não é possível tirar uma foto"</string>
+    <string name="back" msgid="1477626055115561645">"Voltar"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arquivadas"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Excluir"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arquivar"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Desarquivar"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Desativar notificações"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Ativar notificações"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Adicionar contato"</string>
+    <string name="action_download" msgid="7786338136368564146">"Fazer o download"</string>
+    <string name="action_send" msgid="377635240181672039">"Enviar"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Excluir"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Excluir esta mensagem?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Esta ação não pode ser desfeita."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Excluir"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Excluir estas conversas?</item>
+      <item quantity="other">Excluir estas conversas?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Excluir"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Cancelar"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Selecionar várias imagens"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmar seleção"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Falha ao gravar o áudio. Tente novamente."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Falha ao reproduzir o áudio. Tente novamente."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Falha ao salvar o áudio. Tente novamente."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Toque e mantenha pressionado"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imagem"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clipe de áudio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Vídeo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Cartão de visita"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Responder via SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Responder via MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Responder"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> participantes</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Eu"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Contato bloqueado e arquivado"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Contato desbloqueado e desarquivado"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arquivada(s)"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> desarquivada(s)"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificações desativadas"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificações ativadas"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Tudo pronto. Toque em \"Enviar\" novamente."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"O app Mensagens foi definido como o app padrão de SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Descartar anexos</item>
+      <item quantity="other">Descartar anexos</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Anexo de áudio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Reproduzir anexo de áudio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausa"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Falha na mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mensagem não enviada para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Enviando mensagem para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Falha na mensagem para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensagem para <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Falha na mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensagem de <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mensagem não enviada para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Enviando mensagem para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Falha na mensagem para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensagem para <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Hora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Falha na mensagem. Toque para tentar novamente."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversa com <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Excluir assunto"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Capturar vídeo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Capturar uma imagem estática"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Tirar foto"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Iniciar gravação de vídeo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Alternar para câmera em tela cheia"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Alternar entre câmera frontal e traseira"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Parar a gravação e anexar vídeo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Parar gravação de vídeo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotos do app Mensagens"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> fotos salvas no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotos salvas no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> vídeos salvos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> vídeos salvos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> anexos salvos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> anexos salvos no álbum \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos salvos em \"Downloads\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos salvos em \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos salvos</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> anexos salvos</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Não foi possível salvar <xliff:g id="QUANTITY_1">%d</xliff:g> anexos</item>
+      <item quantity="other">Não foi possível salvar <xliff:g id="QUANTITY_1">%d</xliff:g> anexos</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Anexo MMS salvo"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Configurações"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arquivadas"</string>
+    <string name="action_close" msgid="1840519376200478419">"Fechar"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avançadas"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Depurar"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificações"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Som"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silencioso"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibração"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloqueado"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Relat. de entrega de SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicitar um relatório de entrega para cada SMS enviado"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Recuperação automática"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Recuperar mensagens MMS automaticamente"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Recup. autom. em roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Recuperar MMS automaticamente durante roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mensagens em grupo"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Usar MMS para enviar uma única mensagem para vários destinatários"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"App de SMS padrão"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"App de SMS padrão"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Seu número de telefone"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Desconhecido"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sons de mensagem de saída"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Descartar SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Descartar dados brutos de SMS recebidos no arquivo de armazenamento externo"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Descartar MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Descartar dados brutos de MMS recebidos no arquivo de armazenamento externo"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alertas sem fio"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opções de mensagem"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiar texto"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ver detalhes"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Excluir"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Avançar"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalhes da mensagem"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tipo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mensagem de texto"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mensagem multimídia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Para: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Enviada: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Recebida: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Assunto: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Tamanho: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioridade: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Alta"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Baixa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Endereço do remetente oculto"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Não é possível enviar mensagens ao carregar anexos."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Falha ao carregar o anexo. Tente novamente."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"A rede não está pronta. Tente novamente."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Excluir texto"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Alternar entre entrada de texto ou números"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Adicionar mais participantes"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmar participantes"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Iniciar nova conversa"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selecione este item"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Reproduzir vídeo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Pessoas e opções"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Depurar"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Pessoas e opções"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Gerais"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Pessoas nesta conversa"</string>
+    <string name="action_call" msgid="6596167921517350362">"Fazer uma chamada"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Enviar mensagem"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Enviar mensagem&lt;br/&gt;&lt;small&gt;de <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Enviar fotos</item>
+      <item quantity="other">Enviar fotos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Enviar áudios</item>
+      <item quantity="other">Enviar áudios</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Enviar vídeos</item>
+      <item quantity="other">Enviar vídeos</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Enviar cards de contato</item>
+      <item quantity="other">Enviar cards de contato</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Enviar anexos</item>
+      <item quantity="other">Enviar anexos</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> anexos prontos para envio</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> anexos prontos para envio</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Enviar feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ver na Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informações da versão"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versão %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenças de código aberto"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificações"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Limite de anexos alcançado"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Falha ao carregar anexo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Adicionar a Contatos?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Adicionar contato"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Assunto"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Assunto: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Carregando cartão de visita"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Falha ao carregar o cartão de visita"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ver cartão de visita"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> contatos</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> contatos</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Cartões de visita"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Aniversário"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notas"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Encaminhar mensagem"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Responder"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS desativado"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Para enviar, defina o Mensagens como app padrão de SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Definir o Mensagens como o app padrão de SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Alterar"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Para receber mensagens, defina o Mensagens como app padrão de SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nenhum SIM preferido para o envio de mensagens SMS selecionado"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Este app não é permitido pelo proprietário do dispositivo."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Ok"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Muitos participantes em uma conversa"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Contatos inválidos</item>
+      <item quantity="other">Contatos inválidos</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Falha ao carregar a imagem da câmera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Você: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Rascunho"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Quando uma nova conversa for iniciada, será listada aqui"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"As conversas arquivadas aparecem aqui"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Carregando conversas…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imagem"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clipe de áudio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Vídeo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Cartão de visita"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Desfazer"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Repetir"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Digite o nome ou telefone de um contato para iniciar uma nova mensagem"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloquear"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Desbloquear <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Bloquear <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Você continuará recebendo mensagens deste número, mas não será notificado. Esta conversa será ativada."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Contatos bloqueados"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DESBLOQUEAR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Contatos bloqueados"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Escolher imagem da biblioteca de documentos"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Enviando mensagem"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mensagem enviada"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Dados da rede celular desativados. Verifique suas configurações."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Não é possível enviar mensagens no modo avião"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Não foi possível enviar a mensagem"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mensagem baixada"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Dados da rede celular desativados. Verifique suas configurações."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Não é possível fazer o download de mensagens no modo Avião"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Não foi possível fazer o download da mensagem"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Um"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dois"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Três"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Quatro"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinco"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Seis"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sete"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Oito"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nove"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Não é possível enviar a mensagem com <xliff:g id="CARRIERNAME">%1$s</xliff:g>. Erro: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Não é possível enviar a mensagem com operadora desconhecida. Erro: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Enc: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mensagem não enviada: serviço não ativado na rede"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mensagem não enviada: endereço de destino inválido"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mensagem não enviada: mensagem inválida"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mensagem não enviada: conteúdo não compatível"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mensagem não enviada: mensagem não compatível"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mensagem não enviada: muito grande"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nova mensagem"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Visualizar"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imagem"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Não foi possível encontrar um app adequado"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Remover destinatário"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nova mensagem"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Cancelar"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Editar ponto de acesso"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Não definido"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nome"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Porta MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tipo de APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Excluir APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Novo APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Salvar"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Descartar"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"O campo Nome não pode ficar vazio."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"O APN não pode estar vazio."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"O campo MCC deve ter 3 dígitos."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"O campo MNC deve ter 2 ou 3 dígitos."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Restaurando as configurações APN padrão."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Redefinir para o padrão"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Redefinição das configurações padrão do APN concluída."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Sem título"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Nomes dos pontos de acesso"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Novo APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"As configurações do Nome do ponto de acesso não estão disponíveis para este usuário"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copiar para área de transferência?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiar"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"para <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Gerais"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avançadas"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Configurações gerais"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Configurações avançadas"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Enviar mensagens SMS individuais para todos os destinatários. Só você receberá respostas"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Enviar uma só mensagem MMS para todos os destinatários"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Número desconhecido"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nova mensagem"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nova mensagem."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Seletor de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> selecionado, seletor de SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editar assunto"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Selecione o SIM ou edite o assunto"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Toque e segure para gravar áudio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Iniciar nova conversa"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mensagens"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista de mensagens"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mensagens"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nova mensagem"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversas"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Carregando conversas"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Carregando mensagens"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ver mais conversas"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Ver mais mensagens"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversa excluída"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversa excluída. Toque para mostrar outra conversa do app Mensagens"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Contato bloqueado"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Contato desbloqueado"</string>
+    <string name="db_full" msgid="8459265782521418031">"O espaço de armazenamento está baixo. Alguns dados podem ser perdidos."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Selecionar anexos"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmar seleção"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> selecionados"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Remova um ou mais anexos e tente novamente."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Tente enviar sua mensagem. Se ela não for entregue, remova um ou mais anexos."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Você só pode enviar um vídeo por mensagem. Remova os vídeos adicionais e tente novamente."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Ocorreu uma falha no app Mensagens ao carregar o anexo."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Enviar mesmo assim"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Não foi possível iniciar a conversa"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selecionado"</string>
+</resources>
diff --git a/res/values-ro/arrays.xml b/res/values-ro/arrays.xml
new file mode 100644
index 0000000..dc5e3fe
--- /dev/null
+++ b/res/values-ro/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"fără subiect"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Da"</item>
+    <item msgid="6049132459802288033">"Nu"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Mulțumesc"</item>
+    <item msgid="4881335087096496747">"Sunt de acord"</item>
+    <item msgid="2422296858597420738">"Frumos"</item>
+    <item msgid="4805581752819452687">"Sunt pe drum"</item>
+    <item msgid="4746700499431366214">"OK, revin mai târziu"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
new file mode 100644
index 0000000..2f9c5a7
--- /dev/null
+++ b/res/values-ro/strings.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mesaje"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mesaje"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Selectați conversația"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Setări"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Trimiteți mesajul"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Adăugați un atașament"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ajutor"</string>
+    <string name="welcome" msgid="2857560951820802321">"Bun venit"</string>
+    <string name="skip" msgid="7238879696319945853">"Omiteți"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Înainte &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Înainte"</string>
+    <string name="exit" msgid="1905187380359981199">"Ieșiți"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Setări &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Setări"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mesageria necesită permisiuni la SMS, Telefon și Agendă."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Puteți să schimbați permisiunile din Setări &gt; Aplicații &gt; Mesagerie &gt; Permisiuni."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Puteți să schimbați permisiunile din Setări, Aplicații, Mesagerie, Permisiuni."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Folosite frecvent"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Toată agenda"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Trimiteți la <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Faceți fotografii sau înregistrați videoclipuri"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Alegeți imagini de pe acest dispozitiv"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Înregistrați conținut audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Alegeți o fotografie"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Conținutul media este selectat."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Conținutul media este deselectat."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Ați selectat <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imagine din <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imagine"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Înregistrați conținut audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Trimiteți"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Adineauri"</string>
+    <string name="posted_now" msgid="867560789350406701">"Acum"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> minute</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> de minute</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minut</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> ore</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> de ore</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> oră</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> zile</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> de zile</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> zi</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> săptămâni</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de săptămâni</item>
+      <item quantity="one">o săptămână</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> luni</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de luni</item>
+      <item quantity="one">o lună</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> ani</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de ani</item>
+      <item quantity="one">un an</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mesaje clasa 0"</string>
+    <string name="save" msgid="5081141452059463572">"Salvați"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Spațiul de stocare pe dispozitiv este redus. Mesageria va șterge automat mesaje mai vechi pentru a elibera spațiul."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Spațiu de stocare limitat"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Este posibil ca aplicația Mesagerie să nu trimită și să nu primească mesaje până când nu este disponibil mai mult spațiu pe dispozitiv."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Spațiu de stocare scăzut pentru SMS-uri. Poate fi necesar să ștergeți unele mesaje."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Confirmați numărul de telefon"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Prin acest pas efectuat o singură dată vă asigurați că Mesageria va livra în mod corespunzător mesajele de grup."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Număr de telefon"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Ștergeți toate mesajele multimedia"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Ștergeți mesajele mai vechi de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Ștergeți automat mesajele mai vechi de <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorați"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Ștergeți toate mesajele multimedia?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Ștergeți mesajele mai vechi de <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Ștergeți mesajele mai vechi de <xliff:g id="DURATION">%s</xliff:g> și activați ștergerea automată?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> a spus"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ați spus"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mesaj de la <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Ați trimis un mesaj"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Se trimite..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nu s-a trimis. Atingeți pentru a încerca din nou."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nu s-a trimis. Se încearcă din nou..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Trimiteți din nou sau ștergeți"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Inițiați un apel vocal către serviciile de urgență. Momentan, mesajul text nu a putut fi livrat."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Eroare"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Mesaj MMS nou de descărcat"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Mesaj MMS nou"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Descărcarea nu a reușit"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Atingeți pentru a reîncerca"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Atingeți pentru a descărca"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Descărcați sau ștergeți"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Se descarcă..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mesajul a expirat sau nu este disponibil"</string>
+    <string name="mms_info" msgid="3402311750134118165">"dimensiune: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expirare: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nu se poate trimite. Destinatar nevalid."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Serviciul nu este activat în rețea"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Mesajul nu s-a putut trimite din cauza unei probleme de rețea"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mesajul a expirat sau nu este disponibil."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Fără subiect)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Expeditor necunoscut"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Livrat"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nu s-a putut descărca mesajul <xliff:g id="SUBJECT">%1$s</xliff:g> de la <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Nu s-a putut finaliza operațiunea în baza de date din cauza memoriei reduse"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mesajul nu a fost trimis."</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Unele mesaje nu au fost trimise în Mesagerie"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> (de) mesaje în <xliff:g id="CONVERSATIONS">%d</xliff:g> conversații</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> (de) mesaje în <xliff:g id="CONVERSATIONS">%d</xliff:g> de conversații</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> (de) mesaje într-o conversație</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mesajul nu a fost descărcat"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Unele mesaje nu au fost descărcate în Mesagerie"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> (de) mesaje în <xliff:g id="CONVERSATIONS">%d</xliff:g> conversații</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> (de) mesaje în <xliff:g id="CONVERSATIONS">%d</xliff:g> de conversații</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> (de) mesaje într-o conversație</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mesajul către <xliff:g id="NUMBER">%1$s</xliff:g> nu a fost trimis"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Inițiați un apel vocal către serviciile de urgență. Momentan, mesajul text către <xliff:g id="NUMBER">%1$s</xliff:g> nu a putut fi livrat."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> mesaje noi</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> de mesaje noi</item>
+      <item quantity="one">Mesaj nou</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Începeți"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Camera foto nu este disponibilă"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Camera foto nu este disponibilă"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Filmarea video nu este disponibilă"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nu se poate salva fișierul multimedia"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nu se poate fotografia"</string>
+    <string name="back" msgid="1477626055115561645">"Înapoi"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arhivate"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Ștergeți"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arhivați"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Dezarhivați"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Dezactivați notificările"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Activați notificările"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Adăugați o persoană"</string>
+    <string name="action_download" msgid="7786338136368564146">"Descărcați"</string>
+    <string name="action_send" msgid="377635240181672039">"Trimiteți"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Ștergeți"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Ștergeți acest mesaj?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Această acțiune nu poate fi anulată."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Ștergeți"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="few">Ștergeți aceste conversații?</item>
+      <item quantity="other">Ștergeți aceste conversații?</item>
+      <item quantity="one">Ștergeți această conversație?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Ștergeți"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Anulați"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Către"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Selectați mai multe imagini"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Confirmați selecția"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Mesajul audio nu poate fi înregistrat. Încercați din nou."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Mesajul audio nu poate fi redat. Încercați din nou."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Mesajul audio nu a putut fi salvat. Încercați din nou."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Apăsați lung"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Imagine"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip audio"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videoclip"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Carte de vizită"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Descărcați"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Răspundeți prin SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Răsp. prin MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Răspundeți"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> participanți</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> de participanți</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> participant</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Eu"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Persoana de contact este blocată și arhivată"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Persoană de contact deblocată și dezarhivată"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> arhivate"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> dezarhivate"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Notificări dezactivate"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Notificări activate"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Gata. Atingeți din nou Trimiteți."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mesageria a fost setată ca aplicație prestabilită pentru SMS-uri."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="few">Eliminați atașamentele</item>
+      <item quantity="other">Eliminați atașamentele</item>
+      <item quantity="one">Eliminați atașamentul</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Atașament audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Redați atașamentul audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pauză"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mesaj de la <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mesaj neprimit de la <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mesaj de la <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mesaj netrimis către <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Se trimite mesajul către <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mesaj netrimis către <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mesaj către <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mesaj neprimit de la <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mesaj de la <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mesaj netrimis către <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Se trimite mesajul către <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mesaj netrimis către <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mesaj către <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mesaj nelivrat. Atingeți pentru a reîncerca."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Conversație cu <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Ștergeți subiectul"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Înregistrați conținut video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Fotografiați o imagine statică"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Fotografiaţi"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Începeți să înregistrați conținut video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Comutați la camera pe ecran complet"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Comutați între camera foto frontală și camera foto posterioară"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Opriți înregistrarea și atașați videoclipul"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Opriți înregistrarea video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotografii din Mesagerie"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografii salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> de fotografii salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotografie salvată în albumul „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> videoclipuri salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> de videoclipuri salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> videoclip salvat în albumul „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> atașamente salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> de atașamente salvate în albumul „<xliff:g id="ALBUMNAME_3">%s</xliff:g>”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> atașament salvat în albumul „<xliff:g id="ALBUMNAME_1">%s</xliff:g>”</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> atașamente salvate în „Descărcări”</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> de atașamente salvate în „Descărcări”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> atașament salvat în „Descărcări”</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> atașamente au fost salvate</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> de atașamente au fost salvate</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> atașament a fost salvat</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="few">Nu s-au putut salva <xliff:g id="QUANTITY_1">%d</xliff:g> atașamente</item>
+      <item quantity="other">Nu s-au putut salva <xliff:g id="QUANTITY_1">%d</xliff:g> de atașamente</item>
+      <item quantity="one">Nu s-a putut salva <xliff:g id="QUANTITY_0">%d</xliff:g> atașament</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Atașamentul MMS a fost salvat"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Setări"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arhivate"</string>
+    <string name="action_close" msgid="1840519376200478419">"Închideți"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avansate"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Remedierea erorilor"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Notificări"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Sunet"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Silențios"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrații"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blocat"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Rapoarte de trimitere a SMS-urilor"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Solicitați un raport de expediere pentru fiecare mesaj SMS trimis"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Preluare automată"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Preia automat mesajele MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Preluare automată în roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Preia automat mesajele MMS în roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mesagerie de grup"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Utilizați serviciul MMS pentru a trimite un singur mesaj, atunci când există mai mulți destinatari"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplicație SMS prestabilită"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplicație SMS prestabilită"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Numărul dvs. de telefon"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Necunoscut"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sunete pentru mesaje trimise"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Copiați mesajele SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Copiați datele brute din mesajele SMS primite în fișierul de stocare externă"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Copiați mesajele MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Copiați datele brute din mesajele MMS primite în fișierul de stocare externă"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Alerte wireless"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opţiuni mesaj"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Copiați textul"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Vedeți detaliile"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Ștergeți"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Redirecționați"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detalii mesaj"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tip: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mesaj text"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mesaj multimedia"</string>
+    <string name="from_label" msgid="1947831848146564875">"De la: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Către: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Trimis: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Primit: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subiect: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Dimensiune: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritate: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Ridicată"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normală"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Scăzută"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Adresa expeditorului este ascunsă"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Nu se poate trimite mesajul în timp ce se încarcă atașamente."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nu se poate încărca atașamentul. Încercați din nou."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Rețeaua nu este gata. Încercați din nou."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Ștergeți textul"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Comutați între introducere de text și numere"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Adăugați mai mulți participanți"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Confirmați participanții"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Începeți o conversație nouă"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Selectați acest articol"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Redați videoclipul"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Persoane și opțiuni"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Remediați erorile"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Persoane și opțiuni"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Generale"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Persoane participante la conversație"</string>
+    <string name="action_call" msgid="6596167921517350362">"Efectuați un apel"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Trimiteți mesajul"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Trimiteți mesajul&lt;br/&gt;&lt;small&gt;de pe cardul <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="few">Trimiteți fotografiile</item>
+      <item quantity="other">Trimiteți fotografiile</item>
+      <item quantity="one">Trimiteți fotografia</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="few">Trimiteți fișierele audio</item>
+      <item quantity="other">Trimiteți fișierele audio</item>
+      <item quantity="one">Trimiteți fișierul audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="few">Trimiteți videoclipurile</item>
+      <item quantity="other">Trimiteți videoclipurile</item>
+      <item quantity="one">Trimiteți videoclipul</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="few">Trimiteți cărțile de vizită</item>
+      <item quantity="other">Trimiteți cărțile de vizită</item>
+      <item quantity="one">Trimiteți cartea de vizită</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="few">Trimiteți atașamentele</item>
+      <item quantity="other">Trimiteți atașamentele</item>
+      <item quantity="one">Trimiteți atașamentul</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> atașamente gata de trimis</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> de atașamente gata de trimis</item>
+      <item quantity="one">Un atașament gata de trimis</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Trimiteți feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Vedeți în Magazinul Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informații despre versiune"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versiunea %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licențe open source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Notificări"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"S-a atins limita pentru atașamente"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Atașamentul nu a putut fi încărcat."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Adăugați în Agendă?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Adăugați o persoană"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subiect"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subiect: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Se încarcă cartea de vizită"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Cartea de vizită nu a putut fi încărcată"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Vedeți cartea de vizită"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> persoane de contact</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> de persoane de contact</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> persoană de contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Cărți de vizită"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Ziua de naștere"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Note"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Redirecționați mesajul"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Răspundeți"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-urile sunt dezactivate"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Pentru a trimite mesaje, setați Mesageria ca aplicație prestabilită pentru SMS-uri"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Setați Mesageria ca aplicație prestabilită pentru SMS-uri"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Modificați"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Pentru a primi mesaje, setați Mesageria ca aplicație prestabilită pentru SMS-uri"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Pentru trimiterea mesajelor SMS nu este selectat niciun card SIM preferat"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Această aplicație nu este acceptată de proprietarul dispozitivului."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Prea mulți participanți la o conversație"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="few">Persoane de contact nevalide</item>
+      <item quantity="other">Persoane de contact nevalide</item>
+      <item quantity="one">Persoană de contact nevalidă</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nu s-a putut încărca imaginea de la camera foto"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Dvs.: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Mesaj nefinalizat"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Când începeți o nouă conversație, o veți vedea aici"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Conversațiile arhivate apar aici"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Conversațiile sunt în curs de încărcare..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Imagine"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip audio"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Videoclip"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Carte de vizită"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Anulați"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Reîncercați"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Introduceți numele unei persoane de contact sau un număr de telefon pentru a începe un nou mesaj"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blocați"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blocați <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Deblocați-l(o) pe <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blocați <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Veți primi, în continuare, mesaje de la acest număr, dar nu veți mai primi notificări. Această conversație va fi arhivată."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Persoane din Agendă blocate"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"DEBLOCAȚI"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Persoane din Agendă blocate"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Alegeți imaginea din biblioteca de documente"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Se trimite mesajul"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mesaj trimis"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Datele mobile sunt dezactivate. Verificați setările."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Nu se pot trimite mesaje în modul Avion"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Mesajul nu a putut fi trimis"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mesaj descărcat"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Datele mobile sunt dezactivate. Verificați setările."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Nu se pot descărca mesaje în modul Avion"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Mesajul nu a putut fi descărcat"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Unu"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Doi"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Trei"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Patru"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Cinci"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Șase"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Șapte"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Opt"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nouă"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Nu se poate trimite mesaj prin <xliff:g id="CARRIERNAME">%1$s</xliff:g>, eroare <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Nu se poate trimite mesaj printr-un operator necunoscut, eroare <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Redir.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mesajul nu a fost trimis: serviciul nu este activat în rețea"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mesajul nu a fost trimis: adresă de destinație nevalidă"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mesajul nu a fost trimis: mesaj nevalid"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mesajul nu a fost trimis: conținut neacceptat"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mesajul nu a fost trimis: mesaj neacceptat"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mesajul nu a fost trimis: mesaj prea mare"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mesaj nou"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Afișați"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imagine"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nu am găsit o aplicație adecvată"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Eliminați un destinatar"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mesaj nou"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Anulați"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Modificaţi punctul de acces"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nesetat"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nume"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Tip APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Ștergeți APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN nou"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Salvați"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Renunțați"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Câmpul Nume trebuie completat."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN-ul trebuie completat."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Câmpul MCC trebuie să conțină 3 cifre."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Câmpul MNC trebuie să conțină 2 sau 3 cifre."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Se restabilesc setările APN prestabilite."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Resetați la valorile prestabilite"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Resetarea setărilor APN prestabilite a fost finalizată."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Fără titlu"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Numele punctelor de acces"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-uri"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN nou"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Setările pentru „Nume puncte de acces” nu sunt disponibile pentru acest utilizator"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Copiați în clipboard?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Copiați"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"pe cardul <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Generale"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avansate"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Setări generale"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Setări avansate"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Cartela SIM „<xliff:g id="SIM_NAME">%s</xliff:g>”"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Trimiteți mesaje SMS individuale către toți destinatarii. Numai dvs. veți primi răspunsurile."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Trimiteți un singur mesaj MMS către toți destinatarii"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Număr necunoscut"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mesaj nou"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mesaj nou."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Selector de SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> a fost selectat, selector de SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Editați subiectul"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Selectați cardul SIM sau editați subiectul"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Atingeți lung pentru a înregistra conținutul audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Începeți o conversație nouă"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mesagerie"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Listă Mesagerie"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mesagerie"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mesaj nou"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista de conversații"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Se încarcă conversațiile"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Se încarcă mesajele"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Vedeți mai multe conversații"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Vedeți mai multe mesaje"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Conversație ștearsă"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Conversația a fost ștearsă. Atingeți pentru a afișa altă conversație din Mesagerie"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blocat"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Deblocat"</string>
+    <string name="db_full" msgid="8459265782521418031">"Spațiul de stocare este scăzut. Se pot pierde unele date."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Selectați atașamentele"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Confirmați selecția"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Ați selectat <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Eliminați unul sau mai multe atașamente și încercați din nou."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Puteți încerca să trimiteți mesajul, însă dacă nu eliminați unul sau mai multe atașamente, este posibil ca acesta să nu fie livrat."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Puteți trimite doar un videoclip per mesaj. Eliminați videoclipurile suplimentare și încercați din nou."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mesageria nu a putut încărca atașamentul."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Trimiteți oricum"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Conversația nu a putut fi începută"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> selectat"</string>
+</resources>
diff --git a/res/values-ru/arrays.xml b/res/values-ru/arrays.xml
new file mode 100644
index 0000000..8af4db2
--- /dev/null
+++ b/res/values-ru/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"без темы"</item>
+    <item msgid="272485471009191934">"без темы"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Да"</item>
+    <item msgid="6049132459802288033">"Нет"</item>
+    <item msgid="3084376867445867895">"ОК"</item>
+    <item msgid="3155097332660174689">"Ха-ха"</item>
+    <item msgid="2611328818571146775">"Спасибо!"</item>
+    <item msgid="4881335087096496747">"Хорошо"</item>
+    <item msgid="2422296858597420738">"Отлично"</item>
+    <item msgid="4805581752819452687">"Скоро буду"</item>
+    <item msgid="4746700499431366214">"ОК, отвечу позже"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
new file mode 100644
index 0000000..132f8c4
--- /dev/null
+++ b/res/values-ru/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS/MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS/MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Выберите чат"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Настройки"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Отправить сообщение"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Прикрепить файл"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Справка"</string>
+    <string name="welcome" msgid="2857560951820802321">"Добро пожаловать!"</string>
+    <string name="skip" msgid="7238879696319945853">"Пропустить"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Далее &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Далее"</string>
+    <string name="exit" msgid="1905187380359981199">"Закрыть"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Настройки &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Настройки"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Приложению SMS/MMS требуются разрешения категорий SMS, \"Телефон\" и \"Контакты\"."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Чтобы изменить разрешения, нажмите \"Настройки &gt; Приложения &gt; SMS/MMS &gt; Разрешения\"."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Чтобы изменить разрешения, нажмите \"Настройки &gt; Приложения &gt; SMS/MMS &gt; Разрешения\"."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Частые"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Все контакты"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Отправить на номер <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Снять фото или видео"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Выбрать изображения на устройстве"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Записать аудио"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Выбрать фотографию"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медиафайл выбран"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Выбор отменен"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Выбрано: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"изображение <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"изображение"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Запись аудио"</string>
+    <string name="action_share" msgid="2143483844803153871">"Поделиться"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Только что"</string>
+    <string name="posted_now" msgid="867560789350406701">"Только что"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> минута</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> минуты</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> минут</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> минуты</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> час</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> часа</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> часов</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> часа</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> день</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> дня</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> дней</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> дня</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> неделя</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> недели</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> недель</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> недели</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> месяц</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> месяца</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> месяцев</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> месяца</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> год</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> года</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> лет</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> года</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Сообщение класса 0"</string>
+    <string name="save" msgid="5081141452059463572">"Сохранить"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Свободное место в памяти устройства заканчивается. Чтобы освободить его, приложение удалит старые сообщения."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Недостаточно памяти"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Недостаточно свободного места, чтобы отправлять и получать сообщения в SMS/MMS."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Для хранения SMS осталось мало места. Удалите старые сообщения."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Подтверждение номера телефона"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Номер требуется для отправки групповых сообщений в SMS/MMS. Его нужно ввести только один раз."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Номер телефона"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Удалить сообщения с медиафайлами"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Удалить сообщения старше <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Автоматически удалять сообщения старше <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Игнорировать"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Удалить сообщения с медиафайлами?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Удалить сообщения старше <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Удалить сообщения старше <xliff:g id="DURATION">%s</xliff:g> и включить автоматическое удаление?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> пишет:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Вы сказали:"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Сообщение от пользователя <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Вы отправили сообщение"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Отправка…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Сообщение не отправлено. Нажмите, чтобы повторить попытку."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Сообщение не отправлено. Повторная попытка…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Переслать или удалить"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Не удалось доставить сообщение. Чтобы связаться с экстренными службами, позвоните по этому номеру."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Не удалось отправить"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Скачайте новое MMS-сообщение"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Новое сообщение MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Не удалось скачать"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Нажмите, чтобы повторить попытку"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Нажмите, чтобы скачать"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Скачать или удалить"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Скачивание…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Срок действия сообщения истек, или оно недоступно"</string>
+    <string name="mms_info" msgid="3402311750134118165">"размер: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, срок действия: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Не удалось отправить сообщение: укажите действительного получателя."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Услуга не активирована в сети"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Не удалось отправить сообщение из-за ошибки сети"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Срок действия сообщения истек, или оно недоступно"</string>
+    <string name="no_subject" msgid="5587715902648568767">"Без темы"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Неизвестный отправитель"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Доставлено"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Не удалось загрузить сообщение \"<xliff:g id="SUBJECT">%1$s</xliff:g>\" от пользователя <xliff:g id="FROM">%2$s</xliff:g>"</string>
+    <string name="low_memory" msgid="5300743415198486619">"Не удалось выполнить операцию с базой данных: недостаточно памяти"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Сообщение не отправлено"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Некоторые сообщения в SMS/MMS не отправлены"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="few">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="many">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Не удалось загрузить сообщение"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Некоторые сообщения в SMS/MMS не скачаны"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="few">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="many">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other">Сообщений: <xliff:g id="MESSAGES_1">%d</xliff:g>, чатов: <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"SMS на номер <xliff:g id="NUMBER">%1$s</xliff:g> не отправлено"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Не удалось доставить сообщение на номер <xliff:g id="NUMBER">%1$s</xliff:g>. Позвоните в экстренную службу по телефону."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> новое сообщение</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> новых сообщения</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> новых сообщений</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> нового сообщения</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Начать беседу"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камера недоступна"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камера недоступна"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Видеозапись недоступна"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Не удалось сохранить"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Не удалось сфотографировать"</string>
+    <string name="back" msgid="1477626055115561645">"Назад"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архив"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Удалить"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архив"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Вернуть из архива"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Отключить оповещения"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Включить оповещения"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Добавить контакт"</string>
+    <string name="action_download" msgid="7786338136368564146">"Скачать"</string>
+    <string name="action_send" msgid="377635240181672039">"Отправить"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Удалить"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Удалить сообщение?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Это действие нельзя будет отменить."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Удалить"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Удалить эти чаты?</item>
+      <item quantity="few">Удалить эти чаты?</item>
+      <item quantity="many">Удалить эти чаты?</item>
+      <item quantity="other">Удалить эти чаты?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Удалить"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Отмена"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Кому"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Выбрать несколько изображений"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Подтверждение выбора"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Не удалось записать. Повторите попытку."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Не удалось воспроизвести. Повторите попытку."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Не удалось сохранить. Повторите попытку."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Нажмите и удерживайте"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Изображение"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудиоклип"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Карточка контакта"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Скачать"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Отправить SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Ответить MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Ответить"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> участник</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> участника</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> участников</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> участника</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Вы"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Контакт заблокирован, переписка помещена в архив"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Контакт разблокирован, чат возвращен из архива"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Добавлено в архив: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Возвращено из архива: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Уведомления отключены"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Уведомления включены"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Все готово. Нажмите \"Отправить\" ещё раз."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Вы назначили SMS/MMS приложением для SMS по умолчанию"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Убрать прикрепленные файлы</item>
+      <item quantity="few">Убрать прикрепленные файлы</item>
+      <item quantity="many">Убрать прикрепленные файлы</item>
+      <item quantity="other">Убрать прикрепленные файлы</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудиофайл"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Воспроизвести прикрепленный аудиофайл"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Пауза"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Сообщение от пользователя <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Не удалось отправить сообщение от пользователя <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Сообщение от пользователя <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Неотправленное сообщение для пользователя <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Отправляется сообщение для пользователя <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Не удалось отправить сообщение для пользователя <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Сообщение для пользователя <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Не удалось отправить сообщение от пользователя <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Сообщение от пользователя <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Неотправленное сообщение для группы <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Отправляется сообщение для группы <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Не удалось отправить сообщение для группы <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Сообщение для группы <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Время: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Не удалось отправить сообщение. Нажмите, чтобы повторить попытку."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Чат с пользователями <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Удалить тему."</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Снять видео"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Сделать стоп-кадр"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Сделать снимок"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Начать запись видео"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Перейти в полноэкранный режим"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Переключение между основной и фронтальной камерами"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Остановить запись и прикрепить видео"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Остановить запись видео"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Фото из SMS/MMS"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> фото сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> фото сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> фото сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> фото сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> видео сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> видео сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> видео сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> видео сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> прикрепленный файл сохранен в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> прикрепленных файла сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> прикрепленных файлов сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> прикрепленных файла сохранено в альбоме \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленный файл сохранен в Загрузках</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файла сохранено в Загрузках</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файлов сохранено в Загрузках</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файла сохранено в Загрузках</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленный файл сохранен</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файла сохранено</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файлов сохранено</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленного файла сохранено</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Не удалось сохранить <xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленный файл</item>
+      <item quantity="few">Не удалось сохранить <xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файла</item>
+      <item quantity="many">Не удалось сохранить <xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленных файлов</item>
+      <item quantity="other">Не удалось сохранить <xliff:g id="QUANTITY_1">%d</xliff:g> прикрепленного файла</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Сохраненный файл из MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Настройки"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архив"</string>
+    <string name="action_close" msgid="1840519376200478419">"Закрыть"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Дополнительные настройки"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Выполнить отладку"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Уведомления"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Звуковой сигнал"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Без звука"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Вибросигнал"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Заблокировано"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Отчеты о доставке SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Запрашивать отчет о доставке для всех отправляемых SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Автополучение"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Автоматически загружать MMS-сообщения"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Автополучение в роуминге"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Автоматически загружать MMS-сообщения в роуминге"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Групповые сообщения"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Использовать MMS для отправки одного сообщения нескольким получателям"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Приложение для обмена SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Приложение для обмена SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Ваш номер телефона"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Неизвестный"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Сигнал исходящего сообщения"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Передача SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Передать необработанные данные полученных SMS во внешнее хранилище"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Передача MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Передать необработанные данные полученных MMS во внешнее хранилище"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Оповещение населения"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Параметры сообщения"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Копировать текст"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Сведения"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Удалить"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Переслать"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Сведения о сообщении"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Тип: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"MMS"</string>
+    <string name="from_label" msgid="1947831848146564875">"От: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Кому: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Отправлено: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Получено: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Тема: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Размер: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Приоритет: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-карта: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Высокий"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Обычный"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Низкий"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-карта <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Адрес отправителя скрыт"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Не удается отправить сообщение. Дождитесь завершения загрузки прикрепленных файлов."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Не удалось загрузить прикрепленный файл. Повторите попытку."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Сеть не готова. Повторите попытку."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Удалить текст"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Переключение между вводом букв и цифр"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Добавить участников"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Подтвердить участников"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Начать чат"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Выбрать этот вариант"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Воспроизвести видео"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Участники и параметры"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Выполнить отладку"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Участники и параметры"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Общие"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Участники чата"</string>
+    <string name="action_call" msgid="6596167921517350362">"Позвонить"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Отправить сообщение"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Отправить сообщение&lt;br/&gt;&lt;small&gt;с <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Отправить фото</item>
+      <item quantity="few">Отправить фото</item>
+      <item quantity="many">Отправить фото</item>
+      <item quantity="other">Отправить фото</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Отправить аудио</item>
+      <item quantity="few">Отправить аудио</item>
+      <item quantity="many">Отправить аудио</item>
+      <item quantity="other">Отправить аудио</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Отправить видео</item>
+      <item quantity="few">Отправить видео</item>
+      <item quantity="many">Отправить видео</item>
+      <item quantity="other">Отправить видео</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Отправить карточки контактов</item>
+      <item quantity="few">Отправить карточки контактов</item>
+      <item quantity="many">Отправить карточки контактов</item>
+      <item quantity="other">Отправить карточки контактов</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Отправить прикрепленные файлы</item>
+      <item quantity="few">Отправить прикрепленные файлы</item>
+      <item quantity="many">Отправить прикрепленные файлы</item>
+      <item quantity="other">Отправить прикрепленные файлы</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прикрепленный файл готов к отправке</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прикрепленных файла готовы к отправке</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прикрепленных файлов готовы к отправке</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прикрепленного файла готовы к отправке</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Отправить отзыв"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Искать в Play Маркете"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Версия"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Версия %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Лицензии открытого ПО"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Уведомления"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Прикреплено максимальное количество файлов"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Не удалось загрузить прикрепленный файл"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Добавить в контакты?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Добавить"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Тема"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Тема: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Загрузка карточки контакта…"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Не удалось загрузить карточку контакта"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Посмотреть карточку контакта"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> контакт</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> контакта</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> контактов</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контакта</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Карточки контактов"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"День рождения"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Примечания"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Пересылка сообщения"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Ответ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"и ещё 1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"и ещё %d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-служба отключена"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Чтобы отправлять сообщения, назначьте SMS/MMS приложением для SMS по умолчанию"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Назначьте SMS/MMS приложением для SMS по умолчанию"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Изменить"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Чтобы получать сообщения, сделайте SMS/MMS приложением для SMS по умолчанию"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Не выбрана SIM-карта для отправки SMS-сообщений"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Владелец устройства запретил использовать это приложение."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ОК"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Слишком много участников"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Контакты не найдены</item>
+      <item quantity="few">Контакты не найдены</item>
+      <item quantity="many">Контакты не найдены</item>
+      <item quantity="other">Контакты не найдены</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Не удалось загрузить изображение с камеры"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Вы: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Черновик"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Когда вы начнете переписку, она появится здесь"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Здесь появятся архивированные чаты"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Загрузка цепочек писем…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Изображение"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудиоклип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Карточка контакта"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Отменить"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Повторить"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Введите имя пользователя или номер телефона"</string>
+    <string name="action_block" msgid="9032076625645190136">"Заблокировать"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Заблокировать пользователя <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Разблокировать пользователя <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Заблокировать <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Вы по-прежнему будете получать сообщения с этого номера, но не увидите оповещений о них. Этот чат будет архивирован."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Заблокированные контакты"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"РАЗБЛОКИРОВАТЬ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Заблокированные контакты"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Выбрать изображение в библиотеке документов"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Отправка сообщения"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Сообщение отправлено"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Передача данных по мобильной сети отключена в настройках устройства"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"В режиме полета нельзя отправлять сообщения"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Не удалось отправить сообщение"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Сообщение скачано"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Передача данных по мобильной сети отключена в настройках устройства"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Невозможно скачать сообщения в режиме полета"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Невозможно скачать сообщение"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Ноль"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Один"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Два"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Три"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Четыре"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Пять"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Шесть"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Семь"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Восемь"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Девять"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Не удалось отправить сообщение с помощью оператора \"<xliff:g id="CARRIERNAME">%1$s</xliff:g>\" (ошибка <xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Не удалось отправить сообщение с помощью неизвестного оператора (ошибка <xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Сообщение не отправлено: услуга не активирована в сети"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Сообщение не отправлено: недопустимый адрес получателя"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Ошибка: недопустимое сообщение"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Сообщение не отправлено, поскольку содержит неподдерживаемый контент"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Ошибка: неподдерживаемое сообщение"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Не удалось отправить сообщение из-за его размера"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Новое сообщение"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Посмотреть"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Изображение"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Подходящее приложение не найдено"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Удалить получателя."</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Новое сообщение"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Отмена"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Настройки точки доступа"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Не настроено"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Название"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Точка доступа"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Прокси-сервер MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Порт MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Тип точки доступа"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Удалить точку доступа"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Создать точку доступа"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Сохранить"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Отменить"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Укажите название."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Укажите точку доступа."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Поле MCC должно содержать 3 цифры."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Поле MNC должно содержать 2 или 3 цифры."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Восстановление настроек по умолчанию…"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Восстановить настройки по умолчанию"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Настройки по умолчанию восстановлены"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Без названия"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Точки доступа"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Точки доступа"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Создать точку доступа"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Этот пользователь не может изменять настройки точки доступа"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Скопировать в буфер обмена?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Да"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"На <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Общие"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Дополнительные настройки"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Общие настройки"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Расширенные настройки"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM-карта \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Отправлять всем получателям отдельные SMS-сообщения. Ответы на них будут отправлены только вам."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Отправлять всем получателям одно MMS-сообщение"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Неизвестный номер"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Новое сообщение"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Новое сообщение"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Выбрать SIM-карту"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Выбрана SIM-карта <xliff:g id="SIM_0">%1$s</xliff:g>"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Изменить тему"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Выбрать SIM-карту или изменить тему"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Нажмите и удерживайте, чтобы записать аудио"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Начать чат"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS/MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Чаты из SMS/MMS"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS/MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Новое сообщение"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Список чатов"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Загрузка чатов"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Загрузка сообщений…"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Другие чаты"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Другие сообщения"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Чат удален"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Чат удален. Нажмите здесь, чтобы перейти к другому."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Заблокирован"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Разблокирован"</string>
+    <string name="db_full" msgid="8459265782521418031">"Заканчивается место в памяти устройства. Некоторые данные могут быть потеряны."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Выбор прикрепленных файлов"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Подтверждение выбора"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Выбрано: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Удалите один или несколько прикрепленных файлов и повторите попытку."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Если вы не удалите один или несколько прикрепленных файлов, сообщение может не дойти до адресата."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Вы можете отправлять по одному видео за раз. Удалите лишние ролики и повторите попытку."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Не удалось загрузить прикрепленные файлы."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Отправить"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Не удается начать разговор"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"SIM-карта выбрана: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-si/arrays.xml b/res/values-si/arrays.xml
new file mode 100644
index 0000000..89f6c6c
--- /dev/null
+++ b/res/values-si/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"කාරණාවක් නොමැත"</item>
+    <item msgid="272485471009191934">"කාරණාවක් නොමැත"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ඔව්"</item>
+    <item msgid="6049132459802288033">"නැත"</item>
+    <item msgid="3084376867445867895">"හරි"</item>
+    <item msgid="3155097332660174689">"හා හා"</item>
+    <item msgid="2611328818571146775">"ස්තූතියි"</item>
+    <item msgid="4881335087096496747">"මම එකඟයි"</item>
+    <item msgid="2422296858597420738">"නයිස්"</item>
+    <item msgid="4805581752819452687">"මම එන ගමන්"</item>
+    <item msgid="4746700499431366214">"හරි, මම ඔබ වෙත පසුව පැමිණෙන්නම්"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
new file mode 100644
index 0000000..80c7cd7
--- /dev/null
+++ b/res/values-si/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"පණිවිඩ යැවීම"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"පණිවිඩ යැවීම"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"සංවාදය තෝරන්න"</string>
+    <string name="action_settings" msgid="1329008122345201684">"සැකසීම්"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"පණිවිඩය යවන්න"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ඇමිණුමක් එක් කරන්න"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"උදවු"</string>
+    <string name="welcome" msgid="2857560951820802321">"සාදරයෙන් පිළිගනිමු"</string>
+    <string name="skip" msgid="7238879696319945853">"මඟ හරින්න"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ඊළඟ &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"මීළඟ"</string>
+    <string name="exit" msgid="1905187380359981199">"පිටවන්න"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"සැකසීම් &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"සැකසීම්"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"පණිවිඩ යැවීමට SMS, Phone සහ සම්බන්ධතා වෙත අවසර අවශ්‍යයි."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"ඔබට සැකසීම් &gt; යෙදුම් &gt; පණිවිඩ යැවීම &gt; අවසරවල අවසර වෙනස් කළ හැකිය."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"ඔබට සැකසීම්, යෙදුම්, පණිවිඩ යැවීම, අවසරවල අවසර වෙනස් කළ හැකිය."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"නිතරම"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"සියලුම සම්බන්ධතා"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> වෙත යවන්න"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"පින්තූර හෝ වීඩියෝ ලබාගන්න"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"මෙම උපාංගයෙන් පින්තූර තෝරන්න"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ශ්‍රව්‍ය තැටිගත කරන්න"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ඡායාරූපය තෝරන්න"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"මාධ්‍යය තෝරාගෙන තිබේ."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"මාධ්‍යය තෝරාගෙන නොතිබේ."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ක් තෝරාගන්නා ලදි"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"රූපය <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"රූපය"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ශ්‍රව්‍ය තැටිගත කරන්න"</string>
+    <string name="action_share" msgid="2143483844803153871">"බෙදාගන්න"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"මේ දැන්"</string>
+    <string name="posted_now" msgid="867560789350406701">"දැන්"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one">මිනිත්තු <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="other">මිනිත්තු <xliff:g id="COUNT_1">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one">පැය <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="other">පැය <xliff:g id="COUNT_1">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one">දින <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="other">දින <xliff:g id="COUNT_1">%d</xliff:g></item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one">සති <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="other">සති <xliff:g id="COUNT">%d</xliff:g></item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one">මාස <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="other">මාස <xliff:g id="COUNT">%d</xliff:g></item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one">අවුරුදු <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="other">අවුරුදු <xliff:g id="COUNT">%d</xliff:g></item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0 පන්තියේ පණිවිඩය"</string>
+    <string name="save" msgid="5081141452059463572">"සුරකින්න"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"උපාංගයේ ඉඩ අඩුය. පණිවිඩකරණය ඉඩ හිස් කර ගැනීමට පැරණි පණිවිඩ ස්වයංක්‍රියව මකනු ඇත."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"ආචයනය ඉඩ ප්‍රමාණය අඩු වී ඇත"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"පණිවිඩ යැවීම ඔබේ උපාංගය මත වැඩි ඉඩක් ලබාගත හැකිවන තෙක් පණිවිඩ නොයැවිය හැකිය නැතහොත් ලබා නොගත හැකිය."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"අඩු SMS ආචයනය. ඇතැම් විට ඔබට පණිවිඩ මැකීමට සිදුවේ."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ඔබගේ දුරකථන අංකය තහවුරු කරන්න"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"පණිවිඩ යැවීම ඔබේ සමූහ පණිවිඩ නිසි ලෙස බෙදා හරිනු ඇති බවට මෙම එක්-වරක් පියවර තහවුරු කරනු අැත."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"දුරකථන අංකය"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"මාධ්‍ය සමඟ ඇති සියලුම පණිවිඩ මකන්න"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> වඩා පැරණි පණිවිඩ මකන්න"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> වඩා පැරණි පණිවිඩ ස්වයංක්‍රීයව මකන්න"</string>
+    <string name="ignore" msgid="7063392681130898793">"නොසලකා හරින්න"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"මාධ්‍ය සමඟ ඇති සියලුම පණිවිඩ මකන්නද?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> වඩා පැරණි පණිවිඩ මකන්නද?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> වඩා පැරණි පණිවිඩ ස්වයංක්‍රීයව මැකීම සක්‍රිය කරන්නද?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> පැවසුවා"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"ඔබ පැවසුවා"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> වෙතින් පණිවිඩය:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"ඔබ පණිවිඩයක් යැවුවා"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"යවමින්..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"යැව්වේ නැත. නැවත උත්සාහ කිරීමට ස්පර්ශ කරන්න."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"යැව්වේ නැත. නැවත උත්සාහ කරමින්…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"නැවත යවන්න නැතහොත් මකන්න"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"කරුණාකර හදිසි සේවාවන් සඳහා හඬ ඇමතුමක් ගන්න. මේ මොහොතේ ඔබගේ පෙළ පණිවිඩය යැවීමට නොහැක."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"අසාර්ථක වුණි"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"බාගැනීමට අලුත් MMS පණිවුඩයකි"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"අලුත් MMS පණිවුඩය"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"බාගැනීමට නොහැකි විය"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"නැවත උත්සාහයට ස්පර්ශ කරන්න"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"බාගැනීමට ස්පර්ශ කරන්න"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"බාගතකරන්න නැතහොත් මකන්න"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"බාගනිමින්…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"පණිවිඩය කල් ඉකුත්වී ඇත හෝ දැනට නොමැත."</string>
+    <string name="mms_info" msgid="3402311750134118165">"ප්‍රමාණය: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, කල් ඉකුත් වීම: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"යැවිය නොහැක. ලබන්නා වලංගු නැත."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ජාලය තුළ සේවාව සක්‍රිය කර නොමැත"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ජාලයේ ගැටළුවක් හේතුවෙන් යැවීම කළ නොහැක"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"පණිවිඩය කල් ඉකුත්වී ඇත හෝ දැනට නොමැත."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(කාරණාවක් නොමැත)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"නොහඳුනන යවන්නෙක්"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"භාර දුණි"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="SUBJECT">%1$s</xliff:g> පණිවිඩය <xliff:g id="FROM">%2$s</xliff:g> වෙතින් බාගත නොහැකි විය."</string>
+    <string name="low_memory" msgid="5300743415198486619">"අඩු මතකය නිසා දත්ත සමුදාය මත මෙහෙයුම සම්පූර්ණ කළ නොහැකි විය"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"පණිවිඩය යැවුවේ නැත"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"සමහර පණිවිඩ පණිවිඩ යැවීමේදී නොයවන ලදී"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one">සංවාද <xliff:g id="MESSAGES_1">%d</xliff:g> ක් තුළ පණිවිඩ <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other">සංවාද <xliff:g id="MESSAGES_1">%d</xliff:g> ක් තුළ පණිවිඩ <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"පණිවිඩය බානොගන්නා ලදී"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"සමහර පණිවිඩ පණිවිඩ යැවීමේදී බා නොගන්නා ලදී"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one">සංවාද <xliff:g id="MESSAGES_1">%d</xliff:g> ක් තුළ පණිවිඩ <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other">සංවාද <xliff:g id="MESSAGES_1">%d</xliff:g> ක් තුළ පණිවිඩ <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> වෙත පණිවිඩය ගියේ නැත"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"කරුණාකර හදිසි සේවාවන් සඳහා හඬ ඇමතුමක් ගන්න. මේ මොහොතේ <xliff:g id="NUMBER">%1$s</xliff:g> වෙත ඔබගේ පෙළ පණිවිඩය යැවීමට නොහැක."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one">නව පණිවිඩ <xliff:g id="MESSAGES">%d</xliff:g></item>
+      <item quantity="other">නව පණිවිඩ <xliff:g id="MESSAGES">%d</xliff:g></item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ආරම්භ කරන්න"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"කැමරාව නොපවතී"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"කැමරාව නොපවතී"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"වීඩියෝව ගැනීම නොතිබේ"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"මාධ්‍ය සුරැකීම කළ නොහැක"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"පින්තූරය ලබාගත නොහැක"</string>
+    <string name="back" msgid="1477626055115561645">"ආපසු"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"සංරක්ෂිත"</string>
+    <string name="action_delete" msgid="4076795795307486019">"මකන්න"</string>
+    <string name="action_archive" msgid="5437034800324083170">"සංරක්ෂිත කරන්න"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"සංරක්ෂණය නොකළ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"දැනුම්දීම් අක්‍රිය කරන්න"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"දැනුම්දීම් සක්‍රිය කරන්න"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"සම්බන්ධතාවය එක් කරන්න"</string>
+    <string name="action_download" msgid="7786338136368564146">"බාගන්න"</string>
+    <string name="action_send" msgid="377635240181672039">"යවන්න"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"මකන්න"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"මෙම පණිවිඩය මකන්න?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"මෙම ක්‍රියාව අවසන් කිරීම කළ නොහැක."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"මකන්න"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">මෙම සංවාද මකන්නද?</item>
+      <item quantity="other">මෙම සංවාද මකන්නද?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"මකන්න"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"අවලංගු කරන්න"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"වෙත"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"බහු පින්තූර තෝරන්න"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"තේරීම සහතික කරන්න"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ශ්‍රව්‍ය පටිගත කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ශ්‍රව්‍ය ධාවනය කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ශ්‍රව්‍ය සුරැකීම කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ස්පර්ශ කරන්න සහ අල්ලා සිටින්න"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"පින්තූරය"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ශ්‍රව්‍ය පසුර"</string>
+    <string name="notification_video" msgid="4331423498662606204">"වීඩියෝව"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"සම්බන්ධතා කාඩ් පත"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"බාගන්න"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ඔස්සේ ප්‍රතිචාර දක්වන්න"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS හරහා පිළිතුරු දෙන්න"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"පිළිතුරු දෙන්න"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one">සහභාගිවන්නන් <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="other">සහභාගිවන්නන් <xliff:g id="COUNT_1">%d</xliff:g></item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"මම"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"සම්බන්ධතා අවහිර කරන ලද සහ සංරක්ෂණය කරන ලද"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"සම්බන්ධතාව අවහිර කිරීම ඉවත් කර සංරක්ෂණය නොකරන ලදී"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ක් සංරක්ෂණය කරන ලදි"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ක් සංරක්ෂණය නොකරන ලදි"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"දැනුම්දීම් ක්‍රියාවිරහිත කරන ලදී"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"දැනුම්දීම් ක්‍රියාත්මක කරන ලදී"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"සියල්ල සකසා ඇත. නැවත යැවීමට ස්පර්ශ කරන්න."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"පණිවිඩ යැවීම සාර්ථකව පෙරනිමි SMS යෙදුම ලෙස සකසන ලදී."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">ඇමුණුම් ඉවත ලන්න</item>
+      <item quantity="other">ඇමුණුම් ඉවත ලන්න</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ශ්‍රව්‍ය ඇමුණුම"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ශ්‍රව්‍ය ඇමුණුම ධාවනය කරන්න"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"විරාමය"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> වෙතින් පණිවිඩය: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> වෙතින් අසාර්ථක පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> වෙතින් පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g> වෙත නොයැවූ පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g> වෙත පණිවිඩයක් යවමින්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g> වෙත අසාර්ථක පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g> වෙත පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> වෙතින් අසාර්ථක පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> වෙතින් පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> වෙත නොයැවූ පණිවිඩය: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> වෙත පණිවිඩයක් යවමින්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> වෙත අසාර්ථක පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> වෙත පණිවිඩයක්: <xliff:g id="MESSAGE">%2$s</xliff:g>. වේලාව: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"පණිවිඩය අසාර්ථක විය. නැවත උත්සාහ කිරීමට ස්පර්ශ කරන්න."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> සමඟ සංවාදය"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"කාරණය මකන්න"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"වීඩියෝව ග්‍රහණය කරගන්න"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"නිසල පින්තූරයක් ලබාගන්න"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"පින්තූරයක් ගන්න"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"වීඩියෝව පටිගත කිරීම ආරම්භ කරන්න"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"පූර්ණ තිර කැමරාව වෙත මාරු වෙන්න"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ඉදිරිපස සහ පසුපස කාමර අතර මාරු නොවන්න"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"පටිගත කිරීම නවත්වා වීඩියෝව අමුණන්න"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"වීඩියෝ පටිගත කිරීම නැවත් වන්න"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"ඡායාරූප පණිවිඩ යැවීම"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one">ඡායාරූප <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+      <item quantity="other">ඡායාරූප <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one">වීඩියෝ <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+      <item quantity="other">වීඩියෝ <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one">ඇමුණුම් <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+      <item quantity="other">ඇමුණුම් <xliff:g id="QUANTITY_2">%d</xliff:g> ක් \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ඇල්බමය වෙත සුරකින ලදී</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් \"බාගැනීම්\" වෙත සුරකින ලදී</item>
+      <item quantity="other">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් \"බාගැනීම්\" වෙත සුරකින ලදී</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් සුරකින ලදි</item>
+      <item quantity="other">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් සුරකින ලදි</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් සුරැකීමට නොහැකි විය</item>
+      <item quantity="other">ඇමුණුම් <xliff:g id="QUANTITY_1">%d</xliff:g> ක් සුරැකීමට නොහැකි විය</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS ඇමුණුම සුරකින ලදි"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"සැකසීම්"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"සංරක්ෂිත"</string>
+    <string name="action_close" msgid="1840519376200478419">"වසන්න"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"උසස්"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"නිදොස්කරණය"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"දැනුම්දීම්"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ශබ්දය"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"නිහඬ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"කම්පනය වන්න"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"අවහිර කරන ලදි"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS යැවීමේ වාර්තාව"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ඔබ යවන ලද සෑම පණිවිඩයකටම යැවීමේ වාර්තාවක් ඉල්ලන්න"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"ස්වයං-ලබාගැනීම"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS පණිවිඩ ස්වයංක්‍රීයව ලබාගන්න"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"රෝමින් ස්වයං-ලබාගැනීම"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"රෝමිං විට MMS ස්වයංක්‍රියව යළි ලබා ගන්න"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"කණ්ඩායම් පණිවිඩ යැවීම්"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ලබන්නන් කිහිපදෙනෙක් සිටින විට එක් පණිවිඩයක් යැවීමට MMS භාවිතා කරන්න"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"සුපුරුදු SMS යෙදුම"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"සුපුරුදු SMS යෙදුම"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"ඔබගේ දුරකථන අංකය"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"නොදනී"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"යන පණිවිඩ හඬ"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS ගොඩ ගසන්න"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ලැබුණු SMS අමු දත්ත බාහිර ආචයන ගොනුවකට ගොඩ ගසන්න"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS ගොඩ ගසන්න"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ලැබුණු MMS අමු දත්ත බාහිර ආචයන ගොනුවකට ගොඩ ගසන්න"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"නොරැහැන් ඇඟවීම්"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"පණිවිඩ විකල්ප"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"පෙළ පිටපත් කරන්න"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"විස්තර බලන්න"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"මකන්න"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ඉදිරියට යවන්න"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"පණිවිඩ විස්තර"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"වර්ගය: "</string>
+    <string name="text_message" msgid="7415419755252205721">"පෙළ පණිවුඩය"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"බහු මාධ්‍ය පණිවිඩය"</string>
+    <string name="from_label" msgid="1947831848146564875">"වෙතින්: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"වෙත: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"යවන ලද: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ලැබිණි: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"කාරණය: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ප්‍රමාණය: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ප්‍රමුඛතාව: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"ඉහළ"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"සාමාන්‍ය"</string>
+    <string name="priority_low" msgid="7398724779026801851">"පහළ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"සැඟවුණු යවන්නාගේ ලිපිනය"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"ඇමුණුම් පුරණය කිරීමේදී පණිවිඩය යැවිය නොහැක."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ඇමුණුම පුර්ණය කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"ජාලය සූදානම් නැත. නැවත උත්සාහ කරන්න."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"පෙළ මකන්න"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"පෙළ සහ අංක ඇතුළු කිරීම අතර මාරුවන්න"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"සහභාගිවන්නන් තව එකතු කරන්න"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"සහභාගිවන්නන් සහතික කරන්න"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"අළුත් සංවාදයක් ආරම්භ කරන්න"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"මෙම අයිතමය තෝරන්න"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"වීඩියෝව ධාවනය කරන්න"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"පුද්ගලයින් සහ විකල්ප"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"නිදොස්කරණය"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"පුද්ගලයින් සහ විකල්ප"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"පොදු"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"මෙම සංවාදයේ සිටින පුද්ගලයින්"</string>
+    <string name="action_call" msgid="6596167921517350362">"ඇමතුමක් ලබාගන්න"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"පණිවිඩය යවන්න"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> සිට&lt;/small&gt;&lt;br/&gt; පණිවිඩ යවන්න"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">ඡායාරූප යවන්න</item>
+      <item quantity="other">ඡායාරූප යවන්න</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">ශ්‍රව්‍යය යවන්න</item>
+      <item quantity="other">ශ්‍රව්‍යය යවන්න</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">වීඩියෝ යවන්න</item>
+      <item quantity="other">වීඩියෝ යවන්න</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">සම්බන්ධතා කාඩ්පත් යවන්න</item>
+      <item quantity="other">සම්බන්ධතා කාඩ්පත් යවන්න</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">ඇමුණුම් යවන්න</item>
+      <item quantity="other">ඇමුණුම් යවන්න</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">ඇමුණුම් <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ක් යැවීමට සුදානම්</item>
+      <item quantity="other">ඇමුණුම් <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ක් යැවීමට සුදානම්</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ප්‍රතිපෝෂණය යවන්න"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play වෙළඳසැල තුළ බලන්න"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"අනුවාදයේ තොරතුරු"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"අනුවාදය %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"විවෘත මූලාශ්‍ර බලපත්‍ර"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"දැනුම්දීම්"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ඇමුණුම් සීමාව ළඟා විය"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ඇමුණුම ප්‍රවේශනය කිරීම අසාර්ථක විය."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"සම්බන්ධතාවෙත එකතු කරනද?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"සම්බන්ධතාවය එකතු කරන්න"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"මාතෘකාව"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"මාතෘකාව "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"සම්බන්ධතා කාඩ් පත් පුර්ණ කරමින්"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"සම්බන්ධතා කාඩ්පත පුර්ණය කළ නොහැක"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"සම්බන්ධ්තා කාඩ්පත පෙන්වන්න"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one">සම්බන්ධතා <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="other">සම්බන්ධතා <xliff:g id="COUNT_1">%d</xliff:g></item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"සම්බන්ධතා කාඩ්පත්"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"උපන්දිනය"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"සටහන්"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"ඉදිරියට යන පණිවිඩය"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"පිළිතුරු දෙන්න"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS අබල කරන ලදි"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"යැවීමට, පණිවිඩ යැවීම පෙරනිමි SMS යෙදුම ලෙස සකසන්න"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"පණිවිඩ යැවීම පෙරනිමි SMS යෙදුම ලෙස සකසන්න"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"වෙනස් කරන්න"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"පණිවිඩ ලබා ගැනීම සඳහා, පණිවිඩ යැවීම පෙරනිමි SMS යෙදුම ලෙස සකසන්න"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS පණිවිඩ යැවීමට සඳහා මනාප SIM එකක් තෝරාගෙන නොමැත"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"උපාංගයේ හිමිකරු මෙම යෙදුමට ඉඩ නොදෙන ලදි."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"හරි"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"සංවාදයේ සහභාගීවන්නන් ගොඩක් සිටි"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">වලංගු නොවන සම්බන්ධතා</item>
+      <item quantity="other">වලංගු නොවන සම්බන්ධතා</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"කැමරා පින්තූරය පුර්ණය කළ නොහැක"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"ඔබ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"කටු සටහන"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"අලුත් සංවාදක් ඔබ ආරම්භ කළ පසු, එය මෙතැන ලැයිස්තු කර ඇති බව ඔබ දකීවි"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"සංරක්ෂණය කළ සංවාද මෙහි දිස් වේ"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"සංවාද පුර්ණය වෙමින්..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"පින්තූරය"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ශ්‍රව්‍ය පසුර"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"වීඩියෝව"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"සම්බන්ධතා කාඩ් පත"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"අස් කරන්න"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"නැවත උත්සාහ කරන්න"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"අලුත් පණිවිඩයක් ආරම්භ කිරීමට සම්බන්ධතාවේ නම හෝ දුරකථන අංකය ඇතුළු කරන්න"</string>
+    <string name="action_block" msgid="9032076625645190136">"අවහිර කරන්න"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> අවහිර කරන ලද"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> අවහිර නොකරන්න"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> අවහිර කරලද?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"මෙම අංකයෙන් දිගටම පණිවිඩ ලැබීමට ඔබ ඉදිරියට යන ලදි නමුත් තවදුරත් දැනුම් දෙන්න එපා. මෙම සංවාදය සංරක්ෂණය කරවී."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"සම්බන්ධතා අවහිර කරන ලදි"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"අවහිර නොකරන්න"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"සම්බන්ධතා අවහිර කරන ලදි"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ලේඛන පුස්ථකාලයෙන් පින්තූර තෝරන්න"</string>
+    <string name="sending_message" msgid="6363584950085384929">"පණිවිඩය යවමින්"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"පණිවිඩය යවන ලදී"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"සෙල්‍යුලර් දත්ත අක්‍රිය කර තිබේ. ඔබගේ සැකසීම් පරික්ෂා කරන්න."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"අහස්යානා ආකාරය තුළ පණිවිඩ යැවිය නොහැක"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"පණිවිඩය යැවිය නොහැකි විය"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"පණිවිඩය බාගන්නා ලදි"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"සෙල්‍යුලර් දත්ත අක්‍රිය කර තිබේ. ඔබගේ සැකසීම් පරික්ෂා කරන්න."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ගුවන්යානා ප්‍රකාරයේදී පණිවිඩ බාගැනීමට නොහැකිය"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"පණිවිඩය බාගැනීමට නොහැකි විය"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"බිංදුව"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"එක"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"දෙක"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"තුන"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"හතර"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"පහ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"හය"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"හත"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"අට"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"නවය"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> සමඟ පණිවිඩය යැවිය නොහැක, දෝෂය <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"නොදන්නා වාහකයක් සමඟ පණිවිඩය යැවිය නොහැක, දෝෂය <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ඉදිරි: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"පණිවිඩ නොයවන ලදි: ජාලය තුළ සක්‍රිය නොකළ සේවාවකි"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"පණිවිඩ නොයවන ලදි: ගමනාන්ත ලිපිනය වලංගු නැත"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"පණිවිඩ නොයවන ලදි: පණිවිඩය වලංගු නැත"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"පණිවිඩ නොයවන ලදි: අන්තර්ගතය සහාය නොදක්වයි"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"පණිවිඩ නොයවන ලදි: පණිවිඩ සහාය නොදක්වයි"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"පණිවිඩය නොයවන ලදි: ඉතාම විශාලයි"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"අලුත් පණිවිඩය"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"බලන්න"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"පින්තුරය"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"අදාළ යෙදුම සොයාගත නොහැක"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"ලබන්නා ඉවත් කරන්න"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"අලුත් පණිවිඩය"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"අවලංගු කරන්න"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ප්‍රවේශ ස්ථානය සංස්කරණය"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"සකසා නැත"</string>
+    <string name="apn_name" msgid="1572691851070894985">"නම‍"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ප්‍රොක්සිය"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS තොට"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN වර්ගය"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN මකන්න"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"නව APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"සුරකින්න"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ඉවතලන්න"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"නම ක්ෂේත්‍රය හිස් විය නොහැක."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN හිස් විය නොහැක."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ක්ෂේත්‍රය සංඛ්‍යා 3 ක් විය යුතුය."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ක්ෂේත්‍රය ඉලක්කම් 2 ක් හෝ 3 ක් විය යුතුය."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"සුපුරුදු APN සැකසුම් යළි පිහිටුවමින්."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"සුපුරුදු වෙත යළි සකසන්න"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"සුපුරුදු APN සැකසීම නැවත සැකසීම සම්පූර්ණ කරන ලදි."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"නම් යොදා නැත"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ප්‍රවේශ ලක්ෂ්‍ය නම්"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"නව APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"මෙම පරිශීලකයා සඳහා ප්‍රවේශ ලක්ෂ්‍යයේ නමේ සැකසීම් නොතිබේ"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"පසුරු පුවරුව වෙත පිටපත් කරන්නද?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"පිටපත්කරණය"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> වෙත"</string>
+    <string name="general_settings" msgid="5409336577057897710">"පොදු"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"උසස්"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"පොදු සැකසීම්"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"උසස් සැකසුම්"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"සියළුම ලබන්නන් වෙත තනි SMS පණිවිඩ යවන්න. ඕනෑම පිළිතුරක් පමණක් ඔබට ලැබේ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"සියළුම ලබන්නන් වෙත තනි MMS යවන්න"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"නොදන්නා අංකය"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"අලුත් පණිවිඩය"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"අලුත් පණිවිඩය."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM තෝරාගැනීම"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> තෝරාගත්තේය, SIM තෝරාගැනීම"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"මාතෘකාව සකසන්න"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM තෝරන්න හෝ මාතෘකාව සකසන්න"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ශ්‍රව්‍ය පටිගත කිරීමට තට්ටු කර අල්ලා සිටින්න"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"අළුත් සංවාදයක් ආරම්භ කරන්න"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"පණිවිඩ යැවීම"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"පණිවිඩ යැවීමේ ලැයිස්තුව"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"පණිවිඩ යැවීම"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"අලුත් පණිවිඩය"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"සංවාද ලැයිස්තුව"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"සංවාද පුරණය වෙමින්"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"පණිවුඩ පූරණය කරමින්"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"තවත් සංවාද පෙන්වන්න"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"View more messages"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"සංවාදය මකාදැමුණි"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"සංවාදය මකන ලදී. වෙනස් පණිවිඩ යැවීමේ සංවාදයක් පෙන්වීමට ස්පර්ශ කරන්න"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"අවහිර කරන ලදි"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"අවහුර නොකළ"</string>
+    <string name="db_full" msgid="8459265782521418031">"ගබඩා ඉඩ අවමයි. ඇතැම් දත්ත අහිමි වනු ඇත."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"ඇමුණුම් තෝරන්න"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"තේරීම සහතික කරන්න"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ක් තෝරන ලදි"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"කරුණාකර ඇමුණුම් එකක් හෝ වැඩි සංඛ්‍යාවක් ඉවත් කර නැවත උත්සාහ කරන්න."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"ඔබට ඔබේ පණිවිඩය යැවීමට උත්සාහ කළ හැකි වුවත්, ඔබ ඇමුණුම් එකක් හෝ වැඩි සංඛ්‍යාවක් ඉවත් කරන්නේ නම් හැර එය බෙදාගැනීම නොහැකි විය හැකිය."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ඔබට පණිවිඩයකට එක් වීඩියෝවක් පමණක් යැවිය හැකිය. කරුණාකර අමතර වීඩියෝ ඉවත් කර නැවත උත්සාහ කරන්න."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"පණිවිඩ යැවීම ඇමුණුම පූරණය කිරීමට අසමත් විය."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"කෙසේ වුවත් යවන්න"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"සංවාදය ඇරඹීමට නොහැකි විය"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> තෝරාගත්තේය"</string>
+</resources>
diff --git a/res/values-sk/arrays.xml b/res/values-sk/arrays.xml
new file mode 100644
index 0000000..0e48259
--- /dev/null
+++ b/res/values-sk/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"bez predmetu"</item>
+    <item msgid="272485471009191934">"žiadny predmet"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Áno"</item>
+    <item msgid="6049132459802288033">"Nie"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Haha"</item>
+    <item msgid="2611328818571146775">"Ďakujeme"</item>
+    <item msgid="4881335087096496747">"Súhlasím"</item>
+    <item msgid="2422296858597420738">"Pekné"</item>
+    <item msgid="4805581752819452687">"Som na ceste"</item>
+    <item msgid="4746700499431366214">"OK, odpíšem neskôr"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
new file mode 100644
index 0000000..1056a95
--- /dev/null
+++ b/res/values-sk/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"SMS a MMS"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"SMS a MMS"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Vybrať konverzáciu"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Nastavenia"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Odoslať správu"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Pridať prílohu"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Pomocník"</string>
+    <string name="welcome" msgid="2857560951820802321">"Vitajte"</string>
+    <string name="skip" msgid="7238879696319945853">"Preskočiť"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Ďalej &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Ďalej"</string>
+    <string name="exit" msgid="1905187380359981199">"Ukončiť"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Nastavenia &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Nastavenia"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Aplikácia SMS a MMS vyžaduje povolenie na prístup k správam SMS, telefónu a kontaktom."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Povolenia môžete zmeniť v časti Nastavenia &gt; Aplikácie &gt; SMS a MMS &gt; Povolenia."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Povolenia môžete zmeniť v časti Nastavenia, Aplikácie, SMS a MMS, Povolenia."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Často kontaktované osoby"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Všetky kontakty"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Odoslať na číslo <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Snímať obrázky alebo videá"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Vybrať obrázky z tohto zariadenia"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Zaznamenať zvuk"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Vybrať fotku"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Je vybrané médium."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Výber média bol zrušený."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Vybrané: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"obrázok – <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"obrázok"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Zaznamenanie zvuku"</string>
+    <string name="action_share" msgid="2143483844803153871">"Zdieľať"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Práve teraz"</string>
+    <string name="posted_now" msgid="867560789350406701">"Teraz"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> hodiny</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hodiny</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hodín</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hodina</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> dňa</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dní</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> deň</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> týždne</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> týždňa</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> týždňov</item>
+      <item quantity="one">týždeň</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> mesiace</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> mesiaca</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mesiacov</item>
+      <item quantity="one">mesiac</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> roky</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> roka</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> rokov</item>
+      <item quantity="one">rok</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Správa triedy 0"</string>
+    <string name="save" msgid="5081141452059463572">"Uložiť"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"V zariadení dochádza voľné miesto. Služba SMS a MMS bude automaticky odstraňovať staršie správy, aby uvoľnila miesto."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Nedostatok miesta na úložisku"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Aplikácia SMS a MMS nebude môcť posielať ani prijímať správy, pokiaľ v zariadení nebude k dispozícii viac miesta."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"V úložisku pre správy SMS nie je dostatok voľného miesta. Je možné, že budete musieť správy odstrániť."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Potvrďte svoje telefónne číslo"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Tento jednorazový krok zaistí, že aplikácia SMS a MMS bude správne doručovať vaše skupinové správy."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefónne číslo"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Odstrániť všetky správy s médiami"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Odstrániť správy staršie ako <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Automaticky odstrániť správy staršie ako <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorovať"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Odstrániť všetky správy s médiami?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Odstrániť správy staršie ako <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Chcete odstrániť správy staršie ako <xliff:g id="DURATION">%s</xliff:g> a zapnúť automatické odstraňovanie?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> povedal(a)"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Povedali ste"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Správa od používateľa <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Odoslali ste správu"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Odosiela sa…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Správa nebola odoslaná. Klepnutím to skúste znova."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Správa nebola odoslaná. Skúšame to znova…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Znova odoslať alebo odstrániť"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Zavolajte na pohotovostné služby. Vašu textovú správu sa v tejto chvíli nepodarilo doručiť."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Nepodarilo sa"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nová správa MMS na stiahnutie"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nová správa MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nepodarilo sa stiahnuť"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Klepnutím to skúste znova"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Stiahnite klepnutím"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Stiahnuť alebo odstrániť"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Sťahuje sa..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Platnosť správy vypršala alebo správa nie je k dispozícii"</string>
+    <string name="mms_info" msgid="3402311750134118165">"veľkosť: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, vypršanie platnosti: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Správu nie je možné odoslať. Nie je uvedený platný príjemca."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Služba nie je v sieti aktivovaná"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Správu sa nepodarilo odoslať, pretože sa vyskytol problém so sieťou"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Platnosť správy vypršala alebo správa nie je k dispozícii"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Bez predmetu)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Neznámy odosielateľ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Doručené"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nepodarilo sa stiahnuť správu <xliff:g id="SUBJECT">%1$s</xliff:g> od odosielateľa <xliff:g id="FROM">%2$s</xliff:g>"</string>
+    <string name="low_memory" msgid="5300743415198486619">"Operáciu v databáze sa nepodarilo dokončiť z dôvodu nedostatku pamäte"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Správu sa nepodarilo odoslať"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Niektoré správy neboli odoslané v aplikácii SMS a MMS"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzáciách</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzácie</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzáciách</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> Počet správ v jednej konverzácii</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Správu sa nepodarilo stiahnuť"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Niektoré správy neboli stiahnuté v aplikácii SMS a MMS"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzáciách</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzácie</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g>  Počet správ v <xliff:g id="CONVERSATIONS">%d</xliff:g> konverzáciách</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> Počet správ v jednej konverzácii</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Správa na číslo <xliff:g id="NUMBER">%1$s</xliff:g> nebola odoslaná"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Zavolajte na pohotovostné služby. Vašu textovú správu na číslo <xliff:g id="NUMBER">%1$s</xliff:g> sa v tejto chvíli nepodarilo doručiť."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nové správy</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> novej správy</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nových správ</item>
+      <item quantity="one">Nová správa</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Spustiť"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotoaparát nie je k dispozícii"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotoaparát nie je k dispozícii"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Snímanie videa nie je k dispozícii"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Média nie je možné uložiť"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Snímku nie je možné odfotiť"</string>
+    <string name="back" msgid="1477626055115561645">"Späť"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Archivované"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Odstrániť"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Archivovať"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Vybrať z archívu"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Vypnúť upozornenia"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Zapnúť upozornenia"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Pridať kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Stiahnuť"</string>
+    <string name="action_send" msgid="377635240181672039">"Odoslať"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Odstrániť"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Chcete odstrániť túto správu?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Táto akcia sa nedá vrátiť späť."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Odstrániť"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="few">Odstrániť tieto konverzácie?</item>
+      <item quantity="many">Odstrániť tieto konverzácie?</item>
+      <item quantity="other">Odstrániť tieto konverzácie?</item>
+      <item quantity="one">Odstrániť túto konverzáciu?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Odstrániť"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Zrušiť"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Komu"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Vybrať viaceré obrázky"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Potvrdiť výber"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Zvuk sa nedá zaznamenať. Skúste to znova."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Zvuk sa nedá prehrať. Skúste to znova."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Zvuk sa nepodarilo uložiť. Skúste to znova."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Klepnutie a podržanie"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Fotografia"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Zvukový klip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Vizitka"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Stiahnuť"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Odpovedať pomocou správy SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Odpovedať správou MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Odpovedať"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> účastníci</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> účastníka</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> účastníkov</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> účastník</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ja"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt bol zablokovaný a archivovaný"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt bol odblokovaný a jeho archivácia bola zrušená"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Archivované: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Zrušená archivácia: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Upozornenia sú vypnuté"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Upozornenia sú zapnuté"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Všetko je pripravené. Klepnite znova na tlačidlo Odoslať."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Aplikácia SMS a MMS bola úspešne nastavená ako predvolená aplikácia pre SMS"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="few">Zahodiť prílohy</item>
+      <item quantity="many">Zahodiť prílohy</item>
+      <item quantity="other">Zahodiť prílohy</item>
+      <item quantity="one">Zahodiť prílohu</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Zvuková príloha"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Prehrať zvukovú prílohu"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pozastaviť"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Správa od používateľa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Správa od používateľa <xliff:g id="SENDER">%1$s</xliff:g> bola neúspešná: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Správa od používateľa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Správa nebola odoslaná používateľovi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Odosiela sa správa používateľovi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Správa používateľovi <xliff:g id="CONTACT">%1$s</xliff:g> bola neúspešná: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Správa používateľovi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Neúspešná správa od používateľa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Správa od používateľa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Správa nebola odoslaná skupine <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Odosiela sa správa skupine <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Správa skupine <xliff:g id="GROUP">%1$s</xliff:g> bola neúspešná: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Správa skupine <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Neúspešná správa. Skúste to znova klepnutím."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Rozhovor s používateľmi <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Odstrániť predmet"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Natočiť video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Urobiť statickú snímku"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Vyfotiť"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Spustiť natáčanie videa"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Prepnúť na fotoaparát na celej obrazovke"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Prepnúť medzi predným a zadným fotoaparátom"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Zastaviť zaznamenávanie a pripojiť video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Zastaviť zaznamenávanie videa"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotky v aplikácii SMS a MMS"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> fotky boli uložené do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> fotky bolo uloženej do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotiek bolo uložených do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotka bola uložená do albumu <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> videá boli uložené do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> videa bolo uloženého do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videí bolo uložených do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video bolo uložené do albumu <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> prílohy boli uložené do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> prílohy bolo uloženej do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> príloh bolo uložených do albumu <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> príloha bola uložená do albumu <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> prílohy boli uložené do priečinka so stiahnutými súbormi</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> prílohy bolo uloženej do priečinka so stiahnutými súbormi</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> príloh bolo uložených do priečinka so stiahnutými súbormi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> príloha bola uložená do priečinka so stiahnutými súbormi</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="few">Boli uložené <xliff:g id="QUANTITY_1">%d</xliff:g> prílohy</item>
+      <item quantity="many">Bolo uloženej <xliff:g id="QUANTITY_1">%d</xliff:g> prílohy</item>
+      <item quantity="other">Bolo uložených <xliff:g id="QUANTITY_1">%d</xliff:g> príloh</item>
+      <item quantity="one">Bola uložená <xliff:g id="QUANTITY_0">%d</xliff:g> príloha</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="few">Nepodarilo sa uložiť <xliff:g id="QUANTITY_1">%d</xliff:g> prílohy</item>
+      <item quantity="many">Nepodarilo sa uložiť <xliff:g id="QUANTITY_1">%d</xliff:g> prílohy</item>
+      <item quantity="other">Nepodarilo sa uložiť <xliff:g id="QUANTITY_1">%d</xliff:g> príloh</item>
+      <item quantity="one">Nepodarilo sa uložiť <xliff:g id="QUANTITY_0">%d</xliff:g> prílohu</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Uložené prílohy správ MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Nastavenia"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Archivované"</string>
+    <string name="action_close" msgid="1840519376200478419">"Zavrieť"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Rozšírené"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Ladiť"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Upozornenia"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Zvuk"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Tichý režim"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibrovanie"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokované"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Prehľady doručovania SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Vyžadovať potvrdenie o doručení každej odoslanej SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatické načítanie"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Automaticky načítať správy MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Automatické načítanie pri roamingu"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Automaticky načítať správy MMS počas roamingu"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Skupinové správy"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Použiť MMS na odoslanie jednej správy, ak má niekoľko príjemcov"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Predvolená aplikácia SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Predvolená aplikácia SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Vaše telefónne číslo"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Neznáme"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Zvuky odosielanej správy"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Zálohovať správy SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Zálohovať nespracované údaje prijatých správ SMS do súboru v externom úložisku"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Zálohovať správy MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Zálohovať nespracované údaje prijatých správ MMS do súboru v externom úložisku"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Bezdrôtové núdzové upozornenia"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Možnosti správy"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopírovať text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Zobraziť podrobnosti"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Odstrániť"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Poslať ďalej"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Podrobnosti správy"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Typ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Textová správa"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimediálna správa"</string>
+    <string name="from_label" msgid="1947831848146564875">"Od: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Komu: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Odoslané: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Prijaté: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Predmet: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Veľkosť: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priorita: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM karta: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Vysoká"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normálna"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Nízka"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"Slot SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skrytá adresa odosielateľa"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Počas načítavania príloh nie je možné odoslať správu."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nie je možné načítať prílohu. Skúste to znova."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Sieť nie je pripravená. Skúste to znova."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Odstrániť text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Prepnúť medzi zadávaním textu a číslic"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Pridať ďalších účastníkov"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Potvrdiť účastníkov"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Začať novú konverzáciu"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Vybrať túto položku"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Prehrať video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Ľudia a možnosti"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Ladiť"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Ľudia a možnosti"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Všeobecné"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Ľudia v tejto konverzácii"</string>
+    <string name="action_call" msgid="6596167921517350362">"Zavolať"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Odoslať správu"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Odošlite správu&lt;br/&gt;&lt;small&gt;zo SIM karty <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="few">Odoslať fotky</item>
+      <item quantity="many">Odoslať fotky</item>
+      <item quantity="other">Odoslať fotky</item>
+      <item quantity="one">Odoslať fotku</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="few">Odoslať zvukové súbory</item>
+      <item quantity="many">Odoslať zvukové súbory</item>
+      <item quantity="other">Odoslať zvukové súbory</item>
+      <item quantity="one">Odoslať zvukový súbor</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="few">Odoslať videá</item>
+      <item quantity="many">Odoslať videá</item>
+      <item quantity="other">Odoslať videá</item>
+      <item quantity="one">Odoslať video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="few">Odoslať vizitky</item>
+      <item quantity="many">Odoslať vizitky</item>
+      <item quantity="other">Odoslať vizitky</item>
+      <item quantity="one">Odoslať vizitku</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="few">Odoslať prílohy</item>
+      <item quantity="many">Odoslať prílohy</item>
+      <item quantity="other">Odoslať prílohy</item>
+      <item quantity="one">Odoslať prílohu</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> prílohy sú pripravené na odoslanie</item>
+      <item quantity="many"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> prílohy je pripravenej na odoslanie</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> príloh je pripravených na odoslanie</item>
+      <item quantity="one">Jedna príloha je pripravená na odoslanie</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Odoslať spätnú väzbu"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Zobraziť v Obchode Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informácie o verzii"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Verzia %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licencie open source"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Upozornenia"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Dosiahli ste limit pre počet príloh"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Prílohu sa nepodarilo načítať."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Pridať medzi kontakty?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Pridať kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Predmet"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Predmet: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Načítava sa vizitka"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nepodarilo sa načítať vizitku"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Zobraziť vizitku"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> kontakty</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> kontaktu</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontaktov</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Vizitky"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Narodeniny"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Poznámky"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Poslanie správy ďalej"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Odpovedanie"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Správy SMS sú zakázané"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Ak chcete odosielať správy, nastavte SMS a MMS ako predvolenú aplikáciu pre SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Nastavte SMS a MMS ako predvolenú aplikáciu pre SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Zmeniť"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Ak chcete prijímať správy, nastavte SMS a MMS ako predvolenú aplikáciu pre SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nie je vybraná preferovaná SIM karta na odosielanie správ SMS."</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Túto aplikáciu vlastník zariadenia nepovolil."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"V konverzácii je príliš mnoho účastníkov"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="few">Neplatné kontakty</item>
+      <item quantity="many">Neplatné kontakty</item>
+      <item quantity="other">Neplatné kontakty</item>
+      <item quantity="one">Neplatný kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Obrázok z fotoaparátu sa nepodarilo načítať"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vy: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Koncept"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Tu uvidíte svoje konverzácie"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Tu sa zobrazujú archivované konverzácie"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Načítavajú sa konverzácie..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Obrázok"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Zvukový klip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Vizitka"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Späť"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Skúsiť znova"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Zadajte meno kontaktu alebo telefónne číslo a začnite písať novú správu"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokovať"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokovať kontakt <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Odblokovať kontakt <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Blokovať <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Z tohto čísla budete aj naďalej dostávať správy. Nebudete už však dostávať upozornenia. Táto konverzácia bude archivovaná."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokované kontakty"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ODBLOKOVAŤ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokované kontakty"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Vyberte obrázok z knižnice dokumentov"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Správa sa odosiela"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Správa bola odoslaná"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Prenos mobilných údajov je vypnutý. Skontrolujte svoje nastavenia."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"V režime V lietadle nie je možné odosielať správy"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Odoslanie správy zlyhalo"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Správa bola stiahnutá"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Prenos mobilných dát je vypnutý. Skontrolujte svoje nastavenia."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"V režime v lietadle nie je možné sťahovať správy"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Správu nie je možné stiahnuť"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nula"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Jedna"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dva"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tri"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Štyri"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Päť"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Šesť"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sedem"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Osem"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Deväť"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Správu prostredníctvom operátora <xliff:g id="CARRIERNAME">%1$s</xliff:g> nie je možné odoslať. Chyba: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Správu prostredníctvom neznámeho operátora nie je možné odoslať. Chyba: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Poslať ďalej: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Správa nebola odoslaná: služba nie je aktivovaná v sieti"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Správa nebola odoslaná: neplatná cieľová adresa"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Správa nebola odoslaná: neplatná správa"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Správa nebola odoslaná: nepodporovaný obsah"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Správa nebola odoslaná: nepodporovaná správa"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Správa nebola odoslaná: veľkosť prekročila limit"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nová správa"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Zobraziť"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Obrázok"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nenašla sa vhodná aplikácia"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Odstrániť príjemcu"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nová správa"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Zrušiť"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Úprava prístupového bodu"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nenastavené"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Názov"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Názov prístupového bodu"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy server systému MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port systému MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Typ prístupového bodu"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Odstrániť názov prístupového bodu (APN)"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nový prístupový bod"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Uložiť"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Zrušiť"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Pole Meno nemôže byť prázdne."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Názov prístupového bodu (APN) nemôže byť prázdny."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Pole MCC musí obsahovať 3 číslice."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Pole MNC musí obsahovať 2 alebo 3 číslice."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Obnovujú sa predvolené nastavenia názvu prístupového bodu (APN)."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Obnoviť predvolené"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Predvolené nastavenia prístupových bodov boli obnovené"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Bez názvu"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Názvy prístupových bodov"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Prístupové body"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nový prístupový bod"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Nastavenia názvu prístupového bodu (APN) nie sú dostupné pre tohto používateľa"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopírovať do schránky?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopírovať"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"na SIM kartu <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Všeobecné"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Rozšírené"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Všeobecné nastavenia"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Rozšírené nastavenia"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM karta <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Odoslať osobitné správy SMS všetkým príjemcom. Všetky odpovede dostanete iba vy."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Odoslať jednu správu MMS všetkým príjemcom"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Neznáme číslo"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nová správa"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nová správa"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Výber SIM karty"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Výber SIM karty (vybraná SIM karta <xliff:g id="SIM_0">%1$s</xliff:g>)"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Upraviť predmet"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Vybrať SIM kartu alebo upraviť predmet"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Zvuk zaznamenáte klepnutím a podržaním"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Začať novú konverzáciu"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS a MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Zoznam v aplikácii SMS a MMS"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS a MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nová správa"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Zoznam konverzácií"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Načítavajú sa konverzácie..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Načítavajú sa správy"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Zobraziť ďalšie konverzácie"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Zobraziť viac správ"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Konverzácia bola odstránená"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Konverzácia bola odstránená. Klepnutím si zobrazte inú konverzáciu aplikácie SMS a MMS."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Zablokované"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Odblokované"</string>
+    <string name="db_full" msgid="8459265782521418031">"V úložisku je málo miesta. Niektoré údaje môžu byť stratené."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Vybrať prílohy"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Potvrďte výber"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Vybrané: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Odstráňte jednu alebo viac príloh a skúste to znova."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Svoju správu sa môžete pokúsiť odoslať, ale pravdepodobne bude doručená až vtedy, keď odstránite jednu alebo viac príloh."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Môžete odoslať iba jedno video na správu. Odstráňte ďalšie videá a skúste to znova."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Aplikácii SMS a MMS sa nepodarilo načítať prílohu."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Aj tak odoslať"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Rozhovor nie je možné spustiť"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Vybrané: <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-sl/arrays.xml b/res/values-sl/arrays.xml
new file mode 100644
index 0000000..0cd69b7
--- /dev/null
+++ b/res/values-sl/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"brez zadeve"</item>
+    <item msgid="272485471009191934">"nizadeve"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Da"</item>
+    <item msgid="6049132459802288033">"Ne"</item>
+    <item msgid="3084376867445867895">"V redu"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Hvala"</item>
+    <item msgid="4881335087096496747">"Strinjam se"</item>
+    <item msgid="2422296858597420738">"Lepo"</item>
+    <item msgid="4805581752819452687">"Prihajam"</item>
+    <item msgid="4746700499431366214">"V redu, oglasim se pozneje"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
new file mode 100644
index 0000000..6c85318
--- /dev/null
+++ b/res/values-sl/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Sporočila"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Sporočila"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Izbira pogovora"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Nastavitve"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Pošlji sporočilo"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Dodajte prilogo"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Pomoč"</string>
+    <string name="welcome" msgid="2857560951820802321">"Pozdravljeni"</string>
+    <string name="skip" msgid="7238879696319945853">"Preskoči"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Naprej &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Naprej"</string>
+    <string name="exit" msgid="1905187380359981199">"Izhod"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Nastavitve &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Nastavitve"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Sporočila zahtevajo dovoljenje za dostop do sporočil SMS, telefona in stikov."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Dovoljenja lahko spreminjate v »Nastavitve &gt; Aplikacije &gt; Sporočila &gt; Dovoljenja«."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Dovoljenja lahko spreminjate v »Nastavitve, Aplikacije, Sporočila, Dovoljenja«."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Pogosti"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Vsi stiki"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Pošlji na številko <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Snemanje slik ali videoposnetkov"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Izbira slik iz te naprave"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Snemanje zvoka"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Izbira fotografije"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Predstavnost je izbrana."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Izbor predstavnosti je preklican."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Št. izbranih: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"slika <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"slika"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Snemanje zvoka"</string>
+    <string name="action_share" msgid="2143483844803153871">"Skupna raba"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Pravkar"</string>
+    <string name="posted_now" msgid="867560789350406701">"Zdaj"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ura</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> uri</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> ure</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ur</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> dan</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> dneva</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> teden</item>
+      <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> tedna</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> tedne</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tednov</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mesec</item>
+      <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> meseca</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> mesece</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mesecev</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> leto</item>
+      <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> leti</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> leta</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> let</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Sporočilo razreda 0"</string>
+    <string name="save" msgid="5081141452059463572">"Shrani"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"V napravi primanjkuje prostora za shranjevanje. Sporočila bodo zaradi sprostitve prostora samodejno izbrisala starejša sporočila."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Zmanjkalo bo prostora za shranjevanje"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Sporočila morda ne bodo pošiljala ali sprejemala sporočil, dokler v napravi ne bo na voljo več prostora."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Prostora za SMS-je je malo. Morda boste morali izbrisati sporočila."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Potrditev telefonske številke"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"S tem enkratnim korakom boste zagotovili, da bodo Sporočila pravilno dostavljala skupinska sporočila."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonska številka"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Izbriši vsa sporočila s predstavnostjo"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Izbriši sporočila, starejša od <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Samodejno brisanje sporočil, starejših od <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Prezri"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Želite izbrisati vsa sporočila s predstavnostjo?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Želite izbrisati sporočila, starejša od <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Želite izbrisati sporočila, starejša od <xliff:g id="DURATION">%s</xliff:g>, in vklopiti samodejno brisanje?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"Oseba <xliff:g id="SENDER">%s</xliff:g> sporoča"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Sporočili ste"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Sporočilo osebe <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Poslali ste sporočilo"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Pošiljanje …"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Ni bilo poslano. Dotaknite se za vnovični poskus."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Ni bilo poslano. Vnovični poskus …"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Znova pošlji ali izbriši"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Pokličite nujno pomoč. SMS-ja ni bilo mogoče poslati."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Ni uspelo"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Novo sporočilo MMS za prenos"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Novo sporočilo MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Prenos ni uspel"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Dotaknite se za vnovični poskus"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Dotaknite se za prenos"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Prenesi ali izbriši"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Prenašanje …"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Sporočilo je poteklo ali ni na voljo"</string>
+    <string name="mms_info" msgid="3402311750134118165">"velikost: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, poteče: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Pošiljanje ni mogoče. Prejemnik ni veljaven."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Storitev ni aktivirana v omrežju"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Pošiljanje zaradi težave v omrežju ni uspelo"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Sporočilo je poteklo ali ni na voljo"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Ni zadeve)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Neznan pošiljatelj"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Dostavljeno"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Sporočila <xliff:g id="SUBJECT">%1$s</xliff:g> osebe <xliff:g id="FROM">%2$s</xliff:g> ni bilo mogoče prenesti."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Postopka v zbirki podatkov ni bilo mogoče dokončati, ker primanjkuje pomnilnika"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Sporočilo ni bilo poslano"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Nekatera sporočila niso bila poslana v Sporočilih"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočilo v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovoru</item>
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočili v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočila v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočil v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Sporočilo ni bilo preneseno"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Nekatera sporočila niso bila prenesena v Sporočilih"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočilo v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovoru</item>
+      <item quantity="two"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočili v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočila v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> sporočil v <xliff:g id="CONVERSATIONS">%d</xliff:g> pogovorih</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Sporočilo na številko <xliff:g id="NUMBER">%1$s</xliff:g> ni bilo poslano"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Pokličite nujno pomoč. SMS-ja na <xliff:g id="NUMBER">%1$s</xliff:g> ni bilo mogoče poslati."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> novo sporočilo</item>
+      <item quantity="two"><xliff:g id="MESSAGES">%d</xliff:g> novi sporočili</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> nova sporočila</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> novih sporočil</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Začni"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Fotoaparat ni na voljo"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Fotoaparat ni na voljo"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Snemanje videoposnetkov ni na voljo"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Predstavnosti ni mogoče shraniti"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Ni mogoče posneti fotografije"</string>
+    <string name="back" msgid="1477626055115561645">"Nazaj"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arhivirano"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Izbriši"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arhiviraj"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Odstrani iz arhiva"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Izklop obvestil"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Vklop obvestil"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Dodaj stik"</string>
+    <string name="action_download" msgid="7786338136368564146">"Prenos"</string>
+    <string name="action_send" msgid="377635240181672039">"Pošlji"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Izbriši"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Želite izbrisati sporočilo?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Tega dejanja ni mogoče razveljaviti."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Izbriši"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Želite izbrisati te pogovore?</item>
+      <item quantity="two">Želite izbrisati te pogovore?</item>
+      <item quantity="few">Želite izbrisati te pogovore?</item>
+      <item quantity="other">Želite izbrisati te pogovore?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Izbriši"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Prekliči"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Za"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Izbira več slik"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Potrditev izbora"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Zvoka ni mogoče posneti. Poskusite znova."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Zvoka ni mogoče predvajati. Poskusite znova."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Zvoka ni bilo mogoče shraniti. Poskusite znova."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Dotaknite se in pridržite"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Slika"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Zvočni posnetek"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Videoposnetek"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Osebna vizitka"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Prenos"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Odgovor prek sporočila SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Odg. z MMS-jem"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Odgovori"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> udeleženec</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> udeleženca</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> udeleženci</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> udeležencev</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Jaz"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Blokirani in arhivirani stiki"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Stik odblokiran in odstranjen iz arhiva"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Št. arhiviranih: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Št. povrnjenih iz arhiva: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Obvestila izklopljena"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Obvestila vklopljena"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Vse je nastavljeno. Znova se dotaknite »Pošlji«."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Sporočila so uspešno nastavljena kot privzeta aplikacija za sporočila SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Zavrzi priloge</item>
+      <item quantity="two">Zavrzi priloge</item>
+      <item quantity="few">Zavrzi priloge</item>
+      <item quantity="other">Zavrzi priloge</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Zvočna priloga"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Predvajanje zvočne priloge"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Začasna zaustavitev"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Sporočilo pošiljatelja <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Neuspelo sporočilo osebe <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Sporočilo osebe <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Neposlano sporočilo osebi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Pošiljanje sporočila osebi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Neuspelo sporočilo osebi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Sporočilo osebi <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Neuspelo sporočilo osebe <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Sporočilo osebe <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Neposlano sporočilo skupini <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Pošiljanje sporočila skupini <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Neuspelo sporočilo skupini <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Sporočilo skupini <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Čas: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Neuspelo sporočilo. Dotaknite se za vnovičen poskus."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Pogovor z udeleženci <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Izbris zadeve"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Posnemi video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Posnemi fotografijo"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Fotografiraj"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Začni snemanje videa"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Preklopi v celozaslonski način fotoaparata"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Preklop med sprednjim in zadnjim fotoaparatom"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Ustavi snemanje in pripni videoposnetek"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Ustavi snemanje videoposnetka"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Fotografije v Sporočilih"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografija shranjena v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografiji shranjeni v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografije shranjene v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografij shranjenih v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> videoposnetek shranjen v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> videoposnetka shranjena v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> videoposnetki shranjeni v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videoposnetkov shranjenih v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> priloga shranjena v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="two"><xliff:g id="QUANTITY_2">%d</xliff:g> prilogi shranjeni v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> priloge shranjene v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> prilog shranjenih v album »<xliff:g id="ALBUMNAME_3">%s</xliff:g>«</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> priloga shranjena v »Prenosi«</item>
+      <item quantity="two"><xliff:g id="QUANTITY_1">%d</xliff:g> prilogi shranjeni v »Prenosi«</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> priloge shranjene v »Prenosi«</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> prilog shranjenih v »Prenosi«</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> priloga je bila shranjena</item>
+      <item quantity="two"><xliff:g id="QUANTITY_1">%d</xliff:g> prilogi sta bili shranjeni</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> priloge so bile shranjene</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> prilog je bilo shranjenih</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> priloge ni bilo mogoče shraniti</item>
+      <item quantity="two"><xliff:g id="QUANTITY_1">%d</xliff:g> prilog ni bilo mogoče shraniti</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> prilog ni bilo mogoče shraniti</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> prilog ni bilo mogoče shraniti</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Shranjena priloga sporočila MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Nastavitve"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arhivirano"</string>
+    <string name="action_close" msgid="1840519376200478419">"Zapri"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Dodatno"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Odpravljanje napak"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Obvestila"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Zvok"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Tiho"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibriranje"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blokirano"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Poročila o dostavi sporočil SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Zahtevanje poročila o dostavi za vsak poslan SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Samodejni prenos"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Samodejni prenos MMS-jev"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Samodejni prenos med gostovanjem"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Samodejni prenos sporočil MMS med gostovanjem"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Skupinsko pošiljanje sporočil"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Če želite eno sporočilo poslati več prejemnikom, uporabite MMS"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Privzeta aplikacija za sporočila SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Privzeta aplikacija za sporočila SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Vaša telefonska številka"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Neznano"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Zvoki pri odhodnih sporočilih"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Izvoz SMS-jev"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Izvoz neobdelanih podatkov iz prejetih SMS-jev v datoteko v zunanji napravi za shranjevanje"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Izvoz MMS-jev"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Izvoz neobdelanih podatkov iz prejetih MMS-jev v datoteko v zunanji napravi za shranjevanje"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Brezžična opozorila"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Možnosti sporočila"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiraj besedilo"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ogled podrobnosti"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Brisanje"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Posreduj"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Podrobnosti sporočila"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Vrsta: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"MMS"</string>
+    <string name="from_label" msgid="1947831848146564875">"Od: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Za: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Poslano: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Prejeto: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Zadeva: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Velikost: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prednost: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Visoka"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Običajna"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Nizka"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Skrit naslov pošiljatelja"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Med nalaganjem priponk ni mogoče poslati sporočila."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Priloge ni mogoče naložiti. Poskusite znova."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Omrežje ni pripravljeno. Poskusite znova."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Izbriši besedilo"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Preklop med vnašanjem besedila in številk"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Dodaj več udeležencev"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Potrditev udeležencev"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Začenjanje novega pogovora"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Izbira tega elementa"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Predvajanje videoposnetka"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Osebe in možnosti"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Odpravljanje napak"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Osebe in možnosti"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Splošno"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Osebe v tem pogovoru"</string>
+    <string name="action_call" msgid="6596167921517350362">"Klicanje"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Pošlji sporočilo"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Pošiljanje sporočila&lt;br/&gt;&lt;small&gt;s kartico <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Pošljite fotografije</item>
+      <item quantity="two">Pošljite fotografije</item>
+      <item quantity="few">Pošljite fotografije</item>
+      <item quantity="other">Pošljite fotografije</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Pošljite zvočne posnetke</item>
+      <item quantity="two">Pošljite zvočne posnetke</item>
+      <item quantity="few">Pošljite zvočne posnetke</item>
+      <item quantity="other">Pošljite zvočne posnetke</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Pošljite videoposnetke</item>
+      <item quantity="two">Pošljite videoposnetke</item>
+      <item quantity="few">Pošljite videoposnetke</item>
+      <item quantity="other">Pošljite videoposnetke</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Pošljite osebne vizitke</item>
+      <item quantity="two">Pošljite osebne vizitke</item>
+      <item quantity="few">Pošljite osebne vizitke</item>
+      <item quantity="other">Pošljite osebne vizitke</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Pošljite priloge</item>
+      <item quantity="two">Pošljite priloge</item>
+      <item quantity="few">Pošljite priloge</item>
+      <item quantity="other">Pošljite priloge</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priloga je pripravljena za pošiljanje</item>
+      <item quantity="two"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> prilogi sta pripravljeni za pošiljanje</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> priloge so pripravljene za pošiljanje</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> prilog je pripravljenih za pošiljanje</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Pošljite povratne informacije"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Ogled v Trgovini Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Podatki o različici"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Različica %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Odprtokodne licence"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Obvestila"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Dosežena je omejitev za priloge"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Nalaganje priloge ni uspelo."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Ali želite dodati med stike?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Dodaj stik"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Zadeva"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Zadeva: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Nalaganje osebne vizitke"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Vizitke ni bilo mogoče naložiti"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Ogled osebne vizitke"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> stik</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> stika</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> stiki</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> stikov</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Vizitke"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Rojstni dan"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Zapiski"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Posredovanje sporočila"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Odgovor"</string>
+    <string name="plus_one" msgid="9010288417554932581">"še 1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"več kot %d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS-ji so onemogočeni"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Če želite pošiljati, nastavite Sporočila kot privzeto aplikacijo za sporočila SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Nastavite Sporočila kot privzeto aplikacijo za sporočila SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Spremeni"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Če želite prejemati sporočila, nastavite Sporočila kot privzeto aplikacijo za sporočila SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ni izbrane prednostne kartice SIM za pošiljanje sporočil SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Lastnik naprave ne dovoli uporabe te aplikacije."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"V redu"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Preveč udeležencev v pogovoru"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Neveljavni stiki</item>
+      <item quantity="two">Neveljavni stiki</item>
+      <item quantity="few">Neveljavni stiki</item>
+      <item quantity="other">Neveljavni stiki</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Slike fotoaparata ni bilo mogoče naložiti"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Vi: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Osnutek"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Ko začnete nov pogovor, bo naveden tukaj"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Tu so prikazani arhivirani pogovori"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Nalaganje pogovorov ..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Slika"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Zvočni posnetek"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Videoklic"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Osebna vizitka"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Razveljavi"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Poskusi znova"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Če želite začeti novo sporočilo, vnesite ime stika ali telefonsko številko"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blokiraj"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blokiraj stik <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Odblokiraj stik <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Želite blokirati <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Še vedno boste prejemali sporočila s te številke, vendar ne boste več obveščeni. Ta pogovor bo arhiviran."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blokirani stiki"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ODBLOKIRAJ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blokirani stiki"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Izbira slike iz knjižnice dokumentov"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Pošiljanje sporočila"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Sporočilo poslano"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Prenos podatkov v mobilnem omrežju je izklopljen. Preverite nastavitve."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"V načinu za letalo ni mogoče pošiljati sporočil"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Sporočila ni bilo mogoče poslati."</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Sporočilo preneseno"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Prenos podatkov v mobilnem omrežju je izklopljen. Preverite nastavitve."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"V načinu za letalo ni mogoče prenašati sporočil"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Sporočila ni bilo mogoče prenesti"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nič"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Ena"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dva"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tri"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Štiri"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pet"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Šest"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sedem"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Osem"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Devet"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Sporočila prek operaterja <xliff:g id="CARRIERNAME">%1$s</xliff:g> ni mogoče poslati, napaka <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Sporočila prek neznanega operaterja ni mogoče poslati, napaka <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Sporočilo ni bilo poslano: storitev ni aktivirana v omrežju"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Sporočilo ni poslano: neveljaven naslov prejemnika"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Sporočilo ni poslano: neveljavno sporočilo"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Sporočilo ni poslano: nepodprta vsebina"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Sporočilo ni poslano: nepodprto sporočilo"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Sporočilo ni bilo poslano: prevelika velikost"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Novo sporočilo"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Pogled"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Slika"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Ni bilo mogoče najti primerne aplikacije"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Odstrani prejemnika"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Novo sporočilo"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Prekliči"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Urejanje dostopne točke"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ni nastavljeno"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Ime"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"Storitveni center za sporočila MMS"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Strežnik proxy za sporočila MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Vrata za sporočila MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"Mobilna koda države"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"Koda mobilnega omrežja"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Vrsta APN-ja"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Izbriši APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nov APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Shrani"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Zavrzi"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Polje z imenom ne sme biti prazno."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ne sme biti prazen."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Polje z mobilno kodo države mora vsebovati 3 števke."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Polje s kodo mobilnega omrežja mora vsebovati 2 ali 3 števke."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Obnavljanje privzetih nastavitev APN-ja."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Ponastavi na privzeto"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Ponastavitev privzetih nastavitev APN-ja je končana."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Neimenovano"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Imena dostopnih točk"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-ji"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nov APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Nastavitve imena dostopne točke niso na voljo za tega uporabnika"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Želite kopirati v odložišče?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiraj"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"v kartico <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Splošno"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Dodatno"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Splošne nastavitve"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Dodatne nastavitve"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Kartica SIM »<xliff:g id="SIM_NAME">%s</xliff:g>«"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Pošiljanje posameznih sporočil SMS vsem prejemnikom. Morebitne odgovore boste prejeli samo vi."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Pošiljanje enega sporočila MMS vsem prejemnikom"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Neznana številka"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Novo sporočilo"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Novo sporočilo."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Izbirnik kartice SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Izbrana kartica SIM <xliff:g id="SIM_0">%1$s</xliff:g>, izbirnik kartic SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Uredi zadevo"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Izberi kartico SIM ali uredi zadevo"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Dotakni se in pridrži za snemanje zvoka"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Začenjanje novega pogovora"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Sporočila"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Seznam sporočil"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Sporočila"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Novo sporočilo"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Seznam pogovorov"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Nalaganje pogovorov"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Nalaganje sporočil"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Več pogovorov"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Prikaz več sporočil"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Pogovor je izbrisan"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Pogovor je izbrisan. Dotaknite se, če želite prikazati drug pogovor v Sporočilih."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blokiran(-a)"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Odblokiran(-a)"</string>
+    <string name="db_full" msgid="8459265782521418031">"Primanjkuje prostora za shranjevanje. Nekateri podatki bodo morda izgubljeni."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Izbira prilog"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Potrditev izbora"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Št. izbranih: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Odstranite eno ali več prilog in poskusite znova."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Lahko poskusite poslati sporočilo, vendar morda ne bo dostavljeno, razen če odstranite eno ali več prilog."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Pošljete lahko samo en videoposnetek na sporočilo. Odstranite druge videoposnetke in poskusite znova."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Sporočila niso uspela naložiti priloge."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Vseeno pošlji"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Pogovora ni bilo mogoče začeti"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Izbrana kartica SIM <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-sq/arrays.xml b/res/values-sq/arrays.xml
new file mode 100644
index 0000000..2744180
--- /dev/null
+++ b/res/values-sq/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"pa subjekt"</item>
+    <item msgid="272485471009191934">"pa subjekt"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Po"</item>
+    <item msgid="6049132459802288033">"Jo"</item>
+    <item msgid="3084376867445867895">"Në rregull!"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Faleminderit"</item>
+    <item msgid="4881335087096496747">"Pranoj"</item>
+    <item msgid="2422296858597420738">"Këndshëm"</item>
+    <item msgid="4805581752819452687">"Jam rrugës"</item>
+    <item msgid="4746700499431366214">"Në rregull, më lejo të të marr më vonë"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
new file mode 100644
index 0000000..f7b858c
--- /dev/null
+++ b/res/values-sq/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mesazhet"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mesazhet"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Përzgjidh bisedën"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Cilësimet"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Dërgo mesazh"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Shto një bashkëngjitje"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Ndihma"</string>
+    <string name="welcome" msgid="2857560951820802321">"Mirë se erdhe"</string>
+    <string name="skip" msgid="7238879696319945853">"Kapërce"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Përpara &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Përpara"</string>
+    <string name="exit" msgid="1905187380359981199">"Dil"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Cilësimet &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Cilësimet"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mesazhet kanë nevojë për leje për në SMS, Telefon dhe Kontakte."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Lejet mund t\'i ndryshosh te Cilësimet, Aplikacionet, Mesazhet, Lejet."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Lejet mund t\'i ndryshosh te Cilësimet, Aplikacionet, Mesazhet, Lejet."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Të shpeshta"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Të gjitha kontaktet"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Dërgoje te <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Regjistro fotografi ose video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Zgjidh imazhe nga kjo pajisje"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Regjistro audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Zgjidh foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Artikulli \"media\" u zgjodh."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Artikulli \"media\" nuk u zgjodh."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"U përzgjodhën <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"imazhi <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"imazhi"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Regjistro audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Shpërnda"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Pikërisht tani"</string>
+    <string name="posted_now" msgid="867560789350406701">"Tani"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minuta</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minutë</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> orë</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> orë</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ditë</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ditë</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> javë</item>
+      <item quantity="one">një javë</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> muaj</item>
+      <item quantity="one">një muaj</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> vite</item>
+      <item quantity="one">një vit</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Mesazh i kategorisë 0"</string>
+    <string name="save" msgid="5081141452059463572">"Ruaj"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Në pajisje ka mbetur pak hapësirë e lirë. Mesazhet do të fshijnë automatikisht mesazhet e vjetra për të liruar hapësirë."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Hapësira ruajtëse po mbaron"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"\"Mesazhet\" mund të mos dërgojë ose pranojë mesazhe derisa të ketë hapësirë tjetër të lirë në pajisjen tënde."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Hapësirë e paktë ruajtëse për SMS-tw. Mund të të duhet të fshish mesazhe."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Konfirmo numrin tënd të telefonit"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Ky hap që kryhet vetëm një herë do të garantojë që Mesazhet t\'i dorëzojë siç duhet mesazhet e tua në grup."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numri i telefonit"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Fshiji të gjitha mesazhet me klipe \"media\""</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Fshi mesazhe më të vjetra se <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Fshi automatikisht mesazhe më të vjetra se <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Shpërfill"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Të fshihen të gjitha mesazhet me klipe \"media\"?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Të fshihen mesazhet më të vjetra se <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Të fshihen mesazhet më të vjetra se <xliff:g id="DURATION">%s</xliff:g> dhe të aktivizohet fshirja automatike?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> tha"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ti the"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mesazh nga <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Dërgove një mesazh"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Po dërgon..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Nuk u dërgua. Prek për të provuar sërish."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Nuk u dërgua. Po provon sërish…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Dërgo sërish ose fshi"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Bëj një telefonatë me zë drejt shërbimeve të urgjencës. Mesazhi yt me tekst nuk arriti të dërgohej këtë herë."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Dështoi"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Mesazh i ri MMS-je për të shkarkuar"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Mesazh i ri MMS-je"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nuk arriti ta shkarkonte"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Prek për të provuar sërish"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Prek për të shkarkuar"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Shkarko ose fshi"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Po shkarkon…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Mesazhi skadoi ose nuk mund të përdoret"</string>
+    <string name="mms_info" msgid="3402311750134118165">"madhësia: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, skadimi: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Nuk mund ta dërgojë. Marrësi është i pavlefshëm."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Shërbimi nuk është i aktivizuar në rrjet"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Nuk arriti ta dërgonte për shkak të një problemit në rrjet"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Mesazhi skadoi ose nuk mundësohet"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Pa subjekt)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Dërgues i panjohur"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Dorëzuar"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Nuk arriti të shkarkonte mesazhin <xliff:g id="SUBJECT">%1$s</xliff:g> nga <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Nuk arriti të përfundonte operacionin e bazës së të dhënave për shkak të kujtesës së pakët"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Mesazhi nuk është dërguar"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Disa mesazhe nuk janë dërguar te Mesazhet"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mesazhe në <xliff:g id="CONVERSATIONS">%d</xliff:g> bashkëbisedime</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mesazhe në një bashkëbisedim</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Mesazhi nuk u shkarkua"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Disa mesazhe nuk janë shkarkuar te Mesazhet"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> mesazhe në <xliff:g id="CONVERSATIONS">%d</xliff:g> bashkëbisedime</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> mesazhe në një bashkëbisedim</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Mesazhi për <xliff:g id="NUMBER">%1$s</xliff:g> nuk u dërgua"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Bëj një telefonatë me zë drejt shërbimeve të urgjencës. Mesazhi yt me tekst për <xliff:g id="NUMBER">%1$s</xliff:g> nuk arriti të dërgohej këtë herë."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> mesazhe të reja</item>
+      <item quantity="one">Mesazh i ri</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Fillo"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera nuk mund të përdoret"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera nuk mund të përdoret"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Regjistrimi i videos nuk mundësohet"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Nuk mund të ruajë materiale \"media\""</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Nuk mund të nxjerrë fotografi"</string>
+    <string name="back" msgid="1477626055115561645">"Prapa"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arkivuar"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Fshi"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkivo"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Hiq nga arkiva"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Çaktivizo njoftimet"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Aktivizo njoftimet"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Shto kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Shkarko"</string>
+    <string name="action_send" msgid="377635240181672039">"Dërgo"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Fshi"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Të fshihet ky mesazh?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ky veprim nuk mund të zhbëhet."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Fshi"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Fshiji këto biseda?</item>
+      <item quantity="one">Fshije këtë bisedë?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Fshi"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Anulo"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Për"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Përzgjidh shumë imazhe"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Konfirmo përzgjedhjen"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Nuk mund të regjistrojë audio. Provo sërish."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Nuk mund të luajë audio. Provo sërish."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Nuk arriti ta ruante audion. Provo sërish."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Prek dhe mbaj shtypur"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Fotografi"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Klip audioje"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kartë kontakti"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Shkarko"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Përgjigju përmes SMS-së"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Përgjigju përmes MMS-së"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Përgjigju"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> pjesëmarrës</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> pjesëmarrës</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Unë"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt i bllokuar dhe i arkivuar"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakti u zhbllokua dhe arkivimi i tij u anulua"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> të arkivuara"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> të paarkivuara"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Njoftimet janë të çaktivizuara"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Njoftimet janë të aktivizuara"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Gjithçka gati. Prek sërish \"Dërgo\"."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"\"Mesazhet\" u caktua me sukses si aplikacioni me parazgjedhje i SMS-ve."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Hiq bashkëngjitjet</item>
+      <item quantity="one">Hiq bashkëngjitjen</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Bashkëngjitja audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Luaj bashkëngjitjen në audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pauzë"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mesazh nga <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Mesazh i dështuar nga <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mesazh nga <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Mesazh i padërguar për <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Po dërgon mesazh te <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Mesazh i dështuar për <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mesazh për <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Mesazh i dështuar nga <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>.  Ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mesazh nga <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Mesazh i padërguar për <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Po dërgon mesazh te <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Mesazh i dështuar për <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mesazh për <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Ora: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Mesazhi dështoi. Prek për ta provuar sërish."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Bisedë me <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Fshi subjektin"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Regjistro video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Regjistro një pamje të palëvizshme"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Nxirr fotografi"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Fillo regjistrimin në video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Kalo në kamerën me ekran të plotë"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Ndërro mes kamerës para dhe mbrapa"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Ndalo regjistrimin dhe bashkëngjit video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Ndalo regjistrimin e videos"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Foto me mesazhe"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotografi u ruajtën tek albumi \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotografi u ruajt tek albumi \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video u ruajtën tek albumi \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video u ruajt tek albumi \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> bashkëngjitje u ruajtën tek albumi\"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bashkëngjitje u ruajt tek albumi \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bashkëngjitje u ruajtën tek \"Shkarkimet\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bashkëngjitje u ruajt tek \"Shkarkimet\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bashkëngjitje u ruajtën</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bashkëngjitje u ruajt</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bashkëngjitje nuk mund të ruheshin</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bashkëngjitje nuk mund të ruhej</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Bashkëgjitje MMS e ruajtur"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Cilësimet"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arkivuar"</string>
+    <string name="action_close" msgid="1840519376200478419">"Mbyll"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Të përparuara"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Korrigjo"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Njoftime"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Zëri"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Hesht"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Dridh"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"I bllokuar"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Raportet e dorëzimit të SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Kërko një raport dorëzimi për çdo SMS që dërgon"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Gjej automatikisht"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Gjej automatikisht mesazhe MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Gjetje automatike në roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Merr automatikisht mesazhin MMS kur je në roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Mesazhe në grup"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Përdor \"MMS\" për të dërguar një mesazh të vetëm kur ka shumë marrës"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Aplikacioni me parazgjedhje i SMS-ve"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Aplikacioni me parazgjedhje i SMS-ve"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Numri yt i telefonit"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"E panjohur"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Tingujt e mesazheve dalëse"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Hidh SMS-të"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Hidhi të dhënat SMS të papërpunuara në skedarin e hapësirës së jashtme ruajtëse"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Hidh MMS-të"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Hidhi të dhënat MMS të papërpunuara në skedarin e hapësirës së jashtme ruajtëse"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Sinjalizimi pa tel"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Opsionet e mesazhit"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopjo tekstin"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Shiko detajet"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Fshi"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Përpara"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Detajet e mesazhit"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Shkruaj: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Mesazh me tekst"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mesazh multimedial"</string>
+    <string name="from_label" msgid="1947831848146564875">"Nga: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Për: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Dërguar: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Marrë: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Subjekti: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Madhësia: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Përparësia: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"Karta SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"E lartë"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normale"</string>
+    <string name="priority_low" msgid="7398724779026801851">"E ulët"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"Numri i kartës SIM: <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Adresë e fshehur e dërguesit"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Nuk mund të dërgojë mesazh kur ngarkon bashkëngjitje."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Nuk mund ta ngarkojë bashkëngjitjen. Provo sërish."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Rrjeti nuk është gati. Provo përsëri."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Fshi tekstin"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Kalo mes futjes së tekstit dhe numrave"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Shto më shumë pjesëmarrës"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Konfirmo pjesëmarrësit"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Fillo bisedë të re"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Përzgjidh këtë artikull"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Luaj video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Kontaktet dhe opsionet"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Korrigjo"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Kontaktet dhe opsionet"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Të përgjithshme"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Kontakte në këtë bisedë"</string>
+    <string name="action_call" msgid="6596167921517350362">"Bëj telefonatë"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Dërgo mesazh"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Dërgo mesazh&lt;br/&gt;&lt;small&gt;nga <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Dërgo fotografitë</item>
+      <item quantity="one">Dërgo fotografinë</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Dërgo audiot</item>
+      <item quantity="one">Dërgo audion</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Dërgo videot</item>
+      <item quantity="one">Dërgo videon</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Dërgo kartat e kontaktit</item>
+      <item quantity="one">Dërgo kartën e kontaktit</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Dërgo bashkëngjitjet</item>
+      <item quantity="one">Dërgo bashkëngjitjen</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> bashkëngjitje gati për dërgim</item>
+      <item quantity="one">Një bashkëngjitje gati për dërgim</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Dërgo përshtypjet"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Shiko në Dyqanin \"Luaj me Google\""</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Informacion mbi versionin"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Versioni %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenca me burim informacioni të hapur"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Njoftime"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"U arrit kufiri i bashkëngjitjeve"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Dështoi në ngarkimin e bashkëngjitjes."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Shto te kontaktet?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Shto kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subjekti"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subjekti: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Po ngarkon kartën e kontaktit"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Nuk arriti të ngarkonte kartën e kontakteve"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Shiko kartën e kontaktit"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakte</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kartat e kontakteve"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Ditëlindje"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Shënime"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Transfero mesazhin"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Përgjigju"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Funksioni \"SMS\" u çaktivizua"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Për të dërguar, caktoje \"Mesazhet\" si aplikacionin me parazgjedhje të SMS-ve"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Caktoje \"Mesazhet\" si aplikacionin me parazgjedhje të SMS-ve"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Ndrysho"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Për të pranuar mesazhe, caktoje \"Mesazhet\" si aplikacionin me parazgjedhje të SMS-ve"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Nuk u përzgjodh kartë e preferuar SIM për dërgimin e mesazheve SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Ky aplikacion nuk lejohet nga zotëruesi i pajisjes."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Në rregull!"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Shumë pjesëmarrës në një bisedë"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Kontakte të pavlefshme</item>
+      <item quantity="one">Kontakt i pavlefshëm</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Nuk arriti të ngarkonte pamjen e kamerës"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ti: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draft"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Pasi të fillosh një bisedë të re, do ta shikosh të listuar këtu"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Bisedat e arkivuara shfaqen këtu"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Po ngarkon bisedat…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Fotografi"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Klip audioje"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kartë kontakti"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Zhbëj"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Provo përsëri"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Fut një emër kontakti ose numër telefoni për të nisur një mesazh të ri"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blloko"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blloko <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Zhblloko <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Të bllokohet <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Do të vazhdosh të marrësh mesazhe nga ky numër, por nuk do të njoftohesh më. Kjo bisedë do të arkivohet."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Kontaktet e bllokuara"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ZHBLLOKO"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Kontaktet e bllokuara"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Zgjidh imazh nga biblioteka e dokumenteve"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Po dërgon mesazhin"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Mesazhi u dërgua"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Të dhënat celulare janë të çaktivizuara. Kontrollo cilësimet."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Nuk mund të dërgojë mesazhe në modalitetin \"në aeroplan\""</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Mesazhi nuk u arrit të dërgohej"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Mesazhi u shkarkua"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Të dhënat celulare janë të çaktivizuara. Kontrollo cilësimet."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Nuk mund të shkarkojë mesazhe në modalitetin \"në aeroplan\""</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Mesazhi nuk u arrit të shkarkohej"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Një"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dy"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tre"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Katër"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Pesë"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Gjashtë"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Shtatë"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Tetë"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nëntë"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Mesazhi nuk mund të dërgohet me <xliff:g id="CARRIERNAME">%1$s</xliff:g> - gabimi <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Mesazhi nuk mund të dërgohet me një operator celular të panjohur - gabimi <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Transfero: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Mesazhi nuk u dërgua - shërbimi nuk është i aktivizuar në rrjet"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Mesazhi nuk u dërgua - adresë e pavlefshme vendmbërritje"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Mesazhi nuk u dërgua - mesazh i pavlefshëm"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Mesazhi nuk u dërgua - përmbajtje e pambështetur"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Mesazhi nuk u dërgua - mesazh i pambështetur"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Mesazhi nuk u dërgua: shumë i madh"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Mesazh i ri"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Shiko"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Imazh"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Nuk arriti të gjente një aplikacion të përshtatshëm"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Hiq marrësin"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Mesazh i ri"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Anulo"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Redakto pikën e qasjes"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Nuk është vendosur"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Emri"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN-ja"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC-ja"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Përfaqësuesi i MMS-ve"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Porta e MMS-ve"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC-ja"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Lloji i APN-së"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Fshi APN-në"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN e re"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Ruaj"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Injoro"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Fusha \"Emri\" nuk të lihet bosh."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN-ja nuk mund të lihet bosh."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Fusha e MCC-së duhet të ketë 3 shifra."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Fusha e MNC-së duhet të ketë 2 ose 3 shifra."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Po restauron cilësimet e APN-së me parazgjedhje."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Rivendos në parazgjedhje"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Rivendosja e cilësimeve të APN-së me parazgjedhje përfundoi."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Pa titull"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Emrat e Pikës së Qasjes"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN-të"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN e re"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Cilësimet e Emrit të Pikës së Qasjes nuk mund të përdoren për këtë përdorues"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Të kopjohet në kujtesën e fragmenteve"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopjo"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"për <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Të përgjithshme"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Të përparuara"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Cilësimet e përgjithshme"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Cilësimet e përparuara"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"Emri i kartës SIM: \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Dërgoju mesazhe SMS të gjithë marrësve. Vetëm ti do të marrësh përgjigje"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Dërgoju një MMS të vetme, të gjithë marrësve"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Numër i panjohur"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Mesazh i ri."</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Mesazh i ri."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Përzgjedhësi i kartës SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> i përzgjedhur, përzgjedhësi i kartës SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Redakto subjektin"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Përzgjidh kartën SIM ose redakto subjektin"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Prek dhe mbaj shtypur për të regjistruar audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Fillo bisedë të re"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mesazhet"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Lista e Mesazheve"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mesazhet"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Mesazh i ri"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Lista e bisedave"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Po ngarkon bisedat"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Po ngarkon mesazhet"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Shiko më shumë biseda"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Shiko më shumë mesazhe"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Biseda është fshirë"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Biseda u fshi. Prek për të shfaqur një bisedë tjetër te \"Mesazhet\""</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"I bllokuar"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"I zhbllokuar"</string>
+    <string name="db_full" msgid="8459265782521418031">"Hapësira ruajtëse është e vogël. Disa të dhëna mund të humbin."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Përzgjidh bashkëngjitje"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Konfirmo përzgjedhjen"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"U përzgjodhën <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Hiq një ose më shumë bashkëngjitje dhe provo sërish."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Mund të provosh ta dërgosh mesazhin, por mund të mos dërgohet pa hequr një ose disa bashkëngjitje."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Mund të dërgosh vetëm një video për çdo mesazh. Hiqi videot shtesë dhe provo përsëri."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mesazhet dështuan në ngarkimin e bashkëngjitjes."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Dërgoje gjithsesi"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Nuk arriti të fillonte bisedën"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> u zgjodh"</string>
+</resources>
diff --git a/res/values-sr/arrays.xml b/res/values-sr/arrays.xml
new file mode 100644
index 0000000..f099488
--- /dev/null
+++ b/res/values-sr/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"без наслова"</item>
+    <item msgid="272485471009191934">"нема наслова"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Да"</item>
+    <item msgid="6049132459802288033">"Не"</item>
+    <item msgid="3084376867445867895">"Потврди"</item>
+    <item msgid="3155097332660174689">"Хе хе"</item>
+    <item msgid="2611328818571146775">"Хвала"</item>
+    <item msgid="4881335087096496747">"Слажем се"</item>
+    <item msgid="2422296858597420738">"Фино"</item>
+    <item msgid="4805581752819452687">"Стижем ускоро"</item>
+    <item msgid="4746700499431366214">"Добро, јавићу ти се касније"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
new file mode 100644
index 0000000..a1262a0
--- /dev/null
+++ b/res/values-sr/strings.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Размена порука"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Размена порука"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Изаберите преписку"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Подешавања"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Пошаљи поруку"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Додај прилог"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Помоћ"</string>
+    <string name="welcome" msgid="2857560951820802321">"Добро дошли"</string>
+    <string name="skip" msgid="7238879696319945853">"Прескочи"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Следеће &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Даље"</string>
+    <string name="exit" msgid="1905187380359981199">"Изађи"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Подешавања &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Подешавања"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Размена порука тражи дозволу за SMS, телефон и контакте."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Можете да мењате дозволе у одељку Подешавања &gt; Апликације &gt; Размена порука &gt; Дозволе."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Можете да мењате дозволе у одељку Подешавања, Апликације, Размена порука, Дозволе."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Често контактирани"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Сви контакти"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Пошаљи на <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Сними слику или видео снимак"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Избор слика са овог уређаја"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Сними звук"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Изаберите слику"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Изабрали сте медијски садржај."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Опозвали сте избор медијског садржаја."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Изабраних: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"слика <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"слика"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Снимање звука"</string>
+    <string name="action_share" msgid="2143483844803153871">"Дели"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Управо сад"</string>
+    <string name="posted_now" msgid="867560789350406701">"Сада"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> мин</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> мин</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> мин</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> сат</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> сата</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> сати</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> дан</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> дана</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> дана</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> недеље</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> недеље</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> недеља</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> месеца</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> месеца</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> месеци</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> године</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> године</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> година</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Порука класе 0"</string>
+    <string name="save" msgid="5081141452059463572">"Сачувај"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Понестаје простора на уређају. Апликација за размену порука ће аутоматски обрисати старије поруке да би ослободила простор."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Понестаје складишног простора"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Размена порука можда неће моћи да шаље нити прима поруке док још простора не буде доступно на уређају."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Понестаје меморије за SMS. Можда ћете морати да избришете поруке."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Потврдите број телефона"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Овим једнократним кораком обезбеђујете да Размена порука правилно испоручује групне поруке."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Број телефона"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Избриши све поруке са медијским садржајем"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Избриши поруке старије од <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Аутоматски бриши поруке старије од <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Игнориши"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Желите ли да избришете све поруке са медијским садржајем?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Желите ли да избришете поруке старије од <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Желите ли да избришете поруке старије од <xliff:g id="DURATION">%s</xliff:g> и да укључите аутоматско брисање?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> каже"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Рекли сте"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Порука од корисника <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Послали сте поруку"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Шаље се..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Слање није успело. Додирните да бисте покушали поново."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Слање није успело. Покушавамо поново…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Пошаљите поново или избришите"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Упутите гласовни позив службама за хитне случајеве. Слање SMS-а тренутно није успело."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Није успело"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Нова MMS порука за преузимање"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Нова MMS порука"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Преузимање није успело"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Додирните да бисте покушали поново"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Додирните да бисте преузели"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Преузмите или избришите"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Преузима се..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Порука је истекла или није доступна"</string>
+    <string name="mms_info" msgid="3402311750134118165">"величина: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, истиче: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Слање није могуће. Прималац није важећи."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Услуга није активирана у мрежи"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Слање није могуће због проблема са мрежом"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Порука је истекла или није доступна"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Без наслова)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Непознати пошиљалац"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Испоручено"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Није могуће преузети поруку <xliff:g id="SUBJECT">%1$s</xliff:g> пошиљаоца <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Није могуће довршити операцију у вези са базом података због недостатка меморије"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Порука није послата"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Неке поруке нису послате у Размени порука"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзацији</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзације</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзација</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Порука није преузета"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Неке поруке нису преузете у Размени порука"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзацији</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзације</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> поруке(а) у <xliff:g id="CONVERSATIONS">%d</xliff:g> конверзација</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Порука на <xliff:g id="NUMBER">%1$s</xliff:g> није послата"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Упутите гласовни позив службама за хитне случајеве. Слање SMS-а на <xliff:g id="NUMBER">%1$s</xliff:g> тренутно није успело."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> нова порука</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> нове поруке</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> нових порука</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Покрени"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камера није доступна"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камера није доступна"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Снимање видео снимака није доступно"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Чување медија није могуће"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Није успело снимање слике"</string>
+    <string name="back" msgid="1477626055115561645">"Назад"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архивирано"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Избриши"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архивирај"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Опозови архивирање"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Искључи обавештења"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Укључи обавештења"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Додај контакт"</string>
+    <string name="action_download" msgid="7786338136368564146">"Преузми"</string>
+    <string name="action_send" msgid="377635240181672039">"Пошаљи"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Избриши"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Желите да избришете ову поруку?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ова радња не може да се опозове."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Избриши"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Желите ли да избришете ове конверзације?</item>
+      <item quantity="few">Желите ли да избришете ове конверзације?</item>
+      <item quantity="other">Желите ли да избришете ове конверзације?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Избриши"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Откажи"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Прима"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Изаберите више слика"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Потврди избор"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Снимање звука није успело. Покушајте поново."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Пуштање звука није успело. Покушајте поново."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Чување звука није успело. Покушајте поново."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Додирните и задржите"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Слика"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудио исечак"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Видео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Картица контакта"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Преузми"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Одговори преко SMS-а"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Одговори MMS-ом"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Одговорите"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> учесник</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> учесника</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> учесника</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ја"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Контакт је блокиран и архивиран"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Контакт је деблокиран и архивирање је опозвано"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Архивирано: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Опозвано је архивирање за: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Обавештења су искључена"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Обавештења су укључена"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Све је спремно. Додирните Пошаљи поново."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Размена порука је подешена као подразумевана апликација за SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Одбаци прилоге</item>
+      <item quantity="few">Одбаци прилоге</item>
+      <item quantity="other">Одбаци прилоге</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Аудио прилог"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Пусти аудио прилог"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Пауза"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> вам шаље нову поруку: <xliff:g id="MESSAGE">%2$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Није примљена порука од корисника <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Порука од корисника <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Порука није послата кориснику <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Шаље се порука кориснику <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Није успело слање поруке кориснику <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Порука кориснику <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Није примљена порука од корисника <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Порука од корисника <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Порука која није послата групи <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Шаље се порука групи <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Није успело слање поруке групи <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Порука групи <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Време: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Слање поруке није успело. Додирните да бисте поново покушали."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Конверзација са учесницима <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Брисање наслова"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Снимите видео"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Снимите слику"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Снимите слику"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Почните да снимате видео"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Пређите на камеру целог екрана"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Пребацујте са предње на задњу камеру и обрнуто"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Заустави снимање и приложи видео"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Заустави снимање звука"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Слике из Размене порука"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> слика је сачувана у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> слике су сачуване у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> слика је сачувано у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> видео је сачуван у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> видео снимка су сачувана у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> видео снимака је сачувано у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> прилог је сачуван у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> прилога су сачувана у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> прилога је сачувано у албуму „<xliff:g id="ALBUMNAME_3">%s</xliff:g>“</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> прилог је сачуван у директоријуму „Преузимања“</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> прилога су сачувана у директоријуму „Преузимања“</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прилога је сачувано у директоријуму „Преузимања“</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> прилог је сачуван</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> прилога су сачувана</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> прилога је сачувано</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Нисмо успели да сачувамо <xliff:g id="QUANTITY_1">%d</xliff:g> прилог</item>
+      <item quantity="few">Нисмо успели да сачувамо <xliff:g id="QUANTITY_1">%d</xliff:g> прилога</item>
+      <item quantity="other">Нисмо успели да сачувамо <xliff:g id="QUANTITY_1">%d</xliff:g> прилога</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Сачувани прилог MMS-а"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Подешавања"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архивирано"</string>
+    <string name="action_close" msgid="1840519376200478419">"Затвори"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Напредно"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Отклањање грешака"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Обавештења"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Звук"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Нечујно"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Вибрација"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Блокирано"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Извештаји о испоруци SMS-ова"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Захтевајте извештај о испоруци за сваки послати SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Аутоматско преузимање"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Аутоматско преузимање MMS порука"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Аутоматски преузимај у ромингу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Аутоматски преузимај MMS у ромингу"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Групна размена порука"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Користите MMS за слање једне поруке када постоји више прималаца"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Подразумевана апликација за SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Подразумевана апликација за SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Број телефона"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Непознато"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Звукови за одлазне поруке"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Направи сирову копију SMS-а"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Направи сирову копију необрађених података примљеног SMS-а у датотеци спољног складишног простора"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Направи сирову копију MMS-а"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Направи сирову копију необрађених података примљеног MMS-а у датотеци спољног складишног простора"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Обавештења преко мобилне мреже"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Опције поруке"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Копирај текст"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Погледајте детаље"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Избриши"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Проследи"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Детаљи поруке"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Тип: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мултимедијална порука"</string>
+    <string name="from_label" msgid="1947831848146564875">"Од: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Коме: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Послато: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Примљено: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Наслов: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Величина: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Приоритет: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM картица: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Висок"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Нормалан"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Низак"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"Отвор за SIM картицу <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Скривена адреса пошиљаоца"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Не можете да пошаљете поруку док се прилози учитавају."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Учитавање прилога није успело. Покушајте поново."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Мрежа није спремна. Покушајте поново."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Избриши текст"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Пребацивање између уноса текста и бројева"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Додај још учесника"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Потврди учеснике"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Започни нову конверзацију"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Изаберите ову ставку"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Пусти видео"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Људи и опције"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Отклони грешке"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Људи и опције"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Опште"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Људи у овој конверзацији"</string>
+    <string name="action_call" msgid="6596167921517350362">"Позови"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Пошаљите поруку"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Пошаљите поруку&lt;br/&gt;&lt;small&gt;са картице <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Пошаљите слике</item>
+      <item quantity="few">Пошаљите слике</item>
+      <item quantity="other">Пошаљите слике</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Пошаљите аудио снимке</item>
+      <item quantity="few">Пошаљите аудио снимке</item>
+      <item quantity="other">Пошаљите аудио снимке</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Пошаљите видео снимке</item>
+      <item quantity="few">Пошаљите видео снимке</item>
+      <item quantity="other">Пошаљите видео снимке</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Пошаљите картице контаката</item>
+      <item quantity="few">Пошаљите картице контаката</item>
+      <item quantity="other">Пошаљите картице контаката</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Пошаљите прилоге</item>
+      <item quantity="few">Пошаљите прилоге</item>
+      <item quantity="other">Пошаљите прилоге</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прилог је спреман за слање</item>
+      <item quantity="few"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прилога су спремна за слање</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> прилога је спремно за слање</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Пошаљи повратне информације"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Прикажи у Google Play продавници"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Информације о верзији"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Верзија %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Лиценце отвореног кода"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Обавештења"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Ограничење за прилоге је достигнуто"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Учитавање прилога није успело."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Желите ли да додате у контакте?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Додај контакт"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Наслов"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Наслов: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Учитава се картица контакта"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Учитавање картице контакта није успело"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Погледајте картицу контакта"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> контакт</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> контакта</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контаката</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Картице контаката"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Рођендан"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Белешке"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Проследите поруку"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Одговорите"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS је онемогућен"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Да бисте слали поруке, подесите Размену порука као подразумевану апликацију за SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Подесите Размену порука као подразумевану апликацију за SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Промени"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Да бисте примали поруке, подесите Размену порука као подразумевану апликацију за SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Није изабран жељени SIM за слање SMS-ова"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Власник уређаја не дозвољава ову апликацију."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Потврди"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Превише учесника у конверзацији"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Неважећи контакти</item>
+      <item quantity="few">Неважећи контакти</item>
+      <item quantity="other">Неважећи контакти</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Учитавање слике са камере није успело"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ви: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Недовршена порука"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Када започнете нову конверзацију, видећете је наведену овде"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Овде се појављују архивиране преписке"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Преписке се учитавају..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Слика"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудио клип"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Видео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Картица контакта"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Опозови"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Покушај поново"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Унесите име или број телефона контакта да бисте започели нову поруку"</string>
+    <string name="action_block" msgid="9032076625645190136">"Блокирај"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Блокирај <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Деблокирај <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Желите ли да блокирате <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"И даље ћете примати поруке са овог броја, али нећете више добијати обавештења. Ова преписка ће бити архивирана."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Блокирани контакти"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ДЕБЛОКИРАЈ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Блокирани контакти"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Изаберите слику из библиотеке докумената"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Порука се шаље"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Порука је послата"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Подаци за мобилне уређаје су искључени. Проверите подешавања."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Слање порука није могуће у Режиму рада у авиону"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Порука није послата"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Порука је преузета"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Подаци за мобилне уређаје су искључени. Проверите подешавања."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Није могуће преузимати поруке у режиму рада у авиону"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Преузимање поруке није успело"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Нула"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Један"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Два"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Три"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Четири"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Пет"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Шест"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Седам"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Осам"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Девет"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Није могуће послати поруку помоћу мобилног оператера <xliff:g id="CARRIERNAME">%1$s</xliff:g>, грешка <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Није могуће послати поруку помоћу непознатог мобилног оператера, грешка <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Порука није послата: услуга није активирана на мрежи"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Порука није послата: неважећа одредишна адреса"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Порука није послата: неважећа порука"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Порука није послата: неподржани садржај"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Порука није послата: неподржана порука"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Порука није послата: превелика је"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Нова порука"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Прикажи"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Слика"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Проналажење одговарајуће апликације није успело"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Уклањање примаоца"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Нова порука"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Откажи"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Измените приступну тачку"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Није подешено"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Назив"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Назив приступне тачке"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS прокси"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS порт"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Тип назива приступне тачке"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Избриши назив приступне тачке"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Нов назив приступне тачке"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Сачувај"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Одбаци"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Поље Назив не сме да буде празно."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Поље Назив приступне тачке не сме да буде празно."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Поље MCC мора да садржи 3 цифре."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Поље MNC мора да садржи 2 или 3 цифре."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Враћање подразумеваних подешавања назива приступне тачке."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Ресетуј подразумеване вредности"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Ресетовање подразумеваних подешавања назива приступне тачке је довршено."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Ненасловљено"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Називи приступних тачака"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Називи приступних тачака"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Нов назив приступне тачке"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Подешавања назива приступне тачке нису доступна за овог корисника"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Желите ли да копирате у привремену меморију?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Копирај"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"на картицу <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Опште"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Напредно"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Општа подешавања"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Напредна подешавања"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"„<xliff:g id="SIM_NAME">%s</xliff:g>“ SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Шаљите појединачне SMS поруке свим примаоцима. Само ви ћете добијати одговоре"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Пошаљите један MMS свим примаоцима"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Непознат број"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Нова порука"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Нова порука."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Бирач SIM картице"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Изабран је <xliff:g id="SIM_0">%1$s</xliff:g>, бирач SIM картица"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Измени наслов"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Изабери SIM или измени наслов"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Додирните и задржите за снимање звука"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Започни нову конверзацију"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Размена порука"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Листа из Размене порука"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Размена порука"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Нова порука"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Листа преписки"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Учитавају се конверзације"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Учитавају се поруке"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Прикажи још конверзација"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Прикажи још порука"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Конверзација је избрисана"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Конверзација је избрисана. Додирните да бисте приказали неку другу конверзацију Размене порука"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Блокирано"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Деблокирано"</string>
+    <string name="db_full" msgid="8459265782521418031">"Нема довољно меморијског простора. Неки подаци ће можда бити изгубљени."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Изабери прилоге"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Потврди избор"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Изабраних: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Уклоните један прилог или више њих и покушајте поново."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Можете да покушате да пошаљете поруку, али можда неће бити испоручена ако не уклоните један прилог или више њих."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Можете да пошаљете само један видео по поруци. Уклоните друге видео снимке и покушајте поново."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Размена порука није успела да учита прилог."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Ипак пошаљи"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Започињање преписке није успело"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Изабрали сте <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-sv/arrays.xml b/res/values-sv/arrays.xml
new file mode 100644
index 0000000..8f03e4b
--- /dev/null
+++ b/res/values-sv/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"inget ämne"</item>
+    <item msgid="272485471009191934">"inget ämne"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ja"</item>
+    <item msgid="6049132459802288033">"Nej"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Tack"</item>
+    <item msgid="4881335087096496747">"Jag accepterar"</item>
+    <item msgid="2422296858597420738">"Nice"</item>
+    <item msgid="4805581752819452687">"På väg"</item>
+    <item msgid="4746700499431366214">"OK, jag återkommer senare"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
new file mode 100644
index 0000000..01d5820
--- /dev/null
+++ b/res/values-sv/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Sms/mms"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Sms/mms"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Välj konversation"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Inställningar"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Skicka meddelande"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Lägg till en bilaga"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Hjälp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Välkommen"</string>
+    <string name="skip" msgid="7238879696319945853">"Hoppa över"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Nästa &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Nästa"</string>
+    <string name="exit" msgid="1905187380359981199">"Stäng"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Inställningar &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Inställningar"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Meddelanden behöver ha åtkomst till Sms, Telefon och Kontakter."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Du kan ändra behörigheterna i Inställningar &gt; Appar &gt; Meddelanden &gt; Behörigheter."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Du kan ändra behörigheterna i Inställningar, Appar, Meddelanden, Behörigheter."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Frekventa"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Alla kontakter"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Skicka till <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Ta bilder eller spela in video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Välj bilder från den här enheten"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Spela in ljud"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Välj foto"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Video-/bildobjektet har markerats."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Video-/bildobjektet har avmarkerats."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> har valts"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"bild <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"bild"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Spela in ljud"</string>
+    <string name="action_share" msgid="2143483844803153871">"Dela"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Nyss"</string>
+    <string name="posted_now" msgid="867560789350406701">"Nu"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> timmar</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> timme</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dagar</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> veckor</item>
+      <item quantity="one">en vecka</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> månader</item>
+      <item quantity="one">en månad</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> år</item>
+      <item quantity="one">ett år</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Meddelande, klass 0"</string>
+    <string name="save" msgid="5081141452059463572">"Spara"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Det finns ont om utrymme på enheten. Om du skickar och tar emot sms kommer äldre sms att raderas för att göra plats."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Lagringsutrymmet börjar ta slut"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Du kan behöva frigöra utrymme på enheten för att kunna skicka eller ta emot sms med Meddelanden."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Lagringsutrymmet för sms är fullt. Du kan behöva ta bort sms."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Bekräfta ditt telefonnummer"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Genom detta engångssteg säkerställer du att dina gruppmeddelanden levereras som de ska med Meddelanden."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefonnummer"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Ta bort alla meddelanden med mediefiler"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Ta bort meddelanden som är äldre än <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Ta automatiskt bort meddelanden som är äldre än <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ignorera"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Vill du ta bort alla meddelanden med media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Vill du ta bort meddelanden som är äldre än <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Vill du ta bort meddelanden som är äldre än <xliff:g id="DURATION">%s</xliff:g> och aktivera automatisk borttagning?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> sade"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Du sade"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Meddelande från <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Du har skickat ett meddelande"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Skickar …"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Det gick inte att skicka. Tryck om du vill försöka igen."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Det gick inte att skicka. Försöker igen ..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Skicka igen eller ta bort"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Ring larmcentralen. Det gick inte att skicka ett sms just nu."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Misslyckades"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Nya MMS att ladda ned"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Nytt MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Nedladdningen genomfördes inte"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tryck om du vill försöka igen"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Ladda ned genom att trycka"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Ladda ned eller radera"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Hämtar ..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Meddelandet har upphört att gälla eller är inte tillgängligt"</string>
+    <string name="mms_info" msgid="3402311750134118165">"storlek: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, finns kvar till: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Det gick inte att skicka. Mottagaren är inte giltig."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Tjänsten är inte aktiverad i nätverket"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Det gick inte att skicka på grund av nätverksproblem"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Meddelandet har upphört att gälla eller är inte tillgängligt."</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Inget ämne)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Okänd avsändare"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Levererat"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Det gick inte att ladda ned meddelandet <xliff:g id="SUBJECT">%1$s</xliff:g> från <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Det gick inte att slutföra åtgärden i databasen på grund av för låg minneskapacitet"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Meddelandet har inte skickats"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Vissa meddelanden skickades inte i Meddelanden"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> meddelanden i <xliff:g id="CONVERSATIONS">%d</xliff:g> konversationer</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> meddelanden i en konversation</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Meddelandet har inte laddats ned"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Vissa meddelanden laddades inte ned i Meddelanden"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> meddelanden i <xliff:g id="CONVERSATIONS">%d</xliff:g> konversationer</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> meddelanden i en konversation</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Meddelandet till <xliff:g id="NUMBER">%1$s</xliff:g> skickades inte"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Ring larmcentralen. Det gick inte att skicka ett sms till <xliff:g id="NUMBER">%1$s</xliff:g> just nu."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> nya meddelanden</item>
+      <item quantity="one">Nytt meddelande</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Börja"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kameran är inte tillgänglig"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kameran är inte tillgänglig"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Det går inte att spela in video"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Det går inte att spara media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Det går inte att fota"</string>
+    <string name="back" msgid="1477626055115561645">"Föregående"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arkiverat"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Ta bort"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arkivera"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Ångra arkivering"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Inaktivera aviseringar"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Aktivera aviseringar"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Lägg till kontakt"</string>
+    <string name="action_download" msgid="7786338136368564146">"Ladda ned"</string>
+    <string name="action_send" msgid="377635240181672039">"Skicka"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Ta bort"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Vill du ta bort meddelandet?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Åtgärden kan inte ångras."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Ta bort"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Vill du ta bort dessa konversationer?</item>
+      <item quantity="one">Vill du ta bort konversationen?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Ta bort"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Avbryt"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Till"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Markera flera bilder"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Bekräfta ditt val"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Det gick inte att spela in ljud. Försök igen."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Det gick inte att spela upp ljudet. Försök igen."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Det gick inte att spara ljud. Försök igen."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Tryck länge"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Bild"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Ljudklipp"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Visitkort"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Ladda ned"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Svara via sms"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Svara via mms"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Svara"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> deltagare</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> deltagare</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Jag"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakten har blockerats och arkiverats"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakten har återaktiverats och hämtats från arkivet"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> har arkiverats"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> arkiveringar har ångrats"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Aviseringar har inaktiverats"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Aviseringar har aktiverats"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Allt klart. Tryck på Skicka igen."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Meddelanden har angetts som standardapp för sms."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Släng bilagor</item>
+      <item quantity="one">Släng bilaga</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Ljudbilaga"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Spela upp ljudbilaga"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Pausa"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Meddelande från <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Meddelande som inte kunde skickas från <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Meddelande från <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Meddelande som inte har skickats till <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Skickar meddelande till <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Meddelande som inte kunde skickas till <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Meddelande till <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Meddelande som inte kunde skickas från <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Meddelande från <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Meddelande som inte har skickats till <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Skickar meddelande till <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Meddelande som inte kunde skickas till <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Meddelande till <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Tidpunkt: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Det här meddelandet gick inte att skicka. Tryck om du vill försöka igen."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Samtal med <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Radera ämne"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Spela in video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Ta en stillbild"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Ta bild"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Börja spela in video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Byt till fullskärmskamera"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Växla mellan främre och bakre kamera"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Stoppa inspelningen och bifoga en video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Sluta spela in video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Skicka foton med Meddelanden"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> foton har sparats i albumet <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> foto har sparats i albumet <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> videor har sparats i albumet <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video har sparats i albumet <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> bilagor har sparats i albumet <xliff:g id="ALBUMNAME_3">%s</xliff:g></item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bilaga har sparats i albumet <xliff:g id="ALBUMNAME_1">%s</xliff:g></item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bilagor har sparats i Nedladdningar</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bilaga har sparats i Nedladdningar</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> bilagor sparas</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> bilaga har sparats</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Det gick inte att spara <xliff:g id="QUANTITY_1">%d</xliff:g> bilagor</item>
+      <item quantity="one">Det gick inte att spara <xliff:g id="QUANTITY_0">%d</xliff:g> bilaga</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Mms-bilaga har sparats"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Inställningar"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arkiverat"</string>
+    <string name="action_close" msgid="1840519376200478419">"Stäng"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"Mms"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Avancerat"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Felsökning"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Aviseringar"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ljud"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Tyst"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Vibration"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Blockerad"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Sms-leveransrapporter"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Begär en leveransrapport för varje sms du skickar"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Automatisk hämtning"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Hämta mms-meddelanden automatiskt"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Autohämtning vid roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Hämta mms automatiskt vid roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Gruppmeddelanden"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Använd mms för att skicka ett meddelande när det finns flera mottagare"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Standardapp för sms"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Standardapp för sms"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Ditt telefonnummer"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Okänt"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Ljud vid utgående meddelande"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Dumpa sms"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Dumpa rådata för mottagna sms i en extern lagringsfil"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Dumpa mms"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Dumpa rådata för mottagna mms i en extern lagringsfil"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Trådlösa varningar"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Meddelandealternativ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopiera text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Visa mer information"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Ta bort"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Vidarebefordra"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Meddelandeinformation"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Typ: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Sms"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Mms"</string>
+    <string name="from_label" msgid="1947831848146564875">"Från: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Till: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Skickat: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Mottaget: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Ämne: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Storlek: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Prioritet: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Hög"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Låg"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Avsändaradress dold"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Kan inte skicka meddelandet samtidigt som bilagor läses in."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Det gick inte att läsa in bilagan. Försök igen."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Nätverket är inte klart. Försök igen."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Ta bort text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Växla mellan att ange text och siffror"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Lägg till fler deltagare"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Bekräfta deltagare"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Starta ny konversation"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Välj det här objektet"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Spela upp video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Personer och alternativ"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Felsökning"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Personer och alternativ"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Allmänt"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Personer i den här konversationen"</string>
+    <string name="action_call" msgid="6596167921517350362">"Ring ett samtal"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Skicka meddelande"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Skicka meddelandet&lt;br/&gt;&lt;small&gt;från <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Skicka foton</item>
+      <item quantity="one">Skicka foto</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Skicka ljud</item>
+      <item quantity="one">Skicka ljud</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Skicka videor</item>
+      <item quantity="one">Skicka video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Skicka kontaktkort</item>
+      <item quantity="one">Skicka kontaktkort</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Skicka bilagor</item>
+      <item quantity="one">Skicka bilaga</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> bilagor är klara att skicka</item>
+      <item quantity="one">En bilaga är klar att skicka</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Skicka feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Visa i Google Play Butik"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Version"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Version %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Licenser, öppen källkod"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Aviseringar"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Gränsen för bilagor har uppnåtts"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Det gick inte att läsa in bilagan."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Vill du lägga till detta i Kontakter?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Lägg till kontakt"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Ämne"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Ämne: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Läser in visitkort"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Det gick inte att läsa in kontaktkortet"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Visa visitkort"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kontakter</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontaktkort"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Födelsedatum"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Anteckningar"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Vidarebefordra meddelande"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Svara"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+ 1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Sms har inaktiverats"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Ange Meddelanden som standardapp för sms om du vill skicka"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Ange Meddelanden som standardapp för sms"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Ändra"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Ställ in Meddelanden som standardapp för sms om du vill ta emot meddelanden"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Inget SIM-kort har angetts som primärt för att skicka sms"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Appen tillåts inte av enhetsägaren."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"För många deltagare i en konversation"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Ogiltiga kontakter</item>
+      <item quantity="one">Ogiltig kontakt</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Det gick inte att läsa in kamerabild"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Du: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Utkast"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"När du startar en ny konversation listas den här"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arkiverade konversationer visas här"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Läser in konversationer …"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Bild"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Ljudklipp"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Visitkort"</string>
+    <string name="mms_text" msgid="1528791558806015806">"Mms"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Ångra"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Försök igen"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Ange namnet på en kontakt eller ett telefonnummer för att starta ett nytt meddelande"</string>
+    <string name="action_block" msgid="9032076625645190136">"Blockera"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Blockera <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Återaktivera <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vill du blockera <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Du kan fortfarande få meddelanden från det här numret, men du får inga fler aviseringar. Den här konversationen arkiveras."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Blockerade kontakter"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ÅTERAKTIVERA"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Blockerade kontakter"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Välj en bild från dokumentbiblioteket"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Skickar meddelande"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Meddelandet har skickats"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobildata har inaktiverats. Kontrollera inställningarna."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Det går inte att skicka meddelanden i flygplansläge"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Meddelandet kunde inte skickas"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Meddelandet har laddats ned"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobildata har inaktiverats. Kontrollera inställningarna."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Det går inte att ladda ned meddelanden i flygplansläge"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Det gick inte att ladda ned meddelandet"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Noll"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Ett"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Två"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tre"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Fyra"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Fem"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sex"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Sju"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Åtta"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Nio"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Det gick inte att skicka meddelandet med <xliff:g id="CARRIERNAME">%1$s</xliff:g>, fel <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Det gick inte att skicka meddelandet med okänd operatör, fel <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Vidarebefordra: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Meddelandet har inte skickats: tjänsten är inte aktiverad i nätverket"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Meddelandet skickades inte: ogiltig e-postadress"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Meddelandet skickades inte: ogiltigt meddelande"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Meddelandet skickades inte: inget stöd för innehållet"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Meddelandet skickades inte: inget stöd för meddelandet"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Meddelandet skickades inte: för stort"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Nytt meddelande"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Visa"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Bild"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Ingen app för detta hittades"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Ta bort mottagare"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Nytt meddelande"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Avbryt"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Redigera åtkomstpunkt"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Har inte angetts"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Namn"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS-proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS-port"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN-typ"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Ta bort APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Nytt APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Spara"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Ignorera"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Fältet Namn får inte vara tomt."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN får inte vara tomt."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC-fältet måste bestå av 3 siffror."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC-fältet måste bestå av 2 eller 3 siffror."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Återställer standardinställningar för APN."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Återställ standardinställningarna"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Standardinställningar för APN har återställts."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Namnlös"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Åtkomstpunktens namn (APN)"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN:er"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Nytt APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Inställningarna för åtkomstpunktens namn är inte tillgängliga för den här användaren"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Vill du kopiera till urklipp?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopiera"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"till <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Allmänt"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Avancerat"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Allmänna inställningar"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Avancerade inställningar"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM-kortet <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Skicka enskilda sms till alla mottagare. Det är endast du som får de eventuella svaren."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Skicka samma mms till alla mottagare."</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Okänt nummer"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Nytt meddelande"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Nytt meddelande."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM-kortsväljaren"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> har valts, SIM-kortsväljare"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Redigera ämne"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Välj SIM-kort eller redigera ämne"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Tryck länge för att spela in ljud"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Starta ny konversation"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Meddelanden"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Meddelandelista"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Meddelanden"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Nytt meddelande"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Konversationslista"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Konversationer hämtas"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Läser in meddelanden"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Visa fler konversationer"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Visa fler meddelanden"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Konversationen har raderats"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Konversationen raderades. Tryck här om du vill visa en annan konversation i Meddelanden."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Blockerad"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Återaktiverad"</string>
+    <string name="db_full" msgid="8459265782521418031">"Lagringsutrymmet är nästan fullt. All data kanske inte sparas."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Välj bilagor"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Bekräfta ditt val"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> har valts"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Ta bort en eller flera av bilagorna och försök igen."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Du kan testa att skicka meddelandet, men det kanske inte kommer fram om du inte tar bort en eller flera av bilagorna först."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Det går bara att skicka en video per meddelande. Ta bort ytterligare videor och försök igen."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Det gick inte att läsa in bilagan i Meddelanden."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Skicka ändå"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Det gick inte att starta en konversation"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> har valts"</string>
+</resources>
diff --git a/res/values-sw/arrays.xml b/res/values-sw/arrays.xml
new file mode 100644
index 0000000..1641f55
--- /dev/null
+++ b/res/values-sw/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"kichwa hakijaongezwa"</item>
+    <item msgid="272485471009191934">"kichwa hakijaongezwa"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ndiyo"</item>
+    <item msgid="6049132459802288033">"Hapana"</item>
+    <item msgid="3084376867445867895">"Sawa"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Asante"</item>
+    <item msgid="4881335087096496747">"Nakubali"</item>
+    <item msgid="2422296858597420738">"Shwari"</item>
+    <item msgid="4805581752819452687">"Niko njiani"</item>
+    <item msgid="4746700499431366214">"Sawa, nitawasiliana na wewe baadaye"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
new file mode 100644
index 0000000..87b12ae
--- /dev/null
+++ b/res/values-sw/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Utumaji ujumbe"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Utumaji ujumbe"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Chagua mazungumzo"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Mipangilio"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Tuma Ujumbe"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Ongeza kiambatisho"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Usaidizi"</string>
+    <string name="welcome" msgid="2857560951820802321">"Karibu"</string>
+    <string name="skip" msgid="7238879696319945853">"Ruka"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Inayofuata &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Inayofuata"</string>
+    <string name="exit" msgid="1905187380359981199">"Ondoka"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Mipangilio &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Mipangilio"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Programu ya Ujumbe inahitaji ruhusa za SMS, Simu na Anwani."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Unaweza kubadilisha ruhusa katika Mipangilio&gt; Programu&gt; Ujumbe&gt; Ruhusa."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Unaweza kubadilisha ruhusa katika Mipangilio, Programu, Ujumbe, Ruhusa."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Mara kwa mara"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Anwani zote"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Tuma kwa <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Piga picha au urekodi video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Chagua picha kutoka kifaa hiki"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Rekodi sauti"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Chagua picha"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Maudhui yameteuliwa."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Maudhui yameondolewa uteuzi."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> zimechaguliwa"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"picha <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"picha"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Rekodi sauti"</string>
+    <string name="action_share" msgid="2143483844803153871">"Shiriki"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Sasa hivi tu"</string>
+    <string name="posted_now" msgid="867560789350406701">"Sasa"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other">Dakika <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">Dakika <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other">Saa <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">Saa <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other">Siku <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">Siku <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other">wiki <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="one">wiki</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other">miezi <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="one">mwezi</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other">miaka <xliff:g id="COUNT">%d</xliff:g></item>
+      <item quantity="one">mwaka</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Ujumbe wa tabaka 0"</string>
+    <string name="save" msgid="5081141452059463572">"Hifadhi"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Nafasi haitoshi kwenye kifaa. Programu ya Ujumbe itafuta kiotomatiki ujumbe wa zamani ili kuacha nafasi kwenye kifaa."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Nafasi ya kuhafadhi inakaribia kujaa"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Huenda programu ya Ujumbe isitume au kupokea ujumbe hadi nafasi zaidi ipatikane katika kifaa chako."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Hifadhi ya SMS ni ndogo. Itakubidi ufute ujumbe."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Thibitisha nambari yako ya simu"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Hatua hii ya kufanywa mara moja itahakikisha kuwa programu ya Ujumbe itawasilisha ujumbe wako wa kikundi bila tatizo."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Nambari ya simu"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Futa ujumbe wote ulio na picha, sauti au video"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Futa ujumbe uliokaa zaidi ya <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Futa kiotomatiki ujumbe uliokaa zaidi ya <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Puuza"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Je, ungependa kufuta ujumbe wote ulio na maudhui?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Je, ungependa kufuta ujumbe uliokaa zaidi ya <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Je, ungependa kufuta ujumbe uliokaa zaidi ya <xliff:g id="DURATION">%s</xliff:g> na uwashe kufuta kiotomatiki?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> alisema"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ulisema"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Ujumbe kutoka <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Ulituma ujumbe"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Inatuma…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Haikutumwa. Gusa ili ujaribu tena."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Haikutumwa. Jaribu tena..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Tuma tena au ufute"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Tafadhali piga simu ya sauti kwa huduma za dharura. Ujumbe wako haukuweza kupokelewa kwa wakati huu."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Imeshindikana"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Ujumbe mpya wa MMS wa kupakua"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Ujumbe mpya wa MMS"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Haikuweza kupakua"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Gusa ili ujaribu tena"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Gusa ili upakue"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Pakua au ufute"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Inapakua…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Ujumbe umepitwa na wakati au haupo"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ukubwa: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, mwisho: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Haiwezi kutuma. Mpokeaji si sahihi."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Huduma haijaanza kutumika kwenye mtandao."</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Haikutuma kwa sababu ya hitilafu ya mtandao"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Ujumbe umepitwa na wakati au haupo"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Kichwa hakijaongezwa)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Mtumaji asiyejulikana"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Umewasilishwa"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Haikuweza kupakua ujumbe <xliff:g id="SUBJECT">%1$s</xliff:g> kutoka <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Haikuweza kukamilisha utendaji wa hifadhidata kwa sababu ya kumbukumbu ndogo"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Ujumbe haujatumwa"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Baadhi ya ujumbe haukutumwa katika programu ya Ujumbe"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other">Ujumbe <xliff:g id="MESSAGES_1">%d</xliff:g> katika mazungumzo <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="one">Ujumbe <xliff:g id="MESSAGES_0">%d</xliff:g> katika mazungumzo moja</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Ujumbe haujapakuliwa"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Baadhi ya ujumbe haukupakuliwa katika programu ya Ujumbe"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other">Ujumbe <xliff:g id="MESSAGES_1">%d</xliff:g>katika mazungumzo <xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="one">Ujumbe <xliff:g id="MESSAGES_0">%d</xliff:g> katika mazungumzo moja</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Ujumbe kwa <xliff:g id="NUMBER">%1$s</xliff:g> haukutumwa"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Tafadhali piga simu ya sauti kwa huduma za dharura. Ujumbe wako kwa <xliff:g id="NUMBER">%1$s</xliff:g> haukuweza kupokelewa kwa wakati huu."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other">Ujumbe <xliff:g id="MESSAGES">%d</xliff:g> mpya</item>
+      <item quantity="one">Ujumbe mpya</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Anza"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera haipatikani"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera haipatikani"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Kurekodi video hakupatikani"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Haiwezi kuhifadhi maudhui ya picha au video"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Haiwezi kupiga picha"</string>
+    <string name="back" msgid="1477626055115561645">"Nyuma"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Imewekwa kwenye kumbukumbu"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Futa"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Kumbukumbu"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Ondoa kwenye kumbukumbu"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Zima arifa"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Washa arifa"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Ongeza anwani"</string>
+    <string name="action_download" msgid="7786338136368564146">"Pakua"</string>
+    <string name="action_send" msgid="377635240181672039">"Tuma"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Futa"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Je, ungependa kufuta ujumbe huu?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Kitendo hiki hakiwezi kutenduliwa."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Futa"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Ungependa kufuta mazungumzo haya?</item>
+      <item quantity="one">Ungependa kufuta mazungumzo haya?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Futa"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Ghairi"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kwa"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Chagua picha nyingi"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Thibitisha uteuzi"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"<xliff:g id="COUNT">%d</xliff:g>+"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Haiwezi kurekodi sauti. Jaribu tena."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Haiwezi kucheza sauti. Jaribu tena."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Haikuweza kuhifadhi sauti. Jaribu tena."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Gusa na ushikilie"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Picha"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Klipu ya sauti"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kadi ya anwani"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Pakua"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Jibu kupitia SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Jibu kupitia MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Jibu"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other">Washiriki <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">Mshiriki <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Mimi"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Anwani imezuiwa na imewekwa kwenye kumbukumbu"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Anwani imeacha kuzuiliwa na imetolewa kwenye kumbukumbu"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> yamewekwa kwenye kumbukumbu"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> yameondolewa kwenye kumbukumbu"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Arifa zimezimwa"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Arifa zimewashwa"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Imewekwa. Gusa Tuma tena."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Umefaulu kuweka Programu ya Ujumbe kuwa programu ya chaguo-msingi ya SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Tupa viambatisho</item>
+      <item quantity="one">Tupa kiambatisho</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Kiambatisho cha sauti"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Cheza kiambatisho cha sauti"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Sitisha"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Ujumbe kutoka kwa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Ujumbe ulioshindikana kutoka kwa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Ujumbe kutoka <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ujumbe ambao haukutumwa kwa <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Inatuma ujumbe kwa <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Ujumbe ulioshindikana kwa <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Ujumbe kwa <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Ujumbe ulioshindikana kutoka kwa <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Ujumbe kutoka <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ujumbe ambao haukutumwa kwa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Inatuma ujumbe kwa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Ujumbe ulioshindikana kwenda kwa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Ujumbe kwa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saa: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Ujumbe ulishindikana. Gusa ili ujaribu tena."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Mazungumzo na <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Futa kichwa"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Rekodi video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Piga picha ya mnato"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Piga picha"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Anza kurekodi video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Badili utumie kamera ya skrini nzima"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Badili kati ya kamera ya nyuma na mbele"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Acha kurekodi na kuambatisha video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Acha kurekodi video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Picha za programu ya Ujumbe"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">Picha <xliff:g id="QUANTITY_2">%d</xliff:g> zimehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Picha <xliff:g id="QUANTITY_0">%d</xliff:g> imehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">Video <xliff:g id="QUANTITY_2">%d</xliff:g> zimehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one">Video <xliff:g id="QUANTITY_0">%d</xliff:g> imehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">Viambatisho <xliff:g id="QUANTITY_2">%d</xliff:g> vimehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" </item>
+      <item quantity="one">Kiambatisho <xliff:g id="QUANTITY_0">%d</xliff:g> kimehifadhiwa kwenye albamu ya \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">Viambatisho <xliff:g id="QUANTITY_1">%d</xliff:g> vimehifadhiwa kwenye \"Vipakuliwa\"</item>
+      <item quantity="one">Kiambatisho <xliff:g id="QUANTITY_0">%d</xliff:g> kimehifadhiwa kwenye \"Vipakuliwa\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Imehifadhi viambatisho <xliff:g id="QUANTITY_1">%d</xliff:g></item>
+      <item quantity="one">Imehifadhi kiambatisho <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Haikuweza kuhifadhi viambatisho <xliff:g id="QUANTITY_1">%d</xliff:g></item>
+      <item quantity="one">Haikuweza kuhifadhi kiambatisho <xliff:g id="QUANTITY_0">%d</xliff:g></item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Kiambatisho cha MMS kimehifadhiwa"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Mipangilio"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Imewekwa kwenye kumbukumbu"</string>
+    <string name="action_close" msgid="1840519376200478419">"Funga"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Mahiri"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Tatua"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Arifa"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Mlio"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Kimya"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Tetema"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Imezuiwa"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Ripoti za kupokelewa kwa SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Omba ripoti ya kuthibitisha kuwa kila SMS unayotuma imewasilishwa"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Pakua kiotomatiki"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Rejesha ujumbe wa MMS kiotomatiki"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Rejesha kiotomatiki wakati wa kutumia mitandao mingine"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Rejesha MMS kiotomatiki unapotumia mitandao mingine"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Utumaji ujumbe kwa kikundi"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Tumia MMS kutuma ujumbe mmoja wakati kuna wapokeaji wengi"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Programu chaguo-msingi ya SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Programu chaguo-msingi ya SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Nambari yako ya simu"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Isiyojulikana"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Sauti za ujumbe unaotumwa"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Tupa SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Tupa data ghafi za SMS zilizopokelewa kwenye faili ya hifadhi ya nje"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Tupa ujumbe wa MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Tupa data ghafi za ujumbe wa MMS uliopokelewa kwenye faili ya hifadhi ya nje"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Arifa ya dharura"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Chaguo za ujumbe"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Nakili maandishi"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Tazama maelezo"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Futa"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Sambaza"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Maelezo ya ujumbe"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Aina: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Ujumbe wa maandishi"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Ujumbe anuai"</string>
+    <string name="from_label" msgid="1947831848146564875">"Kutoka: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kwa: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Imetumwa: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Imepokelewa: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Kichwa: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Ukubwa: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Kipaumbele: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Juu"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Kawaida"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Chini"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Anwani ya mtumaji iliyofichwa"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Haiwezi kutuma ujumbe wakati inapakiwa viambatisho."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Haiwezi kupakia kiambatisho. Jaribu tena."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Mtandao hauko tayari. Jaribu tena."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Futa ujumbe"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Badili kati ya kuweka maandishi na nambari"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Ongeza washiriki zaidi"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Thibitisha washiriki"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Anzisha mazungumzo mapya"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Chagua bidhaa hii"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Cheza video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Watu na chaguo"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Tatua"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Watu na chaguo"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Jumla"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Watu katika mazungumzo haya"</string>
+    <string name="action_call" msgid="6596167921517350362">"Piga simu"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Tuma ujumbe"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Tuma ujumbe&lt;br/&gt;&lt;small&gt;kutoka <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Tuma picha</item>
+      <item quantity="one">Tuma picha</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Tuma sauti</item>
+      <item quantity="one">Tuma sauti</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Tuma video</item>
+      <item quantity="one">Tuma video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Tuma kadi za anwani</item>
+      <item quantity="one">Tuma kadi ya anwani</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Tuma viambatisho</item>
+      <item quantity="one">Tuma kiambatisho</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">Viambatisho <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> viko tayari kutumwa</item>
+      <item quantity="one">Kiambatisho kimoja kiko tayari kutumwa</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Tuma maoni"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Angalia katika Duka la Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Maelezo kuhusu toleo hili"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Toleo la %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Leseni za programu huria"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Arifa"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Kikomo cha kiambatisho kilifikiwa"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Imeshindwa kupakia kiambatisho."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Ungependa kuongeza kwenye Anwani?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Ongeza Anwani"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Kichwa"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Kichwa: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Inapakia kadi ya anwani"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Haikuweza kupakia kadi ya anwani"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Angalia kadi ya anwani"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other">Anwani <xliff:g id="COUNT_1">%d</xliff:g></item>
+      <item quantity="one">Anwani <xliff:g id="COUNT_0">%d</xliff:g></item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kadi za mawasiliano"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Siku ya kuzaliwa"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Madokezo"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Sambaza ujumbe"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Jibu"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS imezimwa"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Ili utume ujumbe, weka programu ya Ujumbe kuwa programu ya chaguo-msingi ya SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Weka programu ya Ujumbe kuwa programu ya chaguo-msingi ya SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Badilisha"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Ili kupokea ujumbe, weka programu ya Ujumbe iwe programu ya chaguo-msingi ya SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Hakuna SIM inayopendelewa kwa kutuma ujumbe wa SMS iliyochaguliwa"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Programu hii hairuhusiwi na mmiliki kifaa."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"SAWA"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Washiriki wengi mno katika mazungumzo"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Anwani zisizo sahihi</item>
+      <item quantity="one">Anwani isiyo sahihi</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Haikuweza kupakia picha ya kamera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Wewe: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Rasimu"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Utakapoanzisha mazungumzo mapya, utayaona yameorodheshwa hapa"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Mazungumzo yaliyowekwa kwenye kumbukumbu huonekana hapa"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Inapakia mazungumzo..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Picha"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Klipu ya sauti"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kadi ya anwani"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Tendua"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Jaribu tena"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Andika jina la anwani au nambari ya simu ili uanze ujumbe mpya"</string>
+    <string name="action_block" msgid="9032076625645190136">"Zuia"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Zuia <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Ondoa kizuizi kwa <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Ungependa kuzuia <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Utaendelea kupokea ujumbe kutoka nambari hii ila hutapewa arifa tena. Mazungumzo haya yatawekwa kwenye kumbukumbu."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Anwani zilizozuiwa"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ONDOA KIZUIZI"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Anwani zilizozuiwa"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Chagua picha kutoka maktaba ya hati"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Inatuma ujumbe"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Ujumbe umetumwa"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Data ya simu za mkononi imezimwa. Angalia mipangilio yako."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Haiwezi kutuma ujumbe katika Hali ya ndegeni"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Ujumbe haukutumwa"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Ujumbe umepakuliwa"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Data ya simu za mkononi imezimwa. Angalia mipangilio yako."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Haiwezi kupakua ujumbe katika Hali ya ndegeni"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Ujumbe haukuweza kupakuliwa"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Sifuri"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Moja"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Mbili"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tatu"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Nne"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Tano"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sita"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Saba"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Nane"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Tisa"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Huwezi kutuma ujumbe ukitumia <xliff:g id="CARRIERNAME">%1$s</xliff:g>, hitilafu <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Huwezi kutuma ujumbe ukitumia mtoa huduma asiyejulikana, hitilafu <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Ujumbe haukutumwa: huduma haijaanza kutumika kwenye mtandao."</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Ujumbe haujatumwa: anwani ya unakotuma si sahihi"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Ujumbe haujatumwa: ujumbe usio sahihi"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Ujumbe haujatumwa: maudhui yasiyoweza kutumika"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Ujumbe haujatumwa: ujumbe usioweza kutumika"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Ujumbe haujatumwa: ni mkubwa mno"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Ujumbe mpya"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Tazama"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Picha"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Haikuweza kupata programu inayofaa"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Ondoa mpokeaji"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Ujumbe mpya"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Ghairi"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Badilisha mahali pa kufikia"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Haijawekwa"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Jina"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proksi ya MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Mlango wa  MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Aina ya APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Futa APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN Mpya"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Hifadhi"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Tupa"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Sehemu hii haiwezi kuachwa ikiwa haijajazwa."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN haiwezi kuwa tupu."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Sehemu ya MCC lazima iwe na nambari 3."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Sehemu ya MNC lazima iwe na nambari 2 au 3."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Inarejesha mipangilio mbadala ya APN"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Rudisha kwenye chaguo-msingi"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Kuweka upya kwa mipangilio mbadala ya APN kumekamilika"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Haina Kichwa"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Majina ya Lango la Mtandao"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN Mpya"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Mipangilio ya Jina la Lango la Mtandao (APN) haipatikani kwa mtumiaji huyu"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Je, ungependa kunakili kwenye ubao klipu?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Nakili"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"kwa <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Jumla"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Mahiri"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Mipangilio ya jumla"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Mipangilio ya kina"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Tuma ujumbe binafsi wa SMS kwa wapokeaji wote. Wewe tu ndiye utakayepata majibu yoyote"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Tuma MMS moja kwa wapokeaji wote"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Nambari isiyojulikana"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Ujumbe mpya"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Ujumbe mpya."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Kichagua SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> imechaguliwa, Kichagua SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Badilisha kichwa"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Chagua SIM au ubadilishe kichwa"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Gusa na ushikilie ili urekodi sauti"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Anzisha mazungumzo mapya"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Ujumbe"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Orodha ya Ujumbe"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Ujumbe"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Ujumbe mpya"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Orodha ya mazungumzo"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Inapakia mazungumzo"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Inapakia ujumbe"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Tazama mazungumzo zaidi"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Angalia ujumbe zaidi"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Mazungumzo yamefutwa"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Mazungumzo yamefutwa. Gusa ili uonyeshe mazungumzo tofauti ya programu ya Ujumbe"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Amezuiwa"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Ameondolewa kizuizi"</string>
+    <string name="db_full" msgid="8459265782521418031">"Nafasi ya hifadhi ni ndogo. Unaweza kupoteza baadhi ya data."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Chagua viambatisho"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Thibitisha uteuzi"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> vimechaguliwa"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Tafadhali ondoa moja au zaidi ya viambatisho na ujaribu tena."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Unaweza kujaribu kutuma ujumbe wako, lakini huenda usitumwe hadi uondoe kiambatisho kimoja au zaidi."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Unaweza kutuma video moja pekee kwa kila ujumbe. Tafadhali ondoa video za ziada na ujaribu tena."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Programu ya Ujumbe haikupakia kiambatisho."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Tuma tu"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Haikuweza kuanza mazungumzo"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> imechaguliwa"</string>
+</resources>
diff --git a/res/values-ta/arrays.xml b/res/values-ta/arrays.xml
new file mode 100644
index 0000000..9953b60
--- /dev/null
+++ b/res/values-ta/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"தலைப்பு இல்லை"</item>
+    <item msgid="272485471009191934">"தலைப்பு இல்லை"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ஆம்"</item>
+    <item msgid="6049132459802288033">"இல்லை"</item>
+    <item msgid="3084376867445867895">"சரி"</item>
+    <item msgid="3155097332660174689">"ஹிஹி"</item>
+    <item msgid="2611328818571146775">"நன்றி"</item>
+    <item msgid="4881335087096496747">"ஆம்"</item>
+    <item msgid="2422296858597420738">"அருமை"</item>
+    <item msgid="4805581752819452687">"வந்துகொண்டிருக்கிறேன்"</item>
+    <item msgid="4746700499431366214">"பின்னர் அழைக்கிறேன்"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
new file mode 100644
index 0000000..327e454
--- /dev/null
+++ b/res/values-ta/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"மெசேஜ்"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"மெசேஜ்"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"உரையாடலைத் தேர்ந்தெடுக்கவும்"</string>
+    <string name="action_settings" msgid="1329008122345201684">"அமைப்பு"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"செய்தி அனுப்பு"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"இணைப்பைச் சேர்"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"உதவி"</string>
+    <string name="welcome" msgid="2857560951820802321">"நல்வரவு"</string>
+    <string name="skip" msgid="7238879696319945853">"தவிர்"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"அடுத்து &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"அடுத்து"</string>
+    <string name="exit" msgid="1905187380359981199">"வெளியேறு"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"அமைப்புகள் &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"அமைப்புகள்"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"செய்தியிடலுக்கு SMS, ஃபோன் மற்றும் தொடர்புகள் ஆகியவற்றுக்கான அனுமதி தேவை."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"அமைப்புகள் &gt; பயன்பாடுகள் &gt; செய்தியிடல் &gt; அனுமதிகள் என்பதில் அனுமதிகளை மாற்றலாம்."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"அமைப்புகள், பயன்பாடுகள், செய்தியிடல், அனுமதிகள் என்பதில் அனுமதிகளை மாற்றலாம்."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"அடிக்கடி தொடர்புகொண்டவர்கள்"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"எல்லா தொடர்புகளும்"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> க்கு அனுப்பு"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"படங்கள் அல்லது வீடியோவை எடுக்கவும்"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"இந்தச் சாதனத்தில் இருந்து படங்களைத் தேர்வு செய்யவும்"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ஆடியோவைப் பதிவுசெய்"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"படத்தைத் தேர்வுசெய்"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"மீடியா தேர்ந்தெடுக்கப்பட்டது."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"மீடியா தேர்வுநீக்கப்பட்டது."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> தேர்ந்தெடுக்கப்பட்டது"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"படம் <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"படம்"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ஆடியோவைப் பதிவுசெய்"</string>
+    <string name="action_share" msgid="2143483844803153871">"பகிர்"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"சற்றுமுன்"</string>
+    <string name="posted_now" msgid="867560789350406701">"இப்போது"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> நிமிடங்கள்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> நிமிடம்</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> மணிநேரம்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> மணிநேரம்</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> நாட்கள்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> நாள்</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> வாரங்கள்</item>
+      <item quantity="one">ஒரு வாரம்</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> மாதங்கள்</item>
+      <item quantity="one">ஒரு மாதம்</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ஆண்டுகள்</item>
+      <item quantity="one">ஒரு ஆண்டு</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"கிளாஸ் 0 செய்தி"</string>
+    <string name="save" msgid="5081141452059463572">"சேமி"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"சாதனத்தில் இடம் குறைவாக உள்ளது. இடத்தைக் காலியாக்க, செய்தியிடலானது பழைய உரைச் செய்திகளை தானாகவே நீக்கும்."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"சேமிப்பிடம் குறைகிறது"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"உங்கள் சாதனத்தில் கூடுதல் இடம் கிடைக்கும் வரை செய்தியிடல் செய்திகளை அனுப்பாமல் அல்லது பெறாமல் இருக்கக் கூடும்."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS சேமிப்பகம் குறைவாக உள்ளது. நீங்கள் செய்திகளை நீக்க வேண்டியிருக்கலாம்."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"உங்கள் ஃபோன் எண்ணை உறுதிசெய்யவும்"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"இந்த ஒரு முறை செயல்பாடானது, செய்தியிடல் உங்கள் குழுச் செய்திகளைச் சரியாக வழங்குவதை உறுதிப்படுத்தும்."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ஃபோன் எண்"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"மீடியாவுடனான செய்திகளை நீக்கு"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> க்கு முந்தைய செய்திகளை நீக்கு"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> காலத்திற்கு முந்தைய செய்திகளைத் தானாகவே நீக்கு"</string>
+    <string name="ignore" msgid="7063392681130898793">"புறக்கணி"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"மீடியாவுடனான எல்லா செய்திகளையும் நீக்க வேண்டுமா?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> காலத்திற்கு முந்தைய செய்திகளை நீக்க வேண்டுமா?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> காலத்திற்கு முந்தைய செய்திகளை நீக்கி, தானாக நீக்கும் அம்சத்தை இயக்கவா?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> கூறியது"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"நீங்கள் கூறியது"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> இடமிருந்து செய்தி"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"செய்தி அனுப்பியுள்ளீர்கள்"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"அனுப்புகிறது…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"அனுப்பவில்லை. மீண்டும் முயல, தொடவும்."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"அனுப்பவில்லை. மீண்டும் முயல்கிறது…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"மீண்டும் அனுப்பு அல்லது நீக்கு"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"அவசரகால சேவைகளை அழைக்கவும். உங்கள் உரைச் செய்தியை தற்போது வழங்க முடியவில்லை."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"தோல்வி"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"இறக்க, புதிய MMS செய்தி உள்ளது"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"புதிய MMS செய்தி"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"இறக்க முடியவில்லை"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"மீண்டும் முயல, தொடவும்"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"இறக்க, தொடவும்"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"இறக்கு அல்லது நீக்கு"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"இறக்குகிறது…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"செய்தி காலாவதியானது அல்லது இல்லை"</string>
+    <string name="mms_info" msgid="3402311750134118165">"அளவு: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, காலாவதியாகும் தேதி: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"அனுப்ப முடியவில்லை. பெறுநர் விவரம் தவறாக உள்ளது."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"நெட்வொர்க்கில் சேவை இயக்கப்படவில்லை"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"நெட்வொர்க் சிக்கல் காரணமாக அனுப்ப முடியவில்லை"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"செய்தி காலாவதியானது அல்லது இல்லை"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(தலைப்பு இல்லை)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"அறியப்படாத அனுப்புநர்"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"டெலிவரி செய்யப்பட்டது"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> இலிருந்து <xliff:g id="SUBJECT">%1$s</xliff:g> செய்தியைப் பதிவிறக்க முடியவில்லை."</string>
+    <string name="low_memory" msgid="5300743415198486619">"குறைந்த நினைவகம் காரணமாகத் தரவுத்தளச் செயல்பாட்டை முடிக்க முடியவில்லை"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"செய்தி அனுப்பப்படவில்லை"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"செய்தியிடலில் சில செய்திகள் அனுப்பப்படவில்லை"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> உரையாடல்களில் <xliff:g id="MESSAGES_1">%d</xliff:g> செய்திகள் உள்ளன</item>
+      <item quantity="one">ஒரு உரையாடலில் <xliff:g id="MESSAGES_0">%d</xliff:g> செய்திகள் உள்ளன</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"செய்தி இறக்கப்படவில்லை"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"செய்தியிடலில் சில செய்திகள் இறக்கப்படவில்லை"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> உரையாடல்களில் <xliff:g id="MESSAGES_1">%d</xliff:g> செய்திகள் உள்ளன</item>
+      <item quantity="one">ஒரு உரையாடலில் <xliff:g id="MESSAGES_0">%d</xliff:g> செய்திகள் உள்ளன</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g>க்குச் செய்தி அனுப்பப்படவில்லை"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"அவசரகால சேவைகளை அழைக்கவும். <xliff:g id="NUMBER">%1$s</xliff:g>_1க்கு நீங்கள் அனுப்பிய செய்தியை தற்போது வழங்க முடியவில்லை."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> புதிய செய்திகள்</item>
+      <item quantity="one">புதிய செய்தி</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"தொடங்கு"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"கேமரா இல்லை"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"கேமரா இல்லை"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"வீடியோ படமெடுக்க முடியாது"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"மீடியாவைச் சேமிக்க முடியவில்லை"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"படமெடுக்க முடியாது"</string>
+    <string name="back" msgid="1477626055115561645">"முந்தையது"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"காப்பகப்படுத்தப்பட்டன"</string>
+    <string name="action_delete" msgid="4076795795307486019">"நீக்கு"</string>
+    <string name="action_archive" msgid="5437034800324083170">"காப்பிடு"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"காப்பிட வேண்டாம்"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"அறிவிப்புகளை முடக்கு"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"அறிவிப்புகளை இயக்கு"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"தொடர்பைச் சேர்"</string>
+    <string name="action_download" msgid="7786338136368564146">"இறக்கு"</string>
+    <string name="action_send" msgid="377635240181672039">"அனுப்பு"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"நீக்கு"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"இந்தச் செய்தியை நீக்கவா?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"இந்தச் செயலை பின்னர் செயல்தவிர்க்க முடியாது."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"நீக்கு"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">உரையாடல்களை நீக்கவா?</item>
+      <item quantity="one">உரையாடலை நீக்கவா?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"நீக்கு"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ரத்துசெய்"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"பெறுநர்"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"பல படங்களைத் தேர்ந்தெடு"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"தேர்வை உறுதிப்படுத்து"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ஆடியோவைப் பதிவு செய்ய இயலவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ஆடியோவை இயக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ஆடியோவைச் சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"தொட்டுப் பிடித்திருக்கவும்"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"படம்"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ஆடியோ கிளிப்"</string>
+    <string name="notification_video" msgid="4331423498662606204">"வீடியோ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"தொடர்பு கார்டு"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"இறக்கு"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS மூலம் பதிலளி"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS மூலம் பதிலளி"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"பதிலளி"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> பங்கேற்பாளர்கள்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> பங்கேற்பாளர்</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"எனக்கு"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"தொடர்பு தடுக்கப்பட்டு காப்பகப்படுத்தப்பட்டது"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"தொடர்பு தடைநீக்கப்பட்டுள்ளது &amp; பட்டியலில் தோன்றும்"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> காப்பகப்படுத்தப்பட்டன"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> பட்டியலில் தோன்றும்"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"அறிவிப்புகள் முடக்கப்பட்டுள்ளன"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"அறிவிப்புகள் இயக்கப்பட்டுள்ளன"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"எல்லாம் முடிந்தது. மீண்டும் அனுப்பு என்பதைத் தொடவும்."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"செய்தியிடல் இயல்பு SMS பயன்பாடாக அமைக்கப்பட்டது."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">இணைப்புகளை நிராகரி</item>
+      <item quantity="one">இணைப்பை நிராகரி</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ஆடியோ இணைப்பு"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ஆடியோ இணைப்பை இயக்கவும்"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"இடைநிறுத்து"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"செய்தி அனுப்பியவர்: <xliff:g id="SENDER">%1$s</xliff:g> - <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>க்கு அனுப்பிய செய்தி தோல்வி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> அனுப்பிய செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>க்கு அனுப்பப்படாத செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>க்குச் செய்தி அனுப்புகிறது: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>க்கு அனுப்பிய செய்தி தோல்வி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>க்கான செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>க்கு அனுப்பிய செய்தி தோல்வி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> இடமிருந்து செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>க்கு அனுப்பப்படாத செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>க்குச் செய்தி அனுப்புகிறது: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>க்கு அனுப்பிய செய்தி தோல்வி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>க்கான செய்தி: <xliff:g id="MESSAGE">%2$s</xliff:g>. நேரம்: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"செய்தி அனுப்புவதில் தோல்வி. மீண்டும் முயற்சிக்க, தொடவும்."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> உடனான உரையாடல்"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"தலைப்பை நீக்கு"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"வீடியோ எடு"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ஸ்டில் படமெடு"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"படமெடு"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"வீடியோவைப் படமெடு"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"முழுத் திரை கேமராவிற்கு மாறு"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"முன் மற்றும் பின்பக்க கேமராவிற்கு இடையே மாறு"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"பதிவுசெய்வதை நிறுத்தி வீடியோவை இணைக்கவும்"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"வீடியோ பதிவு செய்வதை நிறுத்து"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"செய்தியிடல் படங்கள்"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> படங்கள், \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> படம், \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டது</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> வீடியோக்கள், \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> வீடியோ, \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டது</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> இணைப்புகள், \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> இணைப்பு, \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ஆல்பத்தில் சேமிக்கப்பட்டது</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> இணைப்புகள், \"இறக்கங்கள்\" என்பதில் சேமிக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> இணைப்பு, \"இறக்கங்கள்\" என்பதில் சேமிக்கப்பட்டது</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> இணைப்புகள் சேமிக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> இணைப்பு சேமிக்கப்பட்டது</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> இணைப்புகளைச் சேமிக்க முடியவில்லை</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> இணைப்பைச் சேமிக்க முடியவில்லை</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"சேமித்த MMS இணைப்பு"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"அமைப்பு"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"காப்பகப்படுத்தப்பட்டன"</string>
+    <string name="action_close" msgid="1840519376200478419">"மூடு"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"மேம்பட்டவை"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"பிழைத்திருத்து"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"அறிவிப்புகள்"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ஒலி"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"நிசப்தம்"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"அதிர்வு"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"தடுக்கப்பட்டது"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS டெலிவரி அறிக்கைகள்"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"நீங்கள் அனுப்பும் ஒவ்வொரு SMS க்கும் வழங்கல் அறிக்கையைக் கோரவும்"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"தானாக மீட்டெடு"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"தானாக MMS செய்திகளை மீட்டெடு"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"ரோமிங்கில் தானாக மீட்டெடு"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ரோமிங்கின் போது தானாகவே MMSஐ மீட்டெடு"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"குழு மெசேஜ்"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ஒரு செய்தியைப் பல பெறுநர்களுக்கு அனுப்புவதற்கு MMS ஐப் பயன்படுத்து"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"இயல்புநிலை SMS பயன்பாடு"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"இயல்புநிலை SMS பயன்பாடு"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"மொபைல் எண்"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"தெரியாதது"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"வெளிச்செல்லும் செய்தி ஒலிகள்"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS ஐ நகலெடு"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"பெற்ற SMS அசல் தரவை வெளிப்புறச் சேமிப்பகக் கோப்பில் நகலெடு"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS ஐ நகலெடு"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"பெற்ற MMS அசல் தரவை வெளிப்புறச் சேமிப்பகச் கோப்பில் நகலெடு"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"வயர்லெஸ் விழிப்பூட்டல்கள்"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"செய்தி விருப்பங்கள்"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"உரையை நகலெடு"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"விவரங்களைக் காட்டு"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"நீக்கு"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"முன்னனுப்பு"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"செய்தி விவரங்கள்"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"வகை: "</string>
+    <string name="text_message" msgid="7415419755252205721">"உரைச் செய்தி"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"மல்டிமீடியா செய்தி"</string>
+    <string name="from_label" msgid="1947831848146564875">"அனுப்புநர்: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"பெறுநர்: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"அனுப்பியது: "</string>
+    <string name="received_label" msgid="4442494712757995203">"பெறப்பட்டது: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"தலைப்பு: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"அளவு: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"முன்னுரிமை: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"உயர்தரம்"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"இயல்பு"</string>
+    <string name="priority_low" msgid="7398724779026801851">"குறைந்த தரம்"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"மறைவிலிருக்கும் அனுப்புநர் முகவரி"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"இணைப்புகளை ஏற்றும் போது செய்தியை அனுப்ப முடியாது."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"இணைப்பை ஏற்ற முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"நெட்வொர்க் தயாராக இல்லை. மீண்டும் முயற்சிக்கவும்."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"உரையை நீக்கு"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"உரை மற்றும் எண்களை உள்ளிடுவதன் இடையே மாறு"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"மேலும் பங்கேற்பாளர்களைச் சேர்"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"பங்கேற்பாளர்களை உறுதிப்படுத்தவும்"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"புதிய உரையாடலைத் தொடங்கு"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"இதனைத் தேர்வுசெய்"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"வீடியோவை இயக்கு"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"நபர்களும் விருப்பங்களும்"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"பிழைத்திருத்து"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"நபர்களும் விருப்பங்களும்"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"பொது"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"உரையாடலில் உள்ளவர்கள்"</string>
+    <string name="action_call" msgid="6596167921517350362">"அழை"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"செய்தி அனுப்பு"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"செய்தி அனுப்ப:&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">படங்களை அனுப்பு</item>
+      <item quantity="one">படத்தை அனுப்பு</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">ஆடியோக்களை அனுப்பு</item>
+      <item quantity="one">ஆடியோவை அனுப்பு</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">வீடியோக்களை அனுப்பு</item>
+      <item quantity="one">வீடியோவை அனுப்பு</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">தொடர்பு கார்டுகளை அனுப்பு</item>
+      <item quantity="one">தொடர்பு கார்டை அனுப்பு</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">இணைப்புகளை அனுப்பு</item>
+      <item quantity="one">இணைப்பை அனுப்பு</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> இணைப்புகள் அனுப்புவதற்குத் தயாராக உள்ளன</item>
+      <item quantity="one">ஒரு இணைப்பு அனுப்புவதற்குத் தயாராக உள்ளது</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"கருத்தை அனுப்பு"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store இல் காட்டு"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"பதிப்புத் தகவல்"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"பதிப்பு %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ஓப்பன் சோர்ஸ் உரிமங்கள்"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"அறிவிப்புகள்"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"இணைப்பிற்கான வரம்பை அடைந்துவிட்டீர்கள்"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"இணைப்பை ஏற்றுவதில் தோல்வி."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"தொடர்புகளில் சேர்க்கவா?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"தொடர்பைச் சேர்"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"தலைப்பு"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"தலைப்பு: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"தொடர்பு கார்டை ஏற்றுகிறது"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"தொடர்பு கார்டை ஏற்ற முடியவில்லை"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"தொடர்பு கார்டைக் காட்டு"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> தொடர்புகள்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> தொடர்பு</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"தொடர்பு கார்டுகள்"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"பிறந்தநாள்"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"குறிப்புகள்"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"செய்தியை முன்னனுப்பு"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"பதிலளிக்கவும்"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS முடக்கப்பட்டது"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"அனுப்ப, இயல்பு SMS பயன்பாடாக செய்தியிடலை அமைக்கவும்"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"இயல்பு SMS பயன்பாடாக செய்தியிடலை அமைக்கவும்"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"மாற்று"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"செய்திகளைப் பெற, இயல்பு SMS பயன்பாடாக செய்தியிடலை அமைக்கவும்"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS செய்திகளை அனுப்புவதற்கு விருப்பமான சிம் எதுவும் தேர்ந்தெடுக்கப்படவில்லை"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"சாதன உரிமையாளர் இந்தப் பயன்பாட்டை அனுமதிக்கவில்லை."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"சரி"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"உரையாடலில் பலர் உள்ளனர்"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">தவறான தொடர்புகள்</item>
+      <item quantity="one">தவறான தொடர்பு</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"கேமரா படத்தை ஏற்ற முடியவில்லை"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"நீங்கள்: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"வரைவு"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"புதிய உரையாடலைத் தொடங்கியதும், அது இங்கு பட்டியலிடப்படும்"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"காப்பகப்படுத்திய உரையாடல்கள் இங்கே தோன்றும்"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"உரையாடல்களை ஏற்றுகிறது…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"படம்"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ஆடியோ கிளிப்"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"வீடியோ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"தொடர்பு கார்டு"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"செயல்தவிர்"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"மீண்டும் முயற்சிக்கவும்"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"புதிய செய்தி உருவாக்க, தொடர்பின் பெயர் அல்லது மொபைல் எண்ணை உள்ளிடவும்"</string>
+    <string name="action_block" msgid="9032076625645190136">"தடு"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>ஐத் தடு"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> இன் தடுப்பை நீக்கு"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>ஐத் தடைசெய்யவா?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"தொடர்ந்து இந்த எண்ணில் இருந்து செய்திகளைப் பெறுவீர்கள், அது குறித்து இனி உங்களுக்கு அறிவிக்கப்படாது. உரையாடல் காப்பகப்படுத்தப்படும்."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"தடுக்கப்பட்ட தொடர்புகள்"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"தடுப்பை நீக்கு"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"தடுக்கப்பட்ட தொடர்புகள்"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"ஆவண நூலகத்தில் இருந்து படத்தைத் தேர்வு செய்யவும்"</string>
+    <string name="sending_message" msgid="6363584950085384929">"செய்தி அனுப்பப்படுகிறது"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"செய்தி அனுப்பப்பட்டது"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"செல்லுலார் தரவு முடக்கப்பட்டுள்ளது. அமைப்புகளைச் சரிபார்க்கவும்."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"விமானப் பயன்முறையில் செய்திகளை அனுப்ப முடியாது"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"செய்தியை அனுப்ப முடியவில்லை"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"செய்தி பதிவிறக்கப்பட்டது"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"செல்லுலார் தரவு முடக்கப்பட்டுள்ளது. அமைப்புகளைச் சரிபார்க்கவும்."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"விமானப் பயன்முறையில் செய்திகளை இறக்க முடியாது"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"செய்தி இறக்கப்படவில்லை"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"பூஜ்ஜியம்"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ஒன்று"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"இரண்டு"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"மூன்று"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"நான்கு"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ஐந்து"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ஆறு"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ஏழு"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"எட்டு"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"ஒன்பது"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> மூலம் செய்தியை அனுப்ப முடியவில்லை, பிழை <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"அறியப்படாத மொபைல் நிறுவனம் மூலம் செய்தியை அனுப்ப முடியவில்லை, பிழை <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"அனுப்பு: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"செய்தி அனுப்பப்படவில்லை: நெட்வொர்க்கில் சேவை செயல்படுத்தப்படவில்லை"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"செய்தி அனுப்பப்படவில்லை: தவறான இலக்கு முகவரி"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"செய்தி அனுப்பப்படவில்லை: தவறான செய்தி"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"செய்தி அனுப்பப்படவில்லை: ஆதரிக்கப்படாத உள்ளடக்கம்"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"செய்தி அனுப்பப்படவில்லை: ஆதரிக்கப்படாத செய்தி"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"செய்தி அனுப்பப்படவில்லை: மிகப் பெரியது"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"புதிய செய்தி"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"காட்டு"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"படம்"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"தகுந்த பயன்பாட்டைக் கண்டுபிடிக்க இயலவில்லை"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"பெறுநரை அகற்று"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"புதிய செய்தி"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ரத்துசெய்"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ஆக்சஸ் பாயிண்ட்டைத் திருத்து"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"அமைக்கப்படவில்லை"</string>
+    <string name="apn_name" msgid="1572691851070894985">"பெயர்"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ப்ராக்ஸி"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS போர்ட்"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN வகை"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APNஐ நீக்கு"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"புதிய APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"சேமி"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"நிராகரி"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"பெயர் புலம் வெறுமையாக இருக்கக்கூடாது."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN வெறுமையாக இருக்கக்கூடாது."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC புலம் கண்டிப்பாக 3 இலக்கங்களில் இருக்க வேண்டும்."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC புலம் கண்டிப்பாக 2 அல்லது 3 இலக்கங்களில் இருக்க வேண்டும்."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"இயல்புநிலை APN அமைப்புகளை மீட்டமைக்கிறது."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"இயல்புநிலைக்கு மீட்டமை"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"இயல்புநிலை APN அமைப்புகளை மீட்டமைப்பது முடிந்தது."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"பெயரிடப்படாதது"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ஆக்சஸ் பாயிண்ட் நேம்கள்"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNகள்"</string>
+    <string name="menu_new" msgid="8286285392706532511">"புதிய APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"இவரால் ஆக்சஸ் பாயிண்ட் நேம் அமைப்புகளை மாற்ற முடியாது"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"கிளிப்போர்டுக்கு நகலெடுக்கவா?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"நகலெடு"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"பொது"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"மேம்பட்டவை"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"பொது அமைப்பு"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"மேம்பட்ட அமைப்பு"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" சிம்"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"எல்லா பெறுநர்களுக்கும் SMS செய்திகளைத் தனித்தனியாக அனுப்பவும். நீங்கள் மட்டுமே பதில்களைப் பெறுவீர்கள்"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"எல்லா பெறுநர்களுக்கும் MMS செய்திகளைத் தனித்தனியாக அனுப்பவும்"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"தெரியாத எண்"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"புதிய செய்தி"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"புதிய செய்தி."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"சிம் தேர்வி"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட்டது, சிம் தேர்வி"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"தலைப்பைத் திருத்து"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"சிம்மைத் தேர்ந்தெடுக்கவும் அல்லது தலைப்பைத் திருத்தவும்"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ஆடியோவைப் பதிவுசெய்ய, தொட்டுப் பிடித்திருக்கவும்"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"புதிய உரையாடலைத் தொடங்கு"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"செய்தியிடல்"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"செய்தியிடல் பட்டியல்"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"செய்தியிடல்"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"புதிய செய்தி"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"உரையாடல் பட்டியல்"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"உரையாடல்களை ஏற்றுகிறது"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"செய்திகளை ஏற்றுகிறது"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"மேலும் உரையாடல்களைக் காட்டு"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"கூடுதல் செய்திகளைக் காட்டு"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"உரையாடல் நீக்கப்பட்டது"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"உரையாடல் நீக்கப்பட்டது. வேறொரு செய்தியிடல் உரையாடலைக் காட்ட, தொடவும்"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"தடுக்கப்பட்டார்"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"தடுப்பு நீக்கப்பட்டார்"</string>
+    <string name="db_full" msgid="8459265782521418031">"சேமிப்பகம் குறைவாக உள்ளது. சில தரவை இழக்க நேரிடலாம்."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"இணைப்புகளைத் தேர்ந்தெடு"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"தேர்வை உறுதிப்படுத்து"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> தேர்ந்தெடுக்கப்பட்டன"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"ஒன்று அல்லது அதற்கு மேற்பட்ட இணைப்புகளை அகற்றிவிட்டு, முயற்சிக்கவும்."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"நீங்கள் செய்தியை அனுப்ப முயற்சிக்கலாம், ஆனால் ஒன்று அல்லது அதற்கு மேற்பட்ட இணைப்புகளை நீக்கும் வரை இது வழங்கப்படாமல் இருக்கலாம்."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"ஒரு செய்தியில் ஒரு வீடியோவை மட்டுமே நீங்கள் அனுப்ப முடியும். கூடுதல் வீடியோக்களை அகற்றிவிட்டு, மீண்டும் முயற்சிக்கவும்."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"செய்தியிடலால் இணைப்பை ஏற்ற முடியவில்லை."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"எப்படியேனும் அனுப்பு"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"உரையாடலைத் தொடங்க முடியவில்லை"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> தேர்ந்தெடுக்கப்பட்டது"</string>
+</resources>
diff --git a/res/values-te/arrays.xml b/res/values-te/arrays.xml
new file mode 100644
index 0000000..c18a1b6
--- /dev/null
+++ b/res/values-te/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"విషయం లేదు"</item>
+    <item msgid="272485471009191934">"విషయం లేదు"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"అవును"</item>
+    <item msgid="6049132459802288033">"వద్దు"</item>
+    <item msgid="3084376867445867895">"సరే"</item>
+    <item msgid="3155097332660174689">"హెహే"</item>
+    <item msgid="2611328818571146775">"ధన్యవాదాలు"</item>
+    <item msgid="4881335087096496747">"నేను అంగీకరిస్తున్నాను"</item>
+    <item msgid="2422296858597420738">"బాగుంది"</item>
+    <item msgid="4805581752819452687">"నేను ఆ పని మీదే ఉన్నాను"</item>
+    <item msgid="4746700499431366214">"సరే, నేను మీతో తర్వాత మాట్లాడుతాను"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
new file mode 100644
index 0000000..f2dabb2
--- /dev/null
+++ b/res/values-te/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"మెసేజింగ్"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"మెసేజింగ్"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"సంభాషణను ఎంచుకోండి"</string>
+    <string name="action_settings" msgid="1329008122345201684">"సెట్టింగ్‌లు"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"సందేశం పంపు"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"జోడింపును జోడించండి"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"సహాయం"</string>
+    <string name="welcome" msgid="2857560951820802321">"స్వాగతం"</string>
+    <string name="skip" msgid="7238879696319945853">"దాటవేయి"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"తదుపరి &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"తదుపరి"</string>
+    <string name="exit" msgid="1905187380359981199">"నిష్క్రమించండి"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"సెట్టింగ్‌లు &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"సెట్టింగ్‌లు"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"సందేశ సేవకు SMS, ఫోన్ మరియు పరిచయాల ప్రాప్యత అనుమతి ఇవ్వడం అవసరం."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"మీరు సెట్టింగ్‌లు &gt; అనువర్తనాలు &gt; సందేశ సేవ &gt; అనుమతులులో అనుమతులను మార్చవచ్చు."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"మీరు సెట్టింగ్‌లు, అనువర్తనాలు, సందేశ సేవ, అనుమతులులో అనుమతులను మార్చవచ్చు."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"తరచుగా సంప్రదించినవి"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"అన్ని పరిచయాలు"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g>కి పంపండి"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"చిత్రాలను లేదా వీడియోను సంగ్రహించు"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"ఈ పరికరం నుండి చిత్రాలను ఎంచుకోండి"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"ఆడియోను రికార్డ్ చేయి"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"ఫోటోను ఎంచుకోండి"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"మీడియా ఎంచుకోబడింది."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"మీడియా ఎంపిక తీసివేయబడింది."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ఎంచుకోబడింది"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"చిత్రం <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"చిత్రం"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"ఆడియోను రికార్డ్ చేయి"</string>
+    <string name="action_share" msgid="2143483844803153871">"భాగస్వామ్యం చేయి"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ఇప్పుడే"</string>
+    <string name="posted_now" msgid="867560789350406701">"ఇప్పుడు"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> నిమి</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> నిమి</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> గంటలు</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> గంట</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> రోజులు</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> రోజు</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> వారాలు</item>
+      <item quantity="one">ఒక వారం</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> నెలలు</item>
+      <item quantity="one">ఒక నెల</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> సంవత్సరాలు</item>
+      <item quantity="one">ఒక సంవత్సరం</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"తరగతి 0 సందేశం"</string>
+    <string name="save" msgid="5081141452059463572">"సేవ్ చేయి"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"పరికరంలో ఖాళీ స్థలం తక్కువగా ఉంది. స్థలం ఖాళీ చేయడానికి సందేశ సేవ స్వయంచాలకంగా పాత సందేశాలను తొలగిస్తుంది."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"నిల్వ స్థలం అయిపోతోంది"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"మీ పరికరంలో మరింత ఖాళీ స్థలం లభించే వరకు సందేశ సేవ సందేశాలను పంపలేకపోవచ్చు లేదా స్వీకరించలేకపోవచ్చు."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS నిల్వ తక్కువగా ఉంది. మీరు సందేశాలను తొలగించాల్సి రావచ్చు."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"మీ ఫోన్ నంబర్‌ను నిర్ధారించండి"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ఈ ఒక పర్యాయ దశ సందేశ సేవ మీ సమూహ సందేశాలను సరిగ్గా బట్వాడా చేస్తుందని నిర్ధారిస్తుంది."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"ఫోన్ నంబర్"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"మీడియాలోని అన్ని సందేశాలను తొలగించండి"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> కంటే మునుపు ఉన్న సందేశాలను తొలగించండి"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> కంటే పాత సందేశాలను స్వయంచాలకంగా తొలగించు"</string>
+    <string name="ignore" msgid="7063392681130898793">"విస్మరించు"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"మీడియా ఉన్న అన్ని సందేశాలను తొలగించాలా?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> కంటే పాత సందేశాలను తొలగించాలా?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> కంటే పాత సందేశాలను తొలగించి, స్వయంచాలక తొలగింపుని ఆన్ చేయాలా?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> చెప్పారు"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"మీరు చెప్పారు"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> నుండి సందేశం"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"మీరు సందేశాన్ని పంపారు"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"పంపుతోంది..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"పంపబడలేదు. మళ్లీ ప్రయత్నించడానికి తాకండి."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"పంపబడలేదు. మళ్లీ ప్రయత్నిస్తోంది..."</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"మళ్లీ పంపండి లేదా తొలగించండి"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"దయచేసి అత్యవసర సేవలకు వాయిస్ కాల్ చేయండి. మీ వచన సందేశాన్ని ప్రస్తుతం బట్వాడా చేయడం సాధ్యపడలేదు."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"విఫలమైంది"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"డౌన్‌లోడ్ చేయడానికి కొత్త MMS సందేశం"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"కొత్త MMS సందేశం"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"డౌన్‌లోడ్ చేయడం సాధ్యపడలేదు"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"మళ్లీ ప్రయత్నించడానికి తాకండి"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"డౌన్‌లోడ్ చేయడానికి తాకండి"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"డౌన్‌లోడ్ చేయండి లేదా తొలగించండి"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"డౌన్‌లోడ్ చేస్తోంది…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"సందేశం గడువు ముగిసింది లేదా అందుబాటులో లేదు"</string>
+    <string name="mms_info" msgid="3402311750134118165">"పరిమాణం: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, గడువు: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"పంపడం సాధ్యపడదు. చెల్లని స్వీకర్త."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"నెట్‌వర్క్‌లో సేవ సక్రియం చేయబడలేదు"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"నెట్‌వర్క్ సమస్య కారణంగా పంపడం సాధ్యపడలేదు"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"సందేశం గడువు ముగిసింది లేదా అందుబాటులో లేదు"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(విషయం లేదు)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"పంపినవారు తెలియదు"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"బట్వాడా చేయబడింది"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> నుండి <xliff:g id="SUBJECT">%1$s</xliff:g> సందేశాన్ని డౌన్‌లోడ్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="low_memory" msgid="5300743415198486619">"మెమరీ తక్కువగా ఉన్న కారణంగా డేటాబేస్ నిర్వహణను పూర్తి చేయడం సాధ్యపడలేదు"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"సందేశం పంపబడలేదు"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"సందేశ సేవలో కొన్ని సందేశాలు పంపబడలేదు"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> సంభాషణల్లో <xliff:g id="MESSAGES_1">%d</xliff:g> సందేశాలు</item>
+      <item quantity="one">ఒక సంభాషణలో <xliff:g id="MESSAGES_0">%d</xliff:g> సందేశాలు</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"సందేశం డౌన్‌లోడ్ కాలేదు"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"సందేశ సేవలో కొన్ని సందేశాలు డౌన్‌లోడ్ కాలేదు"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> సంభాషణల్లో <xliff:g id="MESSAGES_1">%d</xliff:g> సందేశాలు</item>
+      <item quantity="one">ఒక సంభాషణలో <xliff:g id="MESSAGES_0">%d</xliff:g> సందేశాలు</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g>కి సందేశం పంపబడలేదు"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"దయచేసి అత్యవసర సేవలకు వాయిస్ కాల్ చేయండి. మీరు <xliff:g id="NUMBER">%1$s</xliff:g>కి పంపిన వచన సందేశాన్ని ప్రస్తుతం బట్వాడా చేయడం సాధ్యపడలేదు."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> కొత్త సందేశాలు</item>
+      <item quantity="one">కొత్త సందేశం</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"ప్రారంభించు"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"కెమెరా అందుబాటులో లేదు"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"కెమెరా అందుబాటులో లేదు"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"వీడియో సంగ్రహణ అందుబాటులో లేదు"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"మీడియాను సేవ్ చేయడం సాధ్యపడదు"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"చిత్రం తీయడం సాధ్యపడలేదు"</string>
+    <string name="back" msgid="1477626055115561645">"వెనుకకు"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"ఆర్కైవ్ చేయబడినవి"</string>
+    <string name="action_delete" msgid="4076795795307486019">"తొలగించు"</string>
+    <string name="action_archive" msgid="5437034800324083170">"ఆర్కైవ్ చేయి"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ఆర్కైవ్ నుండి తీసివేయి"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"నోటిఫికేషన్‌లను ఆఫ్ చేయి"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"నోటిఫికేషన్‌లను ఆన్ చేయి"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"పరిచయాన్ని జోడించు"</string>
+    <string name="action_download" msgid="7786338136368564146">"డౌన్‌లోడ్ చేయి"</string>
+    <string name="action_send" msgid="377635240181672039">"పంపు"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"తొలగించు"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ఈ సందేశాన్ని తొలగించాలా?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"ఈ చర్య రద్దు చేయబడదు."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"తొలగించు"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ఈ సంభాషణలను తొలగించాలా?</item>
+      <item quantity="one">ఈ సంభాషణను తొలగించాలా?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"తొలగించు"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"రద్దు చేయి"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"వీరికి"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"బహుళ చిత్రాలను ఎంచుకోండి"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ఎంపికను నిర్ధారించు"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ఆడియోను రికార్డ్ చేయడం సాధ్యపడదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ఆడియోను ప్లే చేయడం సాధ్యపడదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ఆడియోను సేవ్ చేయడం సాధ్యపడలేదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"తాకి ఉంచండి"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"చిత్రం"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"ఆడియో క్లిప్"</string>
+    <string name="notification_video" msgid="4331423498662606204">"వీడియో"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"పరిచయ కార్డు"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"డౌన్‌లోడ్ చేయి"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ద్వారా ప్రత్యుత్తరం ఇవ్వండి"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMSలో ప్రత్యు."</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ప్రత్యుత్తరం పంపండి"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> మంది పాల్గొన్నారు</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> పాల్గొన్నారు</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"నేను"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"పరిచయం బ్లాక్ చేయబడింది &amp; ఆర్కైవ్ చేయబడింది"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"పరిచయం అన్‌బ్లాక్ చేయబడింది &amp; అన్ఆర్కైవ్ చేయబడింది"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ఆర్కైవ్ చేయబడింది/ఆర్కైవ్ చేయబడ్డాయి"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ఆర్కైవ్ నుండి తీసివేయబడింది/ఆర్కైవ్ నుండి తీసివేయబడ్డాయి"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"నోటిఫికేషన్‌లు ఆఫ్ చేయబడ్డాయి"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"నోటిఫికేషన్‌లు ఆన్ చేయబడ్డాయి"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"అంతా సెట్ చేశారు. మళ్లీ పంపు తాకండి."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"సందేశ సేవ డిఫాల్ట్ SMS అనువర్తనంగా విజయవంతంగా సెట్ చేయబడింది."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">జోడింపులను విస్మరించండి</item>
+      <item quantity="one">జోడింపును విస్మరించండి</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ఆడియో జోడింపు"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"ఆడియో జోడింపుని ప్లే చేయండి"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"పాజ్ చేయి"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> నుండి సందేశం: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> నుండి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపడంలో విఫలమైంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> నుండి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం వచ్చింది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడలేదు. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడుతోంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపడంలో విఫలమైంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడింది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> నుండి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపడంలో విఫలమైంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> నుండి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం వచ్చింది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడలేదు. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడుతోంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపడంలో విఫలమైంది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g>కి <xliff:g id="MESSAGE">%2$s</xliff:g> సందేశం పంపబడింది. సమయం: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"సందేశం పంపడం విఫలమైంది. మళ్లీ ప్రయత్నించడానికి తాకండి."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g>తో సంభాషణ"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"విషయాన్ని తొలగించండి"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"వీడియోను క్యాప్చర్ చేయండి"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"నిలకడగా ఉన్న చిత్రాన్ని క్యాప్చర్ చేయండి"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"చిత్రం తీయండి"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"వీడియో రికార్డింగ్‌ను ప్రారంభించండి"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"కెమెరాను పూర్తి స్క్రీన్‌కి మార్చండి"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"ముందు మరియు వెనుక కెమెరా మోడ్‌ల మధ్య మారండి"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"రికార్డింగ్‌ను ఆపివేసి, వీడియోను చేర్చండి"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"వీడియో రికార్డ్ చేయడాన్ని ఆపివేయండి"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"సందేశ సేవ ఫోటోలు"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ఫోటోలు \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ఫోటో \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడింది</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> వీడియోలు \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> వీడియో \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడింది</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> జోడింపులు \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> జోడింపు \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" ఆల్బమ్‌కి సేవ్ చేయబడింది</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> జోడింపులు \"డౌన్‌లోడ్‌లు\"కి సేవ్ చేయబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> జోడింపు \"డౌన్‌లోడ్‌లు\"కి సేవ్ చేయబడింది</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> జోడింపులు సేవ్ చేయబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> జోడింపు సేవ్ చేయబడింది</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> జోడింపులను సేవ్ చేయలేకపోయింది</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> జోడింపును సేవ్ చేయలేకపోయింది</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS జోడింపు సేవ్ చేయబడింది"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"సెట్టింగ్‌లు"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"ఆర్కైవ్ చేయబడింది"</string>
+    <string name="action_close" msgid="1840519376200478419">"మూసివేయి"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"అధునాతనం"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"డీబగ్"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"నోటిఫికేషన్‌లు"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"ధ్వని"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"నిశ్శబ్దం"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"వైబ్రేట్"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"బ్లాక్ చేయబడింది"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS బట్వాడా నివేదికలు"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"మీరు పంపే ప్రతి SMS కోసం బట్వాడా నివేదికను అభ్యర్థించండి"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"స్వయంచాలకంగా తిరిగి పొందడం"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS సందేశాలను స్వయంచాలకంగా పునరుద్ధరించండి"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"రోమింగ్‌లో ఉన్నప్పుడు స్వీయ-పునరుద్ధరణ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"రోమింగ్‌లో ఉన్నప్పుడు MMSని స్వయంచాలకంగా తిరిగి పొందుతుంది"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"సమూహ సందేశాలు"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ఒక సందేశాన్ని బహుళ స్వీకర్తలకు పంపాల్సినప్పుడు MMSను ఉపయోగించండి"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"డిఫాల్ట్ SMS అనువర్తనం"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"డిఫాల్ట్ SMS అనువర్తనం"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"మీ ఫోన్ నంబర్"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"తెలియదు"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"అవుట్‌గోయింగ్ సందేశ ధ్వనులు"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMSను డంప్ చేయండి"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"స్వీకరించబడిన SMS ప్రాసెస్ చేయబడని డేటాను బాహ్య నిల్వ ఫైల్‌లోకి డంప్ చేయండి"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMSను డంప్ చేయండి"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"స్వీకరించబడిన MMS ప్రాసెస్ చేయబడని డేటాను బాహ్య నిల్వ ఫైల్‌లోకి డంప్ చేయండి"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"వైర్‌లెస్ హెచ్చరికలు"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"సందేశ ఎంపికలు"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"వచనాన్ని కాపీ చేయి"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"వివరాలను వీక్షించండి"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"తొలగించు"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ఫార్వార్డ్ చేయండి"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"సందేశ వివరాలు"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"రకం: "</string>
+    <string name="text_message" msgid="7415419755252205721">"వచన సందేశం"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"మల్టీమీడియా సందేశం"</string>
+    <string name="from_label" msgid="1947831848146564875">"వీరి నుండి: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"వీరికి: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"పంపినది: "</string>
+    <string name="received_label" msgid="4442494712757995203">"స్వీకరించినది: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"విషయం: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"పరిమాణం: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ప్రాధాన్యత: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"అధికం"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"సాధారణం"</string>
+    <string name="priority_low" msgid="7398724779026801851">"తక్కువ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"లేఖరి చిరునామా దాచబడింది"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"జోడింపులు లోడ్ అవుతున్నప్పుడు సందేశాన్ని పంపలేరు."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"జోడింపుని లోడ్ చేయడం సాధ్యపడదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"నెట్‌వర్క్ సిద్ధంగా లేదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"వచనాన్ని తొలగించు"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"వచనం మరియు సంఖ్యలను నమోదు చేయడానికి వాటిని అటుఇటు మార్చు"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"మరింతమంది పాల్గొనేవారిని జోడించు"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"పాల్గొనేవారిని నిర్ధారించండి"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"కొత్త సంభాషణను ప్రారంభించండి"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"ఈ అంశాన్ని ఎంచుకోండి"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"వీడియోను ప్లే చేయండి"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"వ్యక్తులు &amp; ఎంపికలు"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"డీబగ్"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"వ్యక్తులు &amp; ఎంపికలు"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"సాధారణం"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ఈ సంభాషణలో పాల్గొన్న వ్యక్తులు"</string>
+    <string name="action_call" msgid="6596167921517350362">"కాల్ చేయి"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"సందేశాన్ని పంపండి"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"సందేశాన్ని &lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> నుండి&lt;/small&gt;&lt;br/&gt;పంపు"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ఫోటోలను పంపండి</item>
+      <item quantity="one">ఫోటోను పంపండి</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">ఆడియోలను పంపండి</item>
+      <item quantity="one">ఆడియోను పంపండి</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">వీడియోలను పంపండి</item>
+      <item quantity="one">వీడియోను పంపండి</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">పరిచయ కార్డ్‌లను పంపండి</item>
+      <item quantity="one">పరిచయ కార్డ్‌ను పంపండి</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">జోడింపులను పంపండి</item>
+      <item quantity="one">జోడింపుని పంపండి</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> జోడింపులు పంపడానికి సిద్ధంగా ఉన్నాయి</item>
+      <item quantity="one">ఒక జోడింపు పంపడానికి సిద్ధంగా ఉంది</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"అభిప్రాయం పంపండి"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Storeలో వీక్షించండి"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"సంస్కరణ సమాచారం"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"సంస్కరణ %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"ఓపెన్ సోర్స్ లైసెన్స్‌లు"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"నోటిఫికేషన్‌లు"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"జోడింపు పరిమితిని చేరుకున్నారు"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"జోడింపుని లోడ్ చేయడంలో విఫలమైంది."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"పరిచయాలకు జోడించాలా?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"పరిచయాన్ని జోడించు"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"విషయం"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"విషయం: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"పరిచయ కార్డ్‌ను లోడ్ చేస్తోంది"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"పరిచయ కార్డ్‌ను లోడ్ చేయడం సాధ్యపడలేదు"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"పరిచయ కార్డ్‌ను వీక్షించండి"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> పరిచయాలు</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> పరిచయం</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"పరిచయ కార్డ్‌లు"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"పుట్టినరోజు"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"గమనికలు"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"సందేశాన్ని ఫార్వార్డ్ చేయండి"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ప్రత్యుత్తరం"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS నిలిపివేయబడింది"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"పంపడానికి, సందేశ సేవను డిఫాల్ట్ SMS అనువర్తనంగా సెట్ చేయండి"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"సందేశ సేవను డిఫాల్ట్ SMS అనువర్తనంగా సెట్ చేయండి"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"మార్చు"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"సందేశాలు స్వీకరించడానికి, సందేశ సేవను డిఫాల్ట్ SMS అనువర్తనంగా సెట్ చేయండి"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS సందేశాలు పంపడానికి ప్రాధాన్య SIM ఏదీ ఎంచుకోలేదు"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"ఈ అనువర్తనాన్ని పరికరం యజమాని అనుమతించలేదు."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"సరే"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"సంభాషణలో చాలా ఎక్కువ మంది పాల్గొన్నారు"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">పరిచయాలు చెల్లవు</item>
+      <item quantity="one">పరిచయం చెల్లదు</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"కెమెరా చిత్రాన్ని లోడ్ చేయడం సాధ్యపడలేదు"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"మీరు: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"చిత్తుప్రతి"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"మీరు కొత్త సంభాషణను ప్రారంభిస్తే, అది ఇక్కడ జాబితా కావడం మీకు కనిపిస్తుంది"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"ఆర్కైవ్ చేసిన సంభాషణలు ఇక్కడ కనిపిస్తాయి"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"సంభాషణలను లోడ్ చేస్తోంది…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"చిత్రం"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"ఆడియో క్లిప్"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"వీడియో"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"పరిచయ కార్డ్"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"చర్య రద్దు చేయి"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"మళ్లీ ప్రయత్నించు"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"కొత్త సందేశాన్ని ప్రారంభించడానికి పరిచయం పేరు లేదా ఫోన్ నంబర్‌ని నమోదు చేయండి"</string>
+    <string name="action_block" msgid="9032076625645190136">"బ్లాక్ చేయి"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g>ని బ్లాక్ చేయి"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g>ని అన్‌బ్లాక్ చేయి"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g>ని బ్లాక్ చేయాలా?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"మీరు ఈ నంబర్ నుండి సందేశాలను స్వీకరించడం కొనసాగుతుంది కానీ ఇకపై వాటి గురించి తెలియజేయబడదు. ఈ సంభాషణ ఆర్కైవ్ చేయబడుతుంది."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"బ్లాక్ చేయబడిన పరిచయాలు"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"అన్‌బ్లాక్ చేయి"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"బ్లాక్ చేయబడిన పరిచయాలు"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"పత్రం లైబ్రరీ నుండి చిత్రాన్ని ఎంచుకోండి"</string>
+    <string name="sending_message" msgid="6363584950085384929">"సందేశం పంపబడుతోంది"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"సందేశం పంపబడింది"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"సెల్యులార్ డేటా ఆఫ్ చేయబడింది. మీ సెట్టింగ్‌లను తనిఖీ చేయండి."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"ఎయిర్‌ప్లైన్ మోడ్‌లో సందేశాలు పంపడం సాధ్యపడదు"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"సందేశం పంపడం సాధ్యపడలేదు"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"సందేశం డౌన్‌లోడ్ చేయబడింది"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"సెల్యులార్ డేటా ఆఫ్ చేయబడింది. మీ సెట్టింగ్‌లను తనిఖీ చేయండి."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ఎయిర్‌ప్లైన్ మోడ్‌లో సందేశాలను డౌన్‌లోడ్ చేయడం సాధ్యపడదు"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"సందేశాన్ని డౌన్‌లోడ్ చేయడం సాధ్యపడలేదు"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"సున్నా"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ఒకటి"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"రెండు"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"మూడు"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"నాలుగు"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ఐదు"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"ఆరు"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"ఏడు"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"ఎనిమిది"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"తొమ్మిది"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g>తో సందేశం పంపలేరు, దోషం <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"తెలియని క్యారియర్‌తో సందేశం పంపలేరు, లోపం <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ఫార్వా.: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"సందేశం పంపబడలేదు: నెట్‌వర్క్‌లో సేవ సక్రియం కాలేదు"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"సందేశం పంపబడలేదు: గమ్యస్థాన చిరునామా చెల్లదు"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"సందేశం పంపబడలేదు: సందేశం చెల్లదు"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"సందేశం పంపబడలేదు: మద్దతు లేని కంటెంట్"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"సందేశం పంపబడలేదు: మద్దతు లేని సందేశం"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"సందేశం పంపబడలేదు: చాలా పెద్దది"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"కొత్త సందేశం"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"వీక్షించండి"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"చిత్రం"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"సముచిత అనువర్తనాన్ని కనుగొనడం సాధ్యపడలేదు"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"స్వీకర్తను తీసివేయండి"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"కొత్త సందేశం"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"రద్దు చేయి"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"ప్రాప్యత స్థానాన్ని సవరించు"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"సెట్ చేయలేదు"</string>
+    <string name="apn_name" msgid="1572691851070894985">"పేరు"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS ప్రాక్సీ"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS పోర్ట్"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN రకం"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APNను తొలగించు"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"కొత్త APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"సేవ్ చేయి"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"విస్మరించు"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"పేరు ఫీల్డ్ ఖాళీగా ఉండకూడదు."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN ఖాళీగా ఉండకూడదు."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC ఫీల్డ్‌లో తప్పనిసరిగా 3 అంకెలు ఉండాలి."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC ఫీల్డ్‌లో తప్పనిసరిగా 2 లేదా 3 అంకెలు ఉండాలి."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"డిఫాల్ట్ APN సెట్టింగ్‌లను పునరుద్ధరిస్తోంది."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"డిఫాల్ట్‌కు రీసెట్ చేయి"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"డిఫాల్ట్ APN సెట్టింగ్‌లను రీసెట్ చేయడం పూర్తయింది."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"శీర్షిక లేదు"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ప్రాప్యత స్థానం పేర్లు"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNలు"</string>
+    <string name="menu_new" msgid="8286285392706532511">"కొత్త APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"ప్రాప్యత స్థానం పేరు సెట్టింగ్‌లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"క్లిప్‌బోర్డ్‌కు కాపీ చేయాలా?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"కాపీ చేయి"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g>కి"</string>
+    <string name="general_settings" msgid="5409336577057897710">"సాధారణం"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"అధునాతనం"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"సాధారణ సెట్టింగ్‌లు"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"అధునాతన సెట్టింగ్‌లు"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"స్వీకర్తలందరికీ వేర్వేరుగా SMS సందేశాలను పంపండి. ఏవైనా ప్రత్యుత్తరాలను మీరు మాత్రమే పొందుతారు"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"స్వీకర్తలందరికీ ఒకే MMS పంపండి"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"తెలియని నంబర్"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"కొత్త సందేశం"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"కొత్త సందేశం."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM ఎంపిక సాధనం"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> ఎంచుకోబడింది, SIM ఎంపిక"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"విషయాన్ని సవరించు"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM ఎంచుకోండి లేదా విషయాన్ని సవరించండి"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"ఆడియోను రికార్డ్ చేయడానికి తాకి, అలాగే ఉంచండి"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"కొత్త సంభాషణను ప్రారంభించండి"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"సందేశ సేవ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"సందేశ సేవ జాబితా"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"సందేశ సేవ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"కొత్త సందేశం"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"సంభాషణ జాబితా"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"సంభాషణలను లోడ్ చేస్తోంది"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"సందేశాలు లోడ్ అవుతున్నాయి"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"మరిన్ని సంభాషణలను వీక్షించండి"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"మరిన్ని సందేశాలను వీక్షించండి"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"సంభాషణ తొలగించబడింది"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"సంభాషణ తొలగించబడింది. విభిన్న సందేశ సేవ సంభాషణను చూపడానికి తాకండి"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"బ్లాక్ చేయబడ్డారు"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"అన్‌బ్లాక్ చేయబడ్డారు"</string>
+    <string name="db_full" msgid="8459265782521418031">"నిల్వ స్థలంలో ఖాళీ తక్కువగా ఉంది. కొంత డేటా కోల్పోవచ్చు."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"జోడింపులను ఎంచుకోండి"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ఎంపికను నిర్ధారించు"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ఎంచుకోబడింది/ఎంచుకోబడ్డాయి"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"దయచేసి ఒకటి లేదా అంతకంటే ఎక్కువ జోడింపులను తీసివేసి, మళ్లీ ప్రయత్నించండి."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"మీరు మీ సందేశం పంపడాన్ని ప్రయత్నించవచ్చు, కానీ ఒకటి లేదా అంతకంటే ఎక్కువ జోడింపులను తీసివేస్తే మినహా అది బట్వాడా చేయబడదు."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"మీరు ఒక సందేశానికి ఒక వీడియోను మాత్రమే పంపగలరు. దయచేసి అదనపు వీడియోలను తీసివేసి, ఆపై మళ్లీ ప్రయత్నించండి."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"సందేశ సేవ జోడింపును లోడ్ చేయడంలో విఫలమైంది."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ఏదేమైనా పంపు"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"సంభాషణను ప్రారంభించలేరు"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ఎంచుకోబడింది"</string>
+</resources>
diff --git a/res/values-th/arrays.xml b/res/values-th/arrays.xml
new file mode 100644
index 0000000..749516e
--- /dev/null
+++ b/res/values-th/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"ไม่มีเรื่อง"</item>
+    <item msgid="272485471009191934">"ไม่มีชื่อเรื่อง"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ใช่"</item>
+    <item msgid="6049132459802288033">"ไม่ใช่"</item>
+    <item msgid="3084376867445867895">"ตกลง"</item>
+    <item msgid="3155097332660174689">"อิอิ"</item>
+    <item msgid="2611328818571146775">"ขอบคุณ"</item>
+    <item msgid="4881335087096496747">"ฉันเห็นด้วย"</item>
+    <item msgid="2422296858597420738">"เยี่ยมเลย"</item>
+    <item msgid="4805581752819452687">"เดินทางอยู่"</item>
+    <item msgid="4746700499431366214">"ตกลง ฉันจะติดต่อกลับมาในภายหลัง"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
new file mode 100644
index 0000000..3768ca8
--- /dev/null
+++ b/res/values-th/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"การรับส่งข้อความ"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"การรับส่งข้อความ"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"เลือกการสนทนา"</string>
+    <string name="action_settings" msgid="1329008122345201684">"การตั้งค่า"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"ส่งข้อความ"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"เพิ่มไฟล์แนบ"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"ความช่วยเหลือ"</string>
+    <string name="welcome" msgid="2857560951820802321">"ยินดีต้อนรับ"</string>
+    <string name="skip" msgid="7238879696319945853">"ข้าม"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"ถัดไป &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"ถัดไป"</string>
+    <string name="exit" msgid="1905187380359981199">"ออก"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"การตั้งค่า &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"การตั้งค่า"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"การรับส่งข้อความต้องใช้สิทธิ์เข้าถึง SMS, โทรศัพท์ และรายชื่อติดต่อ"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"คุณสามารถเปลี่ยนแปลงสิทธิ์ได้ในการตั้งค่า &gt; แอป &gt; การรับส่งข้อความ &gt; สิทธิ์"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"คุณสามารถเปลี่ยนแปลงสิทธิ์ได้ในการตั้งค่า แอป การรับส่งข้อความ และสิทธิ์"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"ผู้ที่ติดต่อบ่อย"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"รายชื่อติดต่อทั้งหมด"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"ส่งไปยัง <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"จับภาพหรือวิดีโอ"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"เลือกรูปภาพจากอุปกรณ์นี้"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"บันทึกเสียง"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"เลือกรูปภาพ"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"เลือกสื่อแล้ว"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"ไม่มีการเลือกสื่อ"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"เลือกไว้ <xliff:g id="COUNT">%d</xliff:g> รายการ"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"ภาพเมื่อวันที่ <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"ภาพ"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"บันทึกเสียง"</string>
+    <string name="action_share" msgid="2143483844803153871">"แชร์"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"เดี๋ยวนี้เอง"</string>
+    <string name="posted_now" msgid="867560789350406701">"ตอนนี้"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> นาที</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> นาที</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ชั่วโมง</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ชั่วโมง</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> วัน</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> วัน</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> สัปดาห์</item>
+      <item quantity="one">1 สัปดาห์</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> เดือน</item>
+      <item quantity="one">1 เดือน</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ปี</item>
+      <item quantity="one">1 ปี</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"ข้อความคลาส 0"</string>
+    <string name="save" msgid="5081141452059463572">"บันทึก"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"อุปกรณ์มีพื้นที่เหลือน้อย การรับส่งข้อความจะลบข้อความเก่าโดยอัตโนมัติเพื่อเพิ่มพื้นที่ว่าง"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"พื้นที่จัดเก็บเหลือน้อย"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"การรับส่งข้อความอาจไม่ส่งหรือรับข้อความจนกว่าจะมีพื้นที่เพิ่มมากขึ้นบนอุปกรณ์"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"พื้นที่จัดเก็บ SMS เหลือน้อย คุณอาจต้องลบข้อความ"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"ยืนยันหมายเลขโทรศัพท์"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"ขั้นตอนที่ทำเพียงครั้งเดียวนี้จะช่วยให้การรับส่งข้อความส่งข้อความของกลุ่มได้อย่างถูกต้อง"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"หมายเลขโทรศัพท์"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"ลบข้อความทั้งหมดที่มีสื่อ"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"ลบข้อความที่เก่ากว่า <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"ลบข้อความที่เก่ากว่า <xliff:g id="DURATION">%s</xliff:g> โดยอัตโนมัติ"</string>
+    <string name="ignore" msgid="7063392681130898793">"ไม่สนใจ"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"ลบข้อความทั้งหมดที่มีสื่อใช่ไหม"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"ลบข้อความที่เก่ากว่า <xliff:g id="DURATION">%s</xliff:g> ใช่ไหม"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"ลบข้อความที่เก่ากว่า <xliff:g id="DURATION">%s</xliff:g> และเปิดการลบอัตโนมัติใช่ไหม"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> กล่าว"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"คุณกล่าว"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"ข้อความจาก <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"คุณส่งข้อความแล้ว"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"กำลังส่ง…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"ไม่สามารถส่ง แตะเพื่อลองอีกครั้ง"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"ไม่สามารถส่ง ลองอีกครั้ง…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"ส่งอีกครั้งหรือลบ"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"โปรดโทรไปที่ฝ่ายบริการฉุกเฉิน ระบบไม่สามารถส่งข้อความของคุณได้ในขณะนี้"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ล้มเหลว"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"มีข้อความ MMS ใหม่ให้ดาวน์โหลด"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"ข้อความ MMS ใหม่"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ไม่สามารถดาวน์โหลดได้"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"แตะเพื่อลองอีกครั้ง"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"แตะเพื่อดาวน์โหลด"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ดาวน์โหลดหรือลบ"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"กำลังดาวน์โหลด…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"ข้อความหมดอายุหรือไม่สามารถใช้ได้"</string>
+    <string name="mms_info" msgid="3402311750134118165">"ขนาด: <xliff:g id="MESSAGESIZE">%1$s</xliff:g> หมดอายุ: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"ไม่สามารถส่งได้ ผู้รับไม่ถูกต้อง"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"ไม่ได้เปิดใช้บริการบนเครือข่าย"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"ไม่สามารถส่งได้เนื่องจากปัญหาของเครือข่าย"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"ข้อความหมดอายุหรือไม่สามารถใช้ได้"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(ไม่มีเรื่อง)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"ไม่ทราบผู้ส่ง"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ส่งแล้ว"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"ไม่สามารถดาวน์โหลดข้อความ <xliff:g id="SUBJECT">%1$s</xliff:g> จาก <xliff:g id="FROM">%2$s</xliff:g>"</string>
+    <string name="low_memory" msgid="5300743415198486619">"ไม่สามารถดำเนินการฐานข้อมูลให้เสร็จสิ้นเนื่องจากมีหน่วยความจำเหลือน้อย"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"ไม่ได้ส่งข้อความ"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"ไม่ได้ส่งข้อความบางรายการในการรับส่งข้อความ"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ข้อความใน <xliff:g id="CONVERSATIONS">%d</xliff:g> การสนทนา</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> ข้อความใน 1 การสนทนา</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"ข้อความไม่ได้รับการดาวน์โหลด"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"ไม่ได้ดาวน์โหลดข้อความบางรายการในการรับส่งข้อความ"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ข้อความใน <xliff:g id="CONVERSATIONS">%d</xliff:g> การสนทนา</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> ข้อความใน 1 การสนทนา</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"ไม่ได้ส่งข้อความถึง <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"โปรดโทรไปที่ฝ่ายบริการฉุกเฉิน ระบบไม่สามารถส่งข้อความของคุณไปยัง <xliff:g id="NUMBER">%1$s</xliff:g> ได้ในขณะนี้"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ข้อความใหม่</item>
+      <item quantity="one">ข้อความใหม่</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"เริ่ม"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"กล้องไม่สามารถใช้ได้"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"กล้องไม่สามารถใช้ได้"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"การจับภาพวิดีโอไม่พร้อมใช้งาน"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"ไม่สามารถบันทึกสื่อได้"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"ไม่สามารถถ่ายภาพ"</string>
+    <string name="back" msgid="1477626055115561645">"กลับ"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"เก็บถาวรแล้ว"</string>
+    <string name="action_delete" msgid="4076795795307486019">"ลบ"</string>
+    <string name="action_archive" msgid="5437034800324083170">"เก็บถาวร"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"ยกเลิกการเก็บถาวร"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"ปิดการแจ้งเตือน"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"เปิดการแจ้งเตือน"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"เพิ่มรายชื่อติดต่อ"</string>
+    <string name="action_download" msgid="7786338136368564146">"ดาวน์โหลด"</string>
+    <string name="action_send" msgid="377635240181672039">"ส่ง"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"ลบ"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"ลบข้อความนี้ไหม"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"การดำเนินการนี้ไม่สามารถยกเลิกได้"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"ลบ"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ลบการสนทนาเหล่านี้ใช่ไหม</item>
+      <item quantity="one">ลบการสนทนานี้ใช่ไหม</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"ลบ"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"ยกเลิก"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"ถึง"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"เลือกภาพหลายภาพ"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"ยืนยันการเลือก"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"ไม่สามารถบันทึกเสียงได้ ลองอีกครั้ง"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"ไม่สามารถเล่นเสียงได้ ลองอีกครั้ง"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"ไม่สามารถบันทึกเสียงได้ ลองอีกครั้ง"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"แตะค้างไว้"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"ภาพ"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"คลิปเสียง"</string>
+    <string name="notification_video" msgid="4331423498662606204">"วิดีโอ"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"บัตรติดต่อ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ดาวน์โหลด"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"ตอบกลับทาง SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"ตอบกลับผ่าน MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"ตอบ"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other">ผู้เข้าร่วม <xliff:g id="COUNT_1">%d</xliff:g> คน</item>
+      <item quantity="one">ผู้เข้าร่วม <xliff:g id="COUNT_0">%d</xliff:g> คน</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"ฉัน"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"บล็อกและเก็บผู้ติดต่อแล้ว"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"เลิกบล็อกและเลิกเก็บรายชื่อติดต่อแล้ว"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"เก็บแล้ว <xliff:g id="COUNT">%d</xliff:g> รายการ"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"เลิกเก็บแล้ว <xliff:g id="COUNT">%d</xliff:g> รายการ"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"ปิดการแจ้งเตือนแล้ว"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"เปิดการแจ้งเตือนแล้ว"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"ตั้งค่าเรียบร้อย แตะ \"ส่ง\" อีกครั้ง"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"ตั้งค่าการรับส่งข้อความเป็นแอป SMS ค่าเริ่มต้นเรียบร้อยแล้ว"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">ยกเลิกไฟล์แนบ</item>
+      <item quantity="one">ยกเลิกไฟล์แนบ</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"ไฟล์แนบเสียง"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"เล่นไฟล์เสียงที่แนบอยู่"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"หยุดชั่วคราว"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"ข้อความจาก <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"ไม่สามารถรับข้อความจาก <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"ข้อความจาก <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"ข้อความที่ยังไม่ได้ส่งถึง <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"กำลังส่งข้อความถึง <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"ไม่สามารถส่งข้อความถึง <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"ส่งข้อความถึง <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"ไม่สามารถรับข้อความจาก <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g> <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"ข้อความจาก <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g> <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"ข้อความที่ยังไม่ได้ส่งถึง <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"กำลังส่งข้อความถึง <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"ไม่สามารถส่งข้อความถึง <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"ส่งข้อความถึง <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g> เวลา: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ข้อความล้มเหลว แตะเพื่อลองใหม่"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"การสนทนากับ <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"ลบเรื่อง"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"จับภาพวิดีโอ"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"จับภาพนิ่ง"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"ถ่ายภาพ"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"เริ่มบันทึกวิดีโอ"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"สลับไปยังกล้องแบบเต็มหน้าจอ"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"สลับระหว่างกล้องหน้าและกล้องหลัง"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"หยุดการบันทึกและแนบวิดีโอ"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"หยุดการบันทึกวิดีโอ"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"รูปภาพในการรับส่งข้อความ"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other">บันทึก <xliff:g id="QUANTITY_2">%d</xliff:g> ภาพไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" แล้ว</item>
+      <item quantity="one">บันทึก <xliff:g id="QUANTITY_0">%d</xliff:g> ภาพไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" แล้ว</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other">บันทึกวิดีโอ <xliff:g id="QUANTITY_2">%d</xliff:g> รายการไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" แล้ว</item>
+      <item quantity="one">บันทึกวิดีโอ <xliff:g id="QUANTITY_0">%d</xliff:g> รายการไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" แล้ว</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">บันทึก <xliff:g id="QUANTITY_2">%d</xliff:g> ไฟล์แนบไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" แล้ว</item>
+      <item quantity="one">บันทึก <xliff:g id="QUANTITY_0">%d</xliff:g> ไฟล์แนบไปยังอัลบั้ม \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" แล้ว</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">บันทึก <xliff:g id="QUANTITY_1">%d</xliff:g> ไฟล์แนบไปยัง \"ดาวน์โหลด\" แล้ว</item>
+      <item quantity="one">บันทึก <xliff:g id="QUANTITY_0">%d</xliff:g> ไฟล์แนบไปยัง \"ดาวน์โหลด\" แล้ว</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">บันทึกไฟล์แนบ <xliff:g id="QUANTITY_1">%d</xliff:g> รายการแล้ว</item>
+      <item quantity="one">บันทึกไฟล์แนบ <xliff:g id="QUANTITY_0">%d</xliff:g> รายการแล้ว</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">ไม่สามารถบันทึกไฟล์แนบ <xliff:g id="QUANTITY_1">%d</xliff:g> รายการ</item>
+      <item quantity="one">ไม่สามารถบันทึกไฟล์แนบ <xliff:g id="QUANTITY_0">%d</xliff:g> รายการ</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"ไฟล์แนบของ MMS ที่บันทึกไว้"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"การตั้งค่า"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"เก็บถาวรแล้ว"</string>
+    <string name="action_close" msgid="1840519376200478419">"ปิด"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"ขั้นสูง"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"แก้ไขข้อบกพร่อง"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"การแจ้งเตือน"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"เสียง"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"เงียบ"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"สั่น"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"ถูกบล็อก"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"รายงานการส่ง SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"ขอรายงานการส่ง SMS แต่ละครั้ง"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"เรียกอัตโนมัติ"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"เรียกดูข้อความ MMS อัตโนมัติ"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"เรียกข้อความอัตโนมัติขณะโรมมิ่ง"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"ดึง MMS โดยอัตโนมัติเมื่อโรมมิ่ง"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"การรับส่งข้อความแบบกลุ่ม"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"ใช้ MMS ส่งข้อความเดียวเมื่อมีผู้รับหลายราย"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"แอป SMS เริ่มต้น"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"แอป SMS เริ่มต้น"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"หมายเลขโทรศัพท์ของคุณ"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"ไม่รู้จัก"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"เสียงข้อความขาออก"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"ถ่ายโอน SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"ถ่ายโอนข้อมูลดิบของ SMS ที่ได้รับลงในไฟล์พื้นที่จัดเก็บข้อมูลภายนอก"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"ถ่ายโอน MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"ถ่ายโอนข้อมูลดิบของ MMS ที่ได้รับลงในไฟล์พื้นที่จัดเก็บข้อมูลภายนอก"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"การแจ้งเตือนแบบไร้สาย"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"ตัวเลือกข้อความ"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"คัดลอกข้อความ"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"ดูรายละเอียด"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"ลบ"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"ส่งต่อ"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"รายละเอียดข้อความ"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"ประเภท: "</string>
+    <string name="text_message" msgid="7415419755252205721">"ข้อความ"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ข้อความมัลติมีเดีย"</string>
+    <string name="from_label" msgid="1947831848146564875">"จาก: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"ถึง: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ส่งแล้ว: "</string>
+    <string name="received_label" msgid="4442494712757995203">"ได้รับ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"เรื่อง: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"ขนาด: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ลำดับความสำคัญ: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"ซิม: "</string>
+    <string name="priority_high" msgid="728836357310908368">"สูง"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"ปกติ"</string>
+    <string name="priority_low" msgid="7398724779026801851">"ต่ำ"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"ซิม <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"ที่อยู่ผู้ส่งที่ซ่อนไว้"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"ไม่สามารถส่งข้อความเสียงขณะโหลดเอกสารแนบ"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"ไม่สามารถโหลดไฟล์แนบได้ ลองอีกครั้ง"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"เครือข่ายยังไม่พร้อม ลองอีกครั้ง"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"ลบข้อความ"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"สลับระหว่างการป้อนข้อความและตัวเลข"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"เพิ่มผู้เข้าร่วมเพิ่มเติม"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"ยืนยันผู้เข้าร่วม"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"เริ่มต้นการสนทนาใหม่"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"เลือกรายการนี้"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"เล่นวิดีโอ"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"ผู้คนและตัวเลือก"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"แก้ไขข้อบกพร่อง"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"ผู้คนและตัวเลือก"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"ทั่วไป"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"ผู้เข้าร่วมการสนทนานี้"</string>
+    <string name="action_call" msgid="6596167921517350362">"โทรออก"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"ส่งข้อความ"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"ส่งข้อความ&lt;br/&gt;&lt;small&gt;จาก <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">ส่งรูปภาพ</item>
+      <item quantity="one">ส่งรูปภาพ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">ส่งไฟล์เสียง</item>
+      <item quantity="one">ส่งไฟล์เสียง</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ส่งวิดีโอ</item>
+      <item quantity="one">ส่งวิดีโอ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">ส่งการ์ดรายชื่อติดต่อ</item>
+      <item quantity="one">ส่งการ์ดรายชื่อติดต่อ</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">ส่งไฟล์แนบ</item>
+      <item quantity="one">ส่งไฟล์แนบ</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ไฟล์แนบพร้อมส่ง</item>
+      <item quantity="one">1 ไฟล์แนบพร้อมส่ง</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"ส่งความคิดเห็น"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"ดูใน Google Play สโตร์"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ข้อมูลเวอร์ชัน"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"เวอร์ชัน %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"สัญญาอนุญาตสำหรับโอเพนซอร์ส"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"การแจ้งเตือน"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"ถึงขีดจำกัดของไฟล์แนบแล้ว"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"ไม่สามารถโหลดไฟล์แนบได้"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"เพิ่มในรายชื่อติดต่อใช่ไหม"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"เพิ่มรายชื่อติดต่อ"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"เรื่อง"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"เรื่อง: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"กำลังโหลดบัตรติดต่อ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"ไม่สามารถโหลดการ์ดรายชื่อติดต่อได้"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"ดูบัตรติดต่อ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other">รายชื่อติดต่อ <xliff:g id="COUNT_1">%d</xliff:g> ราย</item>
+      <item quantity="one">รายชื่อติดต่อ <xliff:g id="COUNT_0">%d</xliff:g> ราย</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"การ์ดรายชื่อติดต่อ"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"วันเกิด"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"บันทึก"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"ส่งต่อข้อความ"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"ตอบ"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"ปิดใช้ SMS แล้ว"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"ในการส่งข้อความ ให้ตั้งค่าการรับส่งข้อความเป็นแอป SMS ค่าเริ่มต้น"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"ตั้งค่าการรับส่งข้อความเป็นแอป SMS ค่าเริ่มต้น"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"เปลี่ยน"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"ในการรับข้อความ ให้ตั้งค่าการรับส่งข้อความเป็นแอป SMS ค่าเริ่มต้น"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"ยังไม่ได้เลือกซิมสำหรับการส่งข้อความ SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"เจ้าของอุปกรณ์ไม่อนุญาตแอปนี้"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ตกลง"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"มีผู้เข้าร่วมในการสนทนามากเกินไป"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">รายชื่อติดต่อไม่ถูกต้อง</item>
+      <item quantity="one">รายชื่อติดต่อไม่ถูกต้อง</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"ไม่สามารถโหลดภาพจากกล้องได้"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"คุณ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"ข้อความร่าง"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"เมื่อคุณเริ่มการสนทนาใหม่ คุณจะเห็นการสนทนาใหม่ที่นี่"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"การสนทนาที่เก็บไว้จะปรากฏที่นี่"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"กำลังโหลดการสนทนา…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"ภาพ"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"คลิปเสียง"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"วิดีโอ"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"บัตรติดต่อ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"เลิกทำ"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"ลองอีกครั้ง"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ป้อนชื่อผู้ติดต่อหรือหมายเลขโทรศัพท์เพื่อเริ่มเขียนข้อความใหม่"</string>
+    <string name="action_block" msgid="9032076625645190136">"บล็อก"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"บล็อก <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"เลิกบล็อก <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"ต้องการบล็อก <xliff:g id="DESTINATION">%s</xliff:g> ไหม"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"คุณจะยังคงได้รับข้อความจากหมายเลขนี้ต่อไปแต่จะไม่ได้รับการแจ้งเตือนอีก ระบบจะเก็บการสนทนานี้ไว้"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"รายชื่อที่บล็อกไว้"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"เลิกบล็อก"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"รายชื่อที่บล็อกไว้"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"เลือกรูปภาพจากห้องสมุดเอกสาร"</string>
+    <string name="sending_message" msgid="6363584950085384929">"กำลังส่งข้อความ"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"ส่งข้อความแล้ว"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"ข้อมูลมือถือปิดอยู่ โปรดตรวจสอบการตั้งค่า"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"ไม่สามารถส่งข้อความในโหมดบนเครื่องบินได้"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"ไม่สามารถส่งข้อความนี้"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"ดาวน์โหลดข้อความแล้ว"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"ข้อมูลมือถือปิดอยู่ โปรดตรวจสอบการตั้งค่า"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ไม่สามารถดาวน์โหลดข้อความในโหมดบนเครื่องบินได้"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"ไม่สามารถดาวน์โหลดข้อความได้"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"ศูนย์"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"หนึ่ง"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"สอง"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"สาม"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"สี่"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"ห้า"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"หก"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"เจ็ด"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"แปด"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"เก้า"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"ไม่สามารถส่งข้อความผ่าน <xliff:g id="CARRIERNAME">%1$s</xliff:g> ข้อผิดพลาด <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"ไม่สามารถส่งข้อความผ่านผู้ให้บริการที่ไม่รู้จัก ข้อผิดพลาด <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"ส่งต่อ: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"ไม่มีการส่งข้อความ เพราะยังไม่เปิดใช้งานบริการบนเครือข่าย"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"ไม่มีการส่งข้อความ: ที่อยู่ปลายทางไม่ถูกต้อง"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"ไม่มีการส่งข้อความ: ข้อความไม่ถูกต้อง"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"ไม่มีการส่งข้อความ: ระบบไม่สนับสนุนเนื้อหา"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"ไม่มีการส่งข้อความ: ระบบไม่สนับสนุนข้อความ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"ไม่ได้ส่งข้อความ: ขนาดใหญ่เกินไป"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"ข้อความใหม่"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"ดู"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"รูปภาพ"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"ไม่สามารถหาแอปพลิเคชันที่เหมาะสม"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"นำผู้รับออก"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"ข้อความใหม่"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"ยกเลิก"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"แก้ไขจุดเข้าใช้งาน"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"ไม่ได้ตั้งค่า"</string>
+    <string name="apn_name" msgid="1572691851070894985">"ชื่อ"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"พร็อกซี MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"พอร์ต MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"ประเภท APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"ลบ APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN ใหม่"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"บันทึก"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"ยกเลิก"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"ต้องใส่ข้อมูลในช่องชื่อ"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"ต้องใส่ข้อมูล APN"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"ช่อง MCC ต้องเป็นเลข 3 หลัก"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"ช่อง MNC ต้องเป็นเลข 2 หรือ 3 หลัก"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"กำลังคืนการตั้งค่า APN เริ่มต้น"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"รีเซ็ตเป็นค่าเริ่มต้น"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"รีเซ็ตการตั้งค่า APN กลับเป็นค่าเริ่มต้นเรียบร้อยแล้ว"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"ไม่มีชื่อ"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"ชื่อจุดเข้าใช้งาน"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN ใหม่"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"การตั้งค่าจุดเข้าใช้งานไม่สามารถใช้ได้สำหรับผู้ใช้รายนี้"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"คัดลอกไปยังคลิปบอร์ดไหม"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"คัดลอก"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ถึง <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"ทั่วไป"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"ขั้นสูง"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"การตั้งค่าทั่วไป"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"การตั้งค่าขั้นสูง"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"ซิม \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"ส่งข้อความ SMS ส่วนบุคคลให้กับผู้รับทุกคน เฉพาะคุณที่จะได้รับการตอบกลับ"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"ส่ง MMS เดี่ยวให้กับผู้รับทุกคน"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"ไม่ทราบหมายเลข"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"ข้อความใหม่"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"ข้อความใหม่"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"ตัวเลือกซิม"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"เลือก <xliff:g id="SIM_0">%1$s</xliff:g> แล้ว ตัวเลือกซิม"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"แก้ไขเรื่อง"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"เลือกซิมหรือแก้ไขเรื่อง"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"แตะค้างไว้เพื่อบันทึกเสียง"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"เริ่มต้นการสนทนาใหม่"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"การรับส่งข้อความ"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"รายการสนทนาในการรับส่งข้อความ"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"การรับส่งข้อความ"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"ข้อความใหม่"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"รายการการสนทนา"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"กำลังโหลดการสนทนา"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"กำลังโหลดข้อความ"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"ดูการสนทนาเพิ่มเติม"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"ดูข้อความเพิ่มเติม"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"ลบการสนทนาแล้ว"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"ลบการสนทนาแล้ว แตะเพื่อแสดงการสนทนาอื่นๆ ในการรับส่งข้อความ"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"ถูกบล็อก"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"เลิกบล็อกแล้ว"</string>
+    <string name="db_full" msgid="8459265782521418031">"พื้นที่เก็บข้อมูลเหลือน้อย ข้อมูลบางอย่างอาจสูญหายไป"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"เลือกไฟล์แนบ"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"ยืนยันการเลือก"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"เลือกไว้ <xliff:g id="COUNT">%d</xliff:g> รายการ"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"โปรดนำไฟล์แนบออกอย่างน้อย 1 รายการ แล้วลองอีกครั้ง"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"คุณสามารถลองส่งข้อความ แต่ข้อความอาจส่งไม่ได้หากคุณไม่ได้นำไฟล์แนบออกอย่างน้อย 1 รายการ"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"คุณสามารถส่งวิดีโอได้ 1 รายการต่อข้อความเท่านั้น โปรดนำวิดีโอเพิ่มเติมออกและลองอีกครั้ง"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"การรับส่งข้อความไม่สามารถโหลดไฟล์แนบ"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"ส่งเลย"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"ไม่สามารถเริ่มการสนทนาได้"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"เลือก <xliff:g id="SELECTED_SIM">%s</xliff:g> แล้ว"</string>
+</resources>
diff --git a/res/values-tl/arrays.xml b/res/values-tl/arrays.xml
new file mode 100644
index 0000000..6f30a29
--- /dev/null
+++ b/res/values-tl/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"walang paksa"</item>
+    <item msgid="272485471009191934">"nosubject"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Oo"</item>
+    <item msgid="6049132459802288033">"Hindi"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Salamat"</item>
+    <item msgid="4881335087096496747">"Sang-ayon ako"</item>
+    <item msgid="2422296858597420738">"Ayos"</item>
+    <item msgid="4805581752819452687">"Papunta na ako"</item>
+    <item msgid="4746700499431366214">"OK, balikan na lang kita mamaya"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
new file mode 100644
index 0000000..091949f
--- /dev/null
+++ b/res/values-tl/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Pagmemensahe"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Pagmemensahe"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Pumili ng pag-uusap"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Mga Setting"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Magpadala ng Mensahe"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Magdagdag ng attachment"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Tulong"</string>
+    <string name="welcome" msgid="2857560951820802321">"Maligayang Pagdating"</string>
+    <string name="skip" msgid="7238879696319945853">"Laktawan"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Susunod &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Susunod"</string>
+    <string name="exit" msgid="1905187380359981199">"Lumabas"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Mga Setting &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Mga Setting"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Kailangan ng pahintulot ng Pagmemensahe sa SMS, Telepono at Mga Contact."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Maaari mong baguhin ang mga pahintulot sa Mga Setting &gt; Mga App &gt; Pagmemensahe &gt; Mga Pahintulot."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Maaari mong baguhin ang mga pahintulot sa Mga Setting, Mga App, Pagmemensahe, Mga Pahintulot."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Mga madalas makaugnayan"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Lahat ng contact"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Ipadala sa <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Kumuha ng mga larawan o video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Pumili ng mga larawan mula sa device na ito"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"I-record ang audio"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Pumili ng larawan"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Napili ang media."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Inalis sa pagkakapili ang media."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ang pinili"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"larawan <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"larawan"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"I-record ang audio"</string>
+    <string name="action_share" msgid="2143483844803153871">"Ibahagi"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Ngayon lang"</string>
+    <string name="posted_now" msgid="867560789350406701">"Ngayon"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> na min</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> oras</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> na oras</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> araw</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> na araw</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> linggo</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na linggo</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> buwan</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na buwan</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> taon</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na taon</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Class 0 na mensahe"</string>
+    <string name="save" msgid="5081141452059463572">"I-save"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Kaunti na lang ang espasyo ng device. Awtomatikong ide-delete ng Pagmemensahe ang mga mas lumang mensahe upang magbakante ng espasyo."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Nauubos na ang espasyo ng storage"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Maaaring hindi makatanggap o makapagpadala ng mga mensahe ang Pagmemensahe hanggang sa maging available ang higit pang espasyo sa iyong device."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Kaunti na ang storage ng SMS. Maaaring kailanganin mong magtanggal ng mga mensahe."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Kumpirmahin ang numero ng iyong telepono"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Titiyakin ng isang beses na hakbang na ito na maihahatid nang maayos ng Pagmemensahe ang iyong mga mensahe sa pangkat."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Numero ng telepono"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Tanggalin ang lahat ng mensahe na may media"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Tangglain ang mga mensaheng lampas na ng <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Awtomatikong i-delete ang mga mensaheng mas luma sa <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Huwag Pansinin"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"I-delete ang lahat ng mensaheng may media?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"I-delete ang mga mensaheng mas luma sa <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Awtomatikong i-delete ang mga mensaheng mas luma sa <xliff:g id="DURATION">%s</xliff:g> at i-on ang awtomatikong pag-delete?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"Sinabi ni <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Sinabi mo"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Mensahe mula kay <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Nagpadala ka ng mensahe"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Ipinapadala..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Hindi naipadala. Pindutin upang subukang muli.."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Hindi naipadala. Sinusubukang muli…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Ipadalang muli o i-delete"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Mangyaring mag-voice call sa mga pang-emergency na serbisyo. Sa ngayon, hindi maipadala ang iyong text message."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Hindi nagawa"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Bagong MMS message na ida-download"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Bagong MMS message"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Hindi mai-download"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Pindutin upang subukang muli"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Pindutin upang i-download"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"I-download o i-delete"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Nagda-download..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Nag-expire o hindi available ang mensahe"</string>
+    <string name="mms_info" msgid="3402311750134118165">"laki: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, expiration: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Hindi maipadala. Di-wasto ang tatanggap."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Hindi naka-activate sa network ang serbisyo"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Hindi maipadala dahil sa problema sa network"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Nag-expire o hindi available ang mensahe"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Walang paksa)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Hindi kilalang nagpadala"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Naihatid"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Hindi ma-download ang mensaheng <xliff:g id="SUBJECT">%1$s</xliff:g> mula kay <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Hindi makumpleto ang operation sa database dahil sa mababang memory"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Hindi naipadala ang mensahe"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Hindi naipadala sa Pagmemensahe ang ilang mensahe"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> mensahe sa <xliff:g id="CONVERSATIONS">%d</xliff:g> pag-uusap</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> na mensahe sa <xliff:g id="CONVERSATIONS">%d</xliff:g> na pag-uusap</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Hindi na-download ang mensahe"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Hindi na-download sa Pagmemensahe ang ilang mensahe"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> mensahe sa <xliff:g id="CONVERSATIONS">%d</xliff:g> pag-uusap</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> na mensahe sa <xliff:g id="CONVERSATIONS">%d</xliff:g> na pag-uusap</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Hindi naipadala ang mensahe sa <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Mangyaring mag-voice call sa mga pang-emergency na serbisyo. Sa ngayon, hindi maipadala ang iyong text message sa <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> bagong mensahe</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> na bagong mensahe</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Magsimula"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Hindi available ang camera"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Hindi available ang camera"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Hindi available ang pagkuha ng video"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Hindi mai-save ang media"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Hindi makakakuha ng larawan"</string>
+    <string name="back" msgid="1477626055115561645">"Bumalik"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Naka-archive"</string>
+    <string name="action_delete" msgid="4076795795307486019">"I-delete"</string>
+    <string name="action_archive" msgid="5437034800324083170">"I-archive"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Alisin sa archive"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"I-off ang mga notification"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"I-on ang mga notification"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Magdagdag ng contact"</string>
+    <string name="action_download" msgid="7786338136368564146">"I-download"</string>
+    <string name="action_send" msgid="377635240181672039">"Ipadala"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"I-delete"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"I-delete ang mensaheng ito?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Hindi maaaring bawiin ang pagkilos na ito."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"I-delete"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">I-delete ang mga pag-uusap na ito?</item>
+      <item quantity="other">I-delete ang mga pag-uusap na ito?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Tanggalin"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Kanselahin"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Para kay"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Pumili ng maramihang larawan"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Kumpirmahin ang pinili"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Hindi mai-record ang audio. Subukang muli."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Hindi mai-play ang audio. Subukang muli."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Hindi mai-save ang audio. Subukang muli."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Pindutin nang matagal"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Larawan"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio clip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Contact card"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"I-download"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Tumugon sa pamamagitan ng SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Tumugon sa pamamagitan ng MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Tumugon"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> kalahok</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> na kalahok</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ako"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Na-block at na-archive ang contact"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Naka-unblock at hindi naka-archive ang contact"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ang na-archive"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ang inalis sa pagkaka-archive"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Naka-off ang mga notification"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Naka-on ang mga notification"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Handa na ang lahat. Pindutin muli ang Ipadala."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Matagumpay na naitakda ang Pagmemensahe bilang default na SMS app."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">I-discard ang mga attachment</item>
+      <item quantity="other">I-discard ang mga attachment</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Attachment na audio"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"I-play ang attachment na audio"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"I-pause"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Mensahe mula kay <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Hindi naipadalang mensahe mula kay <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Mensahe mula kay <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Hindi naipadalang mensahe kay <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Ipinapadala ang mensahe kay <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Hindi naipadalang mensahe kay <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Mensahe kay <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Hindi naipadalang mensahe mula kay <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Mensahe mula kay <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Hindi naipadalang mensahe sa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Ipinapadala ang mensahe sa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Hindi naipadalang mensahe sa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Mensahe sa <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Oras: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Hindi naipadalang mensahe. Pindutin upang subukang muli."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Pag-uusap kasama sina <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"I-delete ang paksa"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Kumuha ng video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Kumuha ng still na larawan"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Kumuha ng larawan"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Simulan ang pag-record ng video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Lumipat sa camera na full screen"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Lumipat sa pagitan ng camera sa harap at likod"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Ihinto ang pagre-record at i-attach ang video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Itigil ang pagre-record ng video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Mga larawan sa pagmemensahe"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> larawan ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> na larawan ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> video ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> na video ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> attachment ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> na attachment ang naka-save sa album na \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> attachment ang naka-save sa \"Mga Download\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> na attachment ang naka-save sa \"Mga Download\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> attachment ang na-save</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> na attachment ang na-save</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Hindi ma-save ang <xliff:g id="QUANTITY_1">%d</xliff:g> attachment</item>
+      <item quantity="other">Hindi ma-save ang <xliff:g id="QUANTITY_1">%d</xliff:g> na attachment</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Na-save na MMS attachment"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Mga Setting"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Naka-archive"</string>
+    <string name="action_close" msgid="1840519376200478419">"Isara"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Advanced"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"I-debug"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Mga Notification"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Tunog"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Naka-silent"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Mag-vibrate"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Naka-block"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Mga ulat sa pagpapadala ng SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Humiling ng ulat sa paghahatid para sa bawat SMS na iyong ipinapadala"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"I-auto-retrieve"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Awtomatikong kunin ang mga mensaheng MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Awtomatikong pagkuha sa roaming"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Awtomatikong kunin ang MMS kapag naka-roaming"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Panggrupong pagpapadala ng mensahe"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Gamitin ang MMS upang magpadala ng iisang mensahe kapag may maraming recipient"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Default na SMS app"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Default na SMS app"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Numero ng iyong telepono"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Hindi kilala"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Mga tunog ng papalabas na mensahe"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Itapon ang SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Itapon ang raw data ng natanggap na SMS sa file ng external storage"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Itapon ang MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Itapon ang raw data ng natanggap na MMS sa file ng external storage"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Mga wireless na alerto"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Mga opsyon sa mensahe"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopyahin ang text"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Tingnan ang mga detalye"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"I-delete"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Ipasa"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Mga detalye ng mensahe"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Uri: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Text message"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedia message"</string>
+    <string name="from_label" msgid="1947831848146564875">"Mula kay: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Para kay: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Ipinadala: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Natanggap: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Paksa: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Laki: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Priyoridad: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Mataas"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Mababa"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Nakatago ang address ng nagpadala"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Hindi maaaring magpadala ng mensahe habang naglo-load ng mga attachment."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Hindi mai-load ang attachment. Subukang muli."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Hindi pa handa ang network. Subukang muli."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"I-delete ang text"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Lumipat sa pagitan ng paglagay ng text at mga numero"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Magdagdag ng higit pang mga kalahok"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Kumpirmahin ang mga kalahok"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Magsimula ng bagong pag-uusap"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Piliin ang item na ito"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"I-play ang video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Mga tao at opsyon"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"I-debug"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Mga tao at opsyon"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Pangkalahatan"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Mga tao sa pag-uusap na ito"</string>
+    <string name="action_call" msgid="6596167921517350362">"Tumawag"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Magpadala ng mensahe"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Magpadala ng mensahe&lt;br/&gt;&lt;small&gt;mula sa <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Ipadala ang mga larawan</item>
+      <item quantity="other">Ipadala ang mga larawan</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Ipadala ang mga audio</item>
+      <item quantity="other">Ipadala ang mga audio</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Ipadala ang mga video</item>
+      <item quantity="other">Ipadala ang mga video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Ipadala ang mga contact card</item>
+      <item quantity="other">Ipadala ang mga contact card</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Ipadala ang mga attachment</item>
+      <item quantity="other">Ipadala ang mga attachment</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> attachment ang handa nang ipadala</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> na attachment ang handa nang ipadala</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Magpadala ng feedback"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Tingnan sa Google Play Store"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Impormasyon sa bersyon"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Bersyon %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Mga open source na lisensya"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Mga Notification"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Naabot na ang limitasyon ng attachment"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Hindi na-load ang attachment."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Idagdag sa Mga Contact?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Magdagdag ng Contact"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Subject"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Subject: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Nilo-load ang contact card"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Hindi mai-load ang contact card"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Tingnan ang contact card"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> contact</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> na contact</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Mga contact card"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Kaarawan"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Mga Tala"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Ipasa ang mensahe"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Tumugon"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Naka-disable ang SMS"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Upang ipadala, itakda ang Pagmemensahe bilang default na SMS app"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Itakda ang Pagmemensahe bilang default na SMS app"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Baguhin"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Upang makatanggap ng mga mensahe, itakda ang Pagmemensahe bilang default na SMS app"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Walang piniling gustong SIM para sa pagpapadala ng mga mensaheng SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Hindi pinapayagan ang app na ito ng may-ari ng device."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Masyadong maraming kalahok sa isang pag-uusap"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Mga di-wastong contact</item>
+      <item quantity="other">Mga di-wastong contact</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Hindi mai-load ang larawan ng camera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ikaw: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Draft"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Sa sandaling magsimula ka ng bagong pag-uusap, makikita mo ito na nakalista rito"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Lumalabas dito ang mga naka-archive na pag-uusap"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Nilo-load ang mga pag-uusap…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Larawan"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio clip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Card sa pakikipag-ugnayan"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"I-undo"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Subukang muli"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Maglagay ng pangalan ng contact o numero ng telepono upang magsimula ng isang bagong mensahe"</string>
+    <string name="action_block" msgid="9032076625645190136">"I-block"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"I-block ang <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Alisin sa pagkaka-block ang <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"I-block ang <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Patuloy kang makakatanggap ng mga mensahe mula sa numerong ito ngunit hindi ka na aabisuhan. Maa-archive ang pag-uusap na ito."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Mga na-block na contact"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ALISIN SA PAGKAKA-BLOCK"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Mga na-block na contact"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Pumili ng larawan mula sa library ng dokumento"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Ipinapadala ang mensahe"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Naipadala na ang mensahe"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Naka-off ang cellular data. Suriin ang iyong mga setting."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Hindi maaaring magpadala ng mga mensahe sa Airplane mode"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Hindi maipadala ang mensahe"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Na-download na ang mensahe"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Naka-off ang cellular data. Tingnan ang iyong mga setting."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Hindi maaaring mag-download ng mga mensahe sa Airplane mode"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Hindi ma-download ang mensahe"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Zero"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Isa"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Dalawa"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Tatlo"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Apat"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Lima"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Anim"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Pito"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Walo"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Siyam"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Hindi maipadala ang mensahe gamit ang <xliff:g id="CARRIERNAME">%1$s</xliff:g>, error na <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Hindi maipadala ang mensahe gamit ang hindi nakikilalang carrier, error na <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Hindi napadala ang mensahe: hindi naka-activate sa network ang serbisyo"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Hindi naipadala ang mensahe: di-wastong patutunguhang address"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Hindi naipadala ang mensahe: di-wastong mensahe"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Hindi naipadala ang mensahe: hindi sinusuportahang content"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Hindi naipadala ang mensahe: hindi sinusuportahang mensahe"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Hindi napadala ang mensahe: masyadong malaki"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Bagong mensahe"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Tingnan"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Larawan"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Hindi makahanap ng naaangkop na application"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Alisin ang tatanggap"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Bagong mensahe"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Kanselahin"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"I-edit ang access point"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Hindi nakatakda"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Pangalan"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy ng MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Port ng MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Uri ng APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"I-delete ang APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Bagong APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"I-save"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"I-discard"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Hindi maaaring walang laman ang field ng Pangalan."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Hindi maaaring walang laman ang APN."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Dapat na 3 digit ang field na MCC."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Dapat na 2 o 3 digit ang field ng MNC."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Nire-restore ang default na mga setting ng APN"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"I-reset sa default"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Nakumpleto na ang pag-reset sa default na mga setting ng APN."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Walang pamagat"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Mga Access Point Name"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Mga APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Bagong APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Hindi available ang mga setting ng Access Point Name para sa user na ito"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopyahin sa clipboard?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopyahin"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"sa <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Pangkalahatan"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Advanced"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Mga pangkalahatang setting"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Mga advanced na setting"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Magpadala ng mga indibidwal na mensaheng SMS sa lahat ng tatanggap. Ikaw lang ang makakatanggap ng anumang mga tugon"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Magpadala ng iisang MMS sa lahat ng tatanggap"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Hindi kilalang numero"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Bagong mensahe"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Bagong mensahe."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM selector"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Pinili ang <xliff:g id="SIM_0">%1$s</xliff:g>, selector ng SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"I-edit ang paksa"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Pumili ng SIM o i-edit ang paksa"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Pindutin nang matagal upang i-record ang audio"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Magsimula ng bagong pag-uusap"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Pagmemensahe"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Listahan ng Pagmemensahe"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Pagmemensahe"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Bagong mensahe"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Listahan ng pag-uusap"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Nilo-load ang mga pag-uusap"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Nilo-load ang mga mensahe"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Tumingin ng higit pang pag-uusap"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Tingnan ang higit pang mga mensahe"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Na-delete na ang pag-uusap"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Na-delete na ang pag-uusap. Pindutin upang magpakita ng iba\'t ibang pag-uusap sa Pagmemensahe"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Na-block"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Na-unblock"</string>
+    <string name="db_full" msgid="8459265782521418031">"Kaunti na lang ang espasyo sa storage. Maaaring mawala ang ilang data."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Pumili ng mga attachment"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Kumpirmahin ang napili"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ang napili"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Mangyaring mag-alis ng isa o higit pang mga attachment at subukang muli."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Maaari mong subukang ipadala ang iyong mensahe, ngunit maaaring hindi ito maipadala maliban kung mag-aalis ka ng isa o higit pang mga attachment."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Maaari ka lang magpadala ng isang video sa bawat mensahe. Mangyaring alisin ang mga karagdagang video at subukang muli."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Hindi na-load ng pagmemensahe ang attachment."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Ipadala pa rin"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Hindi makapagsimula ng pag-uusap"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> ang napili"</string>
+</resources>
diff --git a/res/values-tr/arrays.xml b/res/values-tr/arrays.xml
new file mode 100644
index 0000000..d0b4e84
--- /dev/null
+++ b/res/values-tr/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"konu yok"</item>
+    <item msgid="272485471009191934">"konu yok"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Evet"</item>
+    <item msgid="6049132459802288033">"Hayır"</item>
+    <item msgid="3084376867445867895">"Tamam"</item>
+    <item msgid="3155097332660174689">"Olur"</item>
+    <item msgid="2611328818571146775">"Teşekkürler"</item>
+    <item msgid="4881335087096496747">"Kabul ediyorum"</item>
+    <item msgid="2422296858597420738">"Güzel"</item>
+    <item msgid="4805581752819452687">"Yoldayım"</item>
+    <item msgid="4746700499431366214">"Tamam, sana sonra dönerim"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
new file mode 100644
index 0000000..7d7fefb
--- /dev/null
+++ b/res/values-tr/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Mesajlaşma"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Mesajlaşma"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"İleti dizisini seç"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Ayarlar"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"İleti Gönder"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Dosya ekle"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Yardım"</string>
+    <string name="welcome" msgid="2857560951820802321">"Hoş geldiniz"</string>
+    <string name="skip" msgid="7238879696319945853">"Atla"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Sonraki &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Sonraki"</string>
+    <string name="exit" msgid="1905187380359981199">"Çık"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Ayarlar &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Ayarlar"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Mesajlaşma\'nın SMS, Telefon ve Kişiler için izninize ihtiyacı var."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"İzinleri; Ayarlar &gt; Uygulamalar &gt; Mesajlaşma &gt; İzinler\'de değiştirebilirsiniz."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"İzinleri; Ayarlar, Uygulamalar, Mesajlaşma, İzinler\'de değiştirebilirsiniz."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Sık kullanılanlar"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tüm kişiler"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Şuraya gönder: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Fotoğraf veya video çekin"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Bu cihazdan resim seç"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Ses kaydedin"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Fotoğraf seç"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Medya seçildi."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Medya seçilmedi."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> öğe seçildi"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"resim <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"resim"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Ses kaydedin"</string>
+    <string name="action_share" msgid="2143483844803153871">"Paylaş"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Şimdi"</string>
+    <string name="posted_now" msgid="867560789350406701">"Şimdi"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> dk.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> dk.</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> saat</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> saat</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> gün</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> gün</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hafta</item>
+      <item quantity="one">bir hafta</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ay</item>
+      <item quantity="one">bir ay</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> yıl</item>
+      <item quantity="one">bir yıl</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Sınıf 0 iletisi"</string>
+    <string name="save" msgid="5081141452059463572">"Kaydet"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Cihazınızda boş alan az. Mesajlaşma boş alan açmak için daha eski iletileri otomatik olarak silecektir."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Depolama alanı bitiyor"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Mesajlaşma, cihazınızda daha fazla yer açılana kadar ileti gönderip almayabilir."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS depolama alanı azaldı. İletileri silmeniz gerekebilir."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Telefon numaranızı doğrulayın"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Bu bir kerelik adım, Mesajlaşma\'nın, grup iletilerini düzgün olarak teslim etmesini sağlayacaktır."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefon numarası"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Medya içeren tüm iletileri sil"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Şundan eski iletileri sil: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Şundan daha eski iletileri otomatik olarak sil: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Yoksay"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Medya içeren tüm iletiler silinsin mi?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Şundan daha eski iletiler silinsin mi: <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Şundan daha eski iletiler silinip otomatik silme etkinleştirilsin mi: <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> şunu dedi:"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Şunu dediniz:"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> adlı kişiden ileti"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Bir ileti gönderdiniz"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Gönderiliyor..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Gönderilmedi. Tekrar denemek için dokunun."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Gönderilmedi. Tekrar deniyor…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Yeniden gönderin veya silin"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Lütfen acil durum servislerine telefon edin. Kısa mesajınız şu anda teslim edilemedi."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Başarısız oldu"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"İndirilecek yeni MMS iletisi"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Yeni MMS iletisi"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"İndirilemedi"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Tekrar denemek için dokunun"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"İndirmek için dokunun"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"İndirin veya silin"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"İndiriliyor..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"İletinin süresi doldu veya kullanılamıyor"</string>
+    <string name="mms_info" msgid="3402311750134118165">"boyut: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, süre sonu: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Gönderilemiyor. Alıcı geçersiz."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Hizmet, ağda etkinleştirilmemiş"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Ağ sorunu nedeniyle gönderilemedi"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"İletinin süresi doldu veya kullanılamıyor"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Konu yok)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Bilinmeyen gönderen"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Teslim edildi"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"<xliff:g id="FROM">%2$s</xliff:g> tarafından gönderilen <xliff:g id="SUBJECT">%1$s</xliff:g> konulu ileti indirilemedi."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Yetersiz bellek nedeniyle veritabanı işlemi tamamlanamadı"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"İleti gönderilmedi"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Bazı iletiler Mesajlaşma\'da gönderilmedi"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ileti dizisinde <xliff:g id="CONVERSATIONS">%d</xliff:g> ileti</item>
+      <item quantity="one">Bir ileti dizisinde <xliff:g id="MESSAGES_0">%d</xliff:g> ileti</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"İleti indirilmedi"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Bazı iletiler Mesajlaşma\'dan indirilmedi"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> ileti dizisinde <xliff:g id="CONVERSATIONS">%d</xliff:g> ileti</item>
+      <item quantity="one">Bir ileti dizisinde <xliff:g id="MESSAGES_0">%d</xliff:g> ileti</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> numaralı telefona ileti gönderilemedi"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Lütfen acil durum servislerine telefon edin. <xliff:g id="NUMBER">%1$s</xliff:g> numaralı telefona gönderdiğiniz kısa mesajınız şu anda teslim edilemedi."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> yeni ileti</item>
+      <item quantity="one">Yeni ileti</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Başlat"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera kullanılamıyor"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera kullanılamıyor"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Video çekimi kullanılamıyor"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Medya kaydedilemiyor"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Resim çekilemiyor"</string>
+    <string name="back" msgid="1477626055115561645">"Geri"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arşivlenen"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Sil"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arşivle"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Arşivden kaldır"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Bildirimleri devre dışı bırak"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Bildirimleri aç"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Kişi ekle"</string>
+    <string name="action_download" msgid="7786338136368564146">"İndir"</string>
+    <string name="action_send" msgid="377635240181672039">"Gönder"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Sil"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Bu ileti silinsin mi?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Bu işlem geri alınamaz."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Sil"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Bu ileti dizileri silinsin mi?</item>
+      <item quantity="one">Bu ileti dizisi silinsin mi?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Sil"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"İptal"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Alıcı:"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Birden fazla resim seç"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Seçimi onayla"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Ses kaydedilemiyor. Tekrar deneyin."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Ses çalınamıyor. Tekrar deneyin."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Ses kaydedilemedi. Tekrar deneyin."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Dokunup basılı tutun"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Resim"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Ses klibi"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kişi kartı"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"İndir"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS ile yanıtla"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS ile yanıtla"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Yanıtla"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> katılımcı</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> katılımcı</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Ben"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kişi engellendi ve arşivlendi"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kişinin engellemesi kaldırıldı ve kişi arşivden geri alındı"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ileti dizisi arşivlendi"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ileti dizisi arşivden kaldırıldı"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Bildirimler kapalı"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Bildirimler açık"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Tümü ayarlandı. Gönder\'e tekrar dokunun."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Mesajlaşma, başarılı bir şekilde varsayılan SMS uygulaması olarak ayarlandı."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Ekleri sil</item>
+      <item quantity="one">Eki sil</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Ses dosyası eki"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Ekli ses dosyasını çal"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Duraklat"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> adlı kişiden ileti: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Şu ileti <xliff:g id="SENDER">%1$s</xliff:g> tarafından gönderilemedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Şu ileti <xliff:g id="SENDER">%1$s</xliff:g> tarafından gönderildi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Şu ileti <xliff:g id="CONTACT">%1$s</xliff:g> adlı kişiye gönderilmedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Şu ileti <xliff:g id="CONTACT">%1$s</xliff:g> adlı kişiye gönderiliyor: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Şu ileti <xliff:g id="CONTACT">%1$s</xliff:g> adlı kişiye gönderilemedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Şu ileti <xliff:g id="CONTACT">%1$s</xliff:g> adlı kişiye gönderildi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Şu ileti <xliff:g id="SENDER">%1$s</xliff:g> tarafından gönderilemedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Şu ileti <xliff:g id="SENDER">%1$s</xliff:g> tarafından gönderildi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Şu ileti <xliff:g id="GROUP">%1$s</xliff:g> adlı gruba gönderilmedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Şu ileti <xliff:g id="GROUP">%1$s</xliff:g> adlı gruba gönderiliyor: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Şu ileti <xliff:g id="GROUP">%1$s</xliff:g> adlı gruba gönderilemedi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Şu ileti <xliff:g id="GROUP">%1$s</xliff:g> adlı gruba gönderildi: <xliff:g id="MESSAGE">%2$s</xliff:g>. Saat: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"İleti başarısız oldu. Yeniden denemek için dokunun."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> ile ileti dizisi"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Konuyu sil"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video çek"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Fotoğraf çek"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Fotoğraf çek"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Video kaydetmeye başla"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Tam ekran kameraya geç"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Ön ve arka kamera arasında geçiş yap"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Kaydı durdur ve video ekle"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Video kaydını durdur"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Mesajlaşma fotoğrafları"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> fotoğraf, \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albümüne kaydedildi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> fotoğraf, \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albümüne kaydedildi</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video, \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albümüne kaydedildi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video, \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albümüne kaydedildi</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other">Ekli <xliff:g id="QUANTITY_2">%d</xliff:g> dosya, \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" albümüne kaydedildi</item>
+      <item quantity="one">Ekli <xliff:g id="QUANTITY_0">%d</xliff:g> dosya, \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" albümüne kaydedildi</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other">Ekli <xliff:g id="QUANTITY_1">%d</xliff:g> dosya, \"İndirilenler\"e kaydedildi</item>
+      <item quantity="one">Ekli <xliff:g id="QUANTITY_0">%d</xliff:g> dosya, \"İndirilenler\"e kaydedildi</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ek kaydedildi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ek kaydedildi</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ek kaydedilemedi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ek kaydedilemedi</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS eki kaydedildi"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Ayarlar"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arşivlenen"</string>
+    <string name="action_close" msgid="1840519376200478419">"Kapat"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Gelişmiş"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Hata Ayıklama"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Bildirimler"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ses"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Sessiz"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Titreşim"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Engellendi"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS iletim raporları"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Gönderilen her SMS için bir iletim raporu iste"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Otomatik al"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS iletilerini otomatik olarak al"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Dolaşımda otomatik al"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Dolaşımdayken MMS\'leri otomatik olarak al"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Grup mesajları"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Birden fazla alıcıya tek bir ileti göndermek için MMS kullanın"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Varsayılan SMS uygulaması"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Varsayılan SMS uygulaması"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Telefon numaranız"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Bilinmiyor"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Giden ileti sesleri"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS verilerini aktar"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Alınan ham SMS verilerini harici bir depolama dosyasına aktarın"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS verilerini aktar"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Alınan ham MMS verilerini harici bir depolama dosyasına aktarın"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Kablosuz uyarıları"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"İleti seçenekleri"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Metni kopyala"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Ayrıntıları görüntüle"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Sil"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Yönlendir"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"İleti ayrıntıları"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Tür: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Kısa mesaj"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimedya iletisi"</string>
+    <string name="from_label" msgid="1947831848146564875">"Gönderen: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Alıcı: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Gönderilme tarihi: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Alınma tarihi: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Konu: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Boyut: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Öncelik: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Yüksek"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Normal"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Düşük"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Gizli gönderen adresi"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Ekler yüklenirken ileti gönderilemez."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Ek yüklenemiyor. Tekrar deneyin."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Ağ hazır değil. Tekrar deneyin."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Metni sil"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Metin ve sayı girişi arasında geçiş yap"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Daha fazla katılımcı ekle"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Katılımcıları onayla"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Yeni ileti dizisi başlat"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Bu öğeyi seçin"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Videoyu oynat"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Kişiler ve seçenekler"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Hata ayıkla"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Kişiler ve seçenekler"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Genel"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Bu görüşmedeki kişiler"</string>
+    <string name="action_call" msgid="6596167921517350362">"Çağrı yap"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"İleti gönder"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Mesajı şu karttan gönder:&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Fotoğrafları gönder</item>
+      <item quantity="one">Fotoğrafı gönder</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Ses dosyalarını gönder</item>
+      <item quantity="one">Ses dosyasını gönder</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Videoları gönder</item>
+      <item quantity="one">Videoyu gönder</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Kişi kartlarını gönder</item>
+      <item quantity="one">Kişi kartını gönder</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Ekleri gönder</item>
+      <item quantity="one">Eki gönder</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ek gönderilmeye hazır</item>
+      <item quantity="one">Bir ek gönderilmeye hazır</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Geri bildirim gönder"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Google Play Store\'da görüntüle"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Sürüm bilgisi"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Sürüm %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Açık kaynak lisansları"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Bildirimler"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Ek sınırına ulaşıldı"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Ek yüklenemedi."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Kişilere eklensin mi?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Kişi Ekle"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Konu"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Konu: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kişi kartı yükleniyor"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kişi kartı yüklenemedi"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Kişi kartını görüntüle"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kişi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kişi</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kişi kartları"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Doğum günü"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Notlar"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"İletiyi yönlendir"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Yanıtla"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS devre dışı bırakıldı"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Göndermek için Mesajlaşma\'yı varsayılan SMS uygulamanız olarak ayarlayın"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Mesajlaşma\'yı varsayılan SMS uygulamanız olarak ayarlayın"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Değiştir"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"İletileri almak için Mesajlaşma\'yı varsayılan SMS uygulamanız olarak ayarlayın"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS iletilerini göndermek için SIM tercihi yapılmadı"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Cihaz sahibi bu uygulamaya izin vermiyor."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"Tamam"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Bir görüşmede çok fazla katılımcı var"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Geçersiz kişiler</item>
+      <item quantity="one">Geçersiz kişi</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kamera görüntüsü yüklenemedi"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Siz: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Taslak"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Yeni bir görüşme başlattığınızda burada listelendiğini göreceksiniz"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arşivlenmiş ileti dizileri burada görünür"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"İleti dizileri yükleniyor..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Resim"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Ses klibi"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kişi kartı"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Geri al"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Yeniden dene"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Yeni bir iletiye başlamak için bir kişi adı veya telefon numarası girin"</string>
+    <string name="action_block" msgid="9032076625645190136">"Engelle"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> hedefini engelle"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> adlı kişinin engellemesini kaldır"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> engellensin mi?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Bu numaradan gelen iletileri almaya devam edecek ancak artık bildirim almayacaksınız. Bu ileti dizisi arşivlenecektir."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Engellenen kişiler"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"ENGELLEMEYİ KALDIR"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Engellenen kişiler"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Doküman kitaplığından resim seç"</string>
+    <string name="sending_message" msgid="6363584950085384929">"İleti gönderiliyor"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"İleti gönderildi"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Hücresel veri özelliği kapalı. Ayarlarınızı kontrol edin."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Uçak modunda iletiler gönderilemiyor"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"İleti gönderilemedi"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"İleti indirildi"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Hücresel veri özelliği kapalı. Ayarlarınızı kontrol edin."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Uçak modundayken iletiler indirilemez"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"İleti indirilemedi"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Sıfır"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Bir"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"İki"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Üç"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Dört"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Beş"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Altı"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Yedi"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Sekiz"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Dokuz"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> ile ileti gönderilemiyor. Hata kodu: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Bilinmeyen operatör ile ileti gönderilemiyor. Hata kodu: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Yön: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"İleti gönderilmedi: Hizmet, ağ üzerinde etkin değil"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"İleti gönderilmedi: Geçersiz gönderim adresi"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"İleti gönderilmedi: Geçersiz ileti"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"İleti gönderilmedi: Desteklenmeyen içerik"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"İleti gönderilmedi: Desteklenmeyen ileti"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"İleti gönderilmedi: Çok büyük"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Yeni ileti"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Görüntüle"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Resim"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Uygun bir uygulama bulunamadı"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Alıcıyı kaldır"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Yeni ileti"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"İptal"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Erişim noktasını düzenle"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ayarlanmadı"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Ad"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proxy\'si"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS bağlantı noktası"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN türü"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APN\'yi sil"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Yeni APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Kaydet"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Yoksay"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Ad alanı boş olamaz."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN boş olamaz."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC alanındaki değer 3 rakamdan oluşmalıdır."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC alanındaki değer 2 veya 3 rakamdan oluşmalıdır."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Varsayılan APN ayarları geri yükleniyor."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Varsayılana sıfırla"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Varsayılan APN ayarlarına sıfırlama tamamlandı."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Başlıksız"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Erişim Noktası Adları (APN)"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN\'ler"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Yeni APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Erişim Noktası Adı (APN) ayarları bu kullanıcı için kullanılamıyor"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Panoya kopyalansın mı?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopyala"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"Mesajın alınacağı kart: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Genel"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Gelişmiş"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Genel ayarlar"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Gelişmiş ayarlar"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Tüm alıcılara tek tek SMS iletisi gönder. Sadece size yanıt gönderilir."</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Tüm alıcılara tek bir MMS iletisi gönder"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Bilinmeyen numara"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Yeni ileti"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Yeni ileti."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM seçici"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> seçildi, SIM seçici"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Konuyu düzenle"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM seçin veya konuyu düzenleyin"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Ses kaydetmek için dokunun ve basılı tutun"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Yeni ileti dizisi başlat"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Mesajlaşma"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Mesajlaşma Listesi"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Mesajlaşma"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Yeni ileti"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"İleti dizisi listesi"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"İleti dizileri yükleniyor"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"İletiler yükleniyor"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Diğer ileti dizilerini görüntüle"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Daha fazla ileti görüntüle"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"İleti dizisi silindi"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"İleti dizisi silindi. Farklı bir Mesajlaşma ileti dizisini görüntülemek için dokunun"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Engellendi"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Engellemesi kaldırıldı"</string>
+    <string name="db_full" msgid="8459265782521418031">"Depolama alanı az. Bazı veriler kaybolabilir."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Ekleri seçin"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Seçimi onayla"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> öğe seçildi"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Lütfen bir veya daha fazla eki kaldırın ve tekrar deneyin."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"İletinizi göndermeyi deneyebilirsiniz, ancak bir veya daha fazla eki kaldırmadığınız sürece ileti teslim edilmeyebilir."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Her iletide yalnızca bir tane video gönderebilirsiniz. Lütfen ek videoları kaldırın ve tekrar deneyin."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Mesajlaşma, eki yükleyemedi."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Yine de gönder"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Sohbet başlatılamadı"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> seçildi"</string>
+</resources>
diff --git a/res/values-uk/arrays.xml b/res/values-uk/arrays.xml
new file mode 100644
index 0000000..fc47a64
--- /dev/null
+++ b/res/values-uk/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"без теми"</item>
+    <item msgid="272485471009191934">"без теми"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Так"</item>
+    <item msgid="6049132459802288033">"Ні"</item>
+    <item msgid="3084376867445867895">"ОК"</item>
+    <item msgid="3155097332660174689">"Ха-ха-ха"</item>
+    <item msgid="2611328818571146775">"Дякую"</item>
+    <item msgid="4881335087096496747">"Погоджуюсь"</item>
+    <item msgid="2422296858597420738">"Чудово"</item>
+    <item msgid="4805581752819452687">"У дорозі"</item>
+    <item msgid="4746700499431366214">"Добре, я зателефоную пізніше"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
new file mode 100644
index 0000000..1fa8a2e
--- /dev/null
+++ b/res/values-uk/strings.xml
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Повідомлення"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Повідомлення"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Виберіть ланцюжок повідомлень"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Налаштування"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Надіслати повідомлення"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Вкласти файл"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Довідка"</string>
+    <string name="welcome" msgid="2857560951820802321">"Вітаємо"</string>
+    <string name="skip" msgid="7238879696319945853">"Пропустити"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Далі &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Далі"</string>
+    <string name="exit" msgid="1905187380359981199">"Вийти"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Налаштування &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Налаштування"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Додатку Повідомлення потрібен доступ до SMS, телефона й контактів."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Щоб змінити дозволи, виберіть \"Налаштування\" &gt; \"Додатки\" &gt; \"Повідомлення\" &gt; \"Дозволи\"."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Щоб змінити дозволи, виберіть \"Налаштування\" &gt; \"Додатки\" &gt; \"Повідомлення\" &gt; \"Дозволи\"."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Найчастіше на зв’язку"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Усі контакти"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Надіслати на номер <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Зняти фото або відео"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Вибрати зображення на цьому пристрої"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Записати аудіо"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Вибрати фотографію"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Медіафайл вибрано."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Медіафайл не вибрано."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Вибрано <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"зображення: <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"зображення"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Записати аудіо"</string>
+    <string name="action_share" msgid="2143483844803153871">"Поділитися"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Щойно"</string>
+    <string name="posted_now" msgid="867560789350406701">"Зараз"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> хвилина</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> хвилини</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> хвилин</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> хвилини</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> година</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> години</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> годин</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> години</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> день</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> дні</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> днів</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> дня</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> тиждень</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> тижні</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> тижнів</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> тижня</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> місяць</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> місяці</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> місяців</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> місяця</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> рік</item>
+      <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> роки</item>
+      <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> років</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> року</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Повідомлення класу 0"</string>
+    <string name="save" msgid="5081141452059463572">"Зберегти"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"На пристрої замало місця. З додатка Повідомлення буде автоматично видалено старіші SMS, щоб звільнити місце."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Закінчується пам’ять"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Додаток Повідомлення не зможе надсилати й отримувати SMS, доки не звільниться місце на пристрої."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Недостатньо місця для SMS. Видаліть старі повідомлення."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Підтвердьте свій номер телефону"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Номер потрібен, щоб надсилати групові повідомлення. Його потрібно ввести лише один раз."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Номер телефону"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Видалити всі повідомлення з медіафайлами"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Видалити повідомлення, отримані понад <xliff:g id="DURATION">%s</xliff:g> тому"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Автоматично видаляти повідомлення, отримані понад <xliff:g id="DURATION">%s</xliff:g> тому"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ігнорувати"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Видалити всі повідомлення з медіафайлами?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Видалити повідомлення, отримані понад <xliff:g id="DURATION">%s</xliff:g> тому?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Видаляти повідомлення, отримані понад <xliff:g id="DURATION">%s</xliff:g> тому й увімкнути автоматичне видалення?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"Повідомлення від користувача <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Ваше повідомлення"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Повідомлення від користувача <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Ви надіслали повідомлення"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Надсилання…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Не надіслано. Торкніться, щоб повторити спробу."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Не надіслано. Повторна спроба…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Надіслати повторно або видалити"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Не вдалося надіслати текстове повідомлення в екстрену службу. Спробуйте зателефонувати."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Помилка"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Доступне нове MMS-повідомлення"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Нове MMS-повідомлення"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Не вдалося завантажити"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Торкніться, щоб повторити спробу"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Торкніться, щоб завантажити"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Завантажити або видалити"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Завантаження…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Повідомлення прострочене або недоступне"</string>
+    <string name="mms_info" msgid="3402311750134118165">"розмір: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, дійсне до: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Не вдається надіслати. Недійсний отримувач."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Послугу не активовано в мережі"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Не вдалося надіслати через проблему з мережею"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Повідомлення прострочене або недоступне"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Без теми)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Невідомий відправник"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Доставлено"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Не вдалося завантажити повідомлення з темою \"<xliff:g id="SUBJECT">%1$s</xliff:g>\" від користувача <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Не вдалося завершити дію з базою даних. Недостатньо пам’яті"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Повідомлення не надіслано"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Деякі повідомлення не надіслано"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлень у ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Повідомлення не завантажено"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Деякі повідомлення не завантажено"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="few"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="many"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлень у ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> повідомлення в ланцюжках (<xliff:g id="CONVERSATIONS">%d</xliff:g>)</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Повідомлення на номер <xliff:g id="NUMBER">%1$s</xliff:g> не надіслано"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Не вдалося надіслати текстове повідомлення на номер екстреної служби <xliff:g id="NUMBER">%1$s</xliff:g>. Спробуйте зателефонувати."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> нове повідомлення</item>
+      <item quantity="few"><xliff:g id="MESSAGES">%d</xliff:g> нові повідомлення</item>
+      <item quantity="many"><xliff:g id="MESSAGES">%d</xliff:g> нових повідомлень</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> нового повідомлення</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Почати"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Камера недоступна"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Камера недоступна"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Відеозйомка недоступна"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Не вдається зберегти медіафайли"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Не вдається сфотографувати"</string>
+    <string name="back" msgid="1477626055115561645">"Назад"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Архів"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Видалити"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Архів"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Розархівувати"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Вимкнути сповіщення"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Увімкнути сповіщення"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Додати контакт"</string>
+    <string name="action_download" msgid="7786338136368564146">"Завантажити"</string>
+    <string name="action_send" msgid="377635240181672039">"Надіслати"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Видалити"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Видалити це повідомлення?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Цю дію не можна скасувати."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Видалити"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Видалити ці ланцюжки повідомлень?</item>
+      <item quantity="few">Видалити ці ланцюжки повідомлень?</item>
+      <item quantity="many">Видалити ці ланцюжки повідомлень?</item>
+      <item quantity="other">Видалити ці ланцюжки повідомлень?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Видалити"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Скасувати"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Кому:"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Вибрати кілька зображень"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Підтвердити вибір"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Не вдається записати аудіо. Повторіть спробу."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Не вдається відтворити аудіо. Повторіть спробу."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Не вдалося зберегти аудіо. Повторіть спробу."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Натисніть і утримуйте"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Зображення"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Аудіокліп"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Відео"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Картка контакта"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Завантажити"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Відповісти за допомогою SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Надіслати MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Відповісти"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> учасник</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> учасники</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> учасників</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> учасника</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Я"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Користувача заблоковано та заархівовано"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Контакт розблоковано та розархівовано"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Заархівовано: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Розархівовано: <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Сповіщення вимкнено"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Сповіщення ввімкнено"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Готово. Торкніться опції \"Надіслати\" знову."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Повідомлення тепер є додатком для SMS за умовчанням."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Видалити вкладені файли</item>
+      <item quantity="few">Видалити вкладені файли</item>
+      <item quantity="many">Видалити вкладені файли</item>
+      <item quantity="other">Видалити вкладені файли</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Вкладений аудіофайл"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Відтворити аудіовкладення"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Пауза"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Повідомлення від користувача <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Не вдалося надіслати повідомлення від користувача <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Повідомлення від користувача <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Ненадіслане повідомлення групі <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Надсилається повідомлення групі <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Не вдалося надіслати повідомлення групі <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Повідомлення групі <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Не вдалося надіслати повідомлення від користувача <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Повідомлення від користувача <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Ненадіслане повідомлення групі <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Надсилається повідомлення групі <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Не вдалося надіслати повідомлення групі <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Повідомлення групі <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Час: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Не вдалося надіслати повідомлення. Торкніться, щоб повторити спробу."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Учасники бесіди: <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Видалити тему"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Зняти відео"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Зняти статичне зображення"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Зробити знімок"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Почати запис відео"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Показувати зображення з камери на весь екран"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Переключатися між камерами на передній і задній панелях"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Зупинити запис і долучити відео"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Зупинити запис відео"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Фото з повідомлень"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографію збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографії збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографій збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> фотографії збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> відео збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> відео збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> відео збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> відео збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> вкладений файл збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_2">%d</xliff:g> вкладені файли збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_2">%d</xliff:g> вкладених файлів збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> вкладеного файлу збережено в альбом \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> вкладений файл збережено в папку \"Завантаження\"</item>
+      <item quantity="few"><xliff:g id="QUANTITY_1">%d</xliff:g> вкладені файли збережено в папку \"Завантаження\"</item>
+      <item quantity="many"><xliff:g id="QUANTITY_1">%d</xliff:g> вкладених файлів збережено в папку \"Завантаження\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> вкладеного файлу збережено в папку \"Завантаження\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one">Збережено <xliff:g id="QUANTITY_1">%d</xliff:g> вкладений файл</item>
+      <item quantity="few">Збережено <xliff:g id="QUANTITY_1">%d</xliff:g> вкладені файли</item>
+      <item quantity="many">Збережено <xliff:g id="QUANTITY_1">%d</xliff:g> вкладених файлів</item>
+      <item quantity="other">Збережено <xliff:g id="QUANTITY_1">%d</xliff:g> вкладеного файлу</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Не вдалося зберегти <xliff:g id="QUANTITY_1">%d</xliff:g> вкладений файл</item>
+      <item quantity="few">Не вдалося зберегти <xliff:g id="QUANTITY_1">%d</xliff:g> вкладені файли</item>
+      <item quantity="many">Не вдалося зберегти <xliff:g id="QUANTITY_1">%d</xliff:g> вкладених файлів</item>
+      <item quantity="other">Не вдалося зберегти <xliff:g id="QUANTITY_1">%d</xliff:g> вкладеного файлу</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Вкладення з MMS збережено"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Налаштування"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Архів"</string>
+    <string name="action_close" msgid="1840519376200478419">"Закрити"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Додатково"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Налагодження"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Сповіщення"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Сигнал"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Без звуку"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Вібросигнал"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Заблоковано"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Звіти про доставку SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Запитувати звіт про доставку для кожного надісланого SMS"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Автоматичне отримання"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Автоматично отримувати MMS-повідомлення"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Автоотримання в роумінгу"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Автоматично отримувати MMS у роумінгу"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Групові повідомлення"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Використовуйте опцію MMS, щоб надсилати одне повідомлення декільком одержувачам"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Додаток для SMS за умовчанням"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Додаток для SMS за умовчанням"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Ваш номер телефону"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Невідомий"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Сигнали для вихідних повідомлень"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Записати дані SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Записати отримані вихідні дані SMS у файл зовнішньої пам’яті"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Записати дані MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Записати отримані вихідні дані MMS у файл зовнішньої пам’яті"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Сповіщення через бездротові мережі"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Параметри повідомлення"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Копіювати текст"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Переглянути деталі"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Видалити"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Переслати"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Деталі повідомлення"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Тип: "</string>
+    <string name="text_message" msgid="7415419755252205721">"SMS"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Мультимедійне повідомлення"</string>
+    <string name="from_label" msgid="1947831848146564875">"Від: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Кому: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Надіслано: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Отримано: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Тема: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Розмір: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Пріоритет: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-карта: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Високий"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Звичайний"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Низький"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM-карта <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Прихована адреса відправника"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Неможливо надіслати повідомлення під час завантаження вкладених файлів."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Не вдається завантажити вкладений файл. Повторіть спробу."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Мережа не готова. Повторіть спробу."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Видалити текст"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Переключення між введенням тексту та числами"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Додати більше учасників"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Підтвердити учасників"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Почати нову бесіду"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Вибрати цей елемент"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Відтворити відео"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Учасники й опції"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Налагодження"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Учасники й опції"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Загальні"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Учасники цієї бесіди"</string>
+    <string name="action_call" msgid="6596167921517350362">"Телефонувати"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Надіслати повідомлення"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Надіслати повідомлення&lt;br/&gt;&lt;small&gt;із SIM-карти <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Надіслати фото</item>
+      <item quantity="few">Надіслати фото</item>
+      <item quantity="many">Надіслати фото</item>
+      <item quantity="other">Надіслати фото</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Надіслати аудіозаписи</item>
+      <item quantity="few">Надіслати аудіозаписи</item>
+      <item quantity="many">Надіслати аудіозаписи</item>
+      <item quantity="other">Надіслати аудіозаписи</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Надіслати відео</item>
+      <item quantity="few">Надіслати відео</item>
+      <item quantity="many">Надіслати відео</item>
+      <item quantity="other">Надіслати відео</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Надіслати картки контактів</item>
+      <item quantity="few">Надіслати картки контактів</item>
+      <item quantity="many">Надіслати картки контактів</item>
+      <item quantity="other">Надіслати картки контактів</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Надіслати вкладені файли</item>
+      <item quantity="few">Надіслати вкладені файли</item>
+      <item quantity="many">Надіслати вкладені файли</item>
+      <item quantity="other">Надіслати вкладені файли</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one">Можна надсилати <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> вкладений файл</item>
+      <item quantity="few">Можна надсилати <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> вкладені файли</item>
+      <item quantity="many">Можна надсилати <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> вкладених файлів</item>
+      <item quantity="other">Можна надсилати <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> вкладеного файлу</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Надіслати відгук"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Переглянути в магазині Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Інформація про версію"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Версія %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Ліцензії відкритого коду"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Сповіщення"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Ви вклали максимальну кількість файлів"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Не вдалося завантажити вкладений файл."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Додати в контакти?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Додати контакт"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Тема"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Тема: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g>. <xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Завантаження картки контакта"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Не вдалося завантажити картку контакта"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Переглянути картку контакта"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> контакт</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> контакти</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> контактів</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> контакта</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Картки контактів"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"День народження"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Нотатки"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Переслати повідомлення"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Відповісти"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS вимкнено"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Щоб надсилати SMS, зробіть Повідомлення додатком для SMS за умовчанням"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Зробіть Повідомлення додатком для SMS за умовчанням"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Змінити"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Щоб отримувати повідомлення, зробіть Повідомлення додатком для SMS за умовчанням"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Не вибрано основної SIM-карти для надсилання SMS-повідомлень"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Власник пристрою не надав дозволів для цього додатка."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ОК"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Забагато учасників у бесіді"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Недійсні контакти</item>
+      <item quantity="few">Недійсні контакти</item>
+      <item quantity="many">Недійсні контакти</item>
+      <item quantity="other">Недійсні контакти</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Не вдалося завантажити зображення з камери"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Ви: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Чернетка"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Коли ви почнете переписку, вона з’явиться тут"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Тут відображаються заархівовані бесіди"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Завантаження бесід…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Зображення"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Аудіокліп"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Відео"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Картка контакта"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Скасувати"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Повторити"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Щоб створити нове повідомлення, введіть ім’я контакта або номер телефону"</string>
+    <string name="action_block" msgid="9032076625645190136">"Заблокувати"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Блокувати користувача <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Розблокувати користувача <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Заблокувати номер <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Ви надалі отримуватимете повідомлення з цього номера, але не отримуватимете сповіщення. Цю бесіду буде заархівовано."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Заблоковані контакти"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"РОЗБЛОКУВАТИ"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Заблоковані контакти"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Вибрати зображення з бібліотеки документів"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Повідомлення надсилається"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Повідомлення надіслано"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Мобільне передавання даних вимкнено. Перевірте налаштування."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Не вдається надіслати повідомлення в режимі польоту"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Не вдалося надіслати повідомлення"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Повідомлення завантажено"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Мобільний Інтернет вимкнено. Перевірте налаштування."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Неможливо завантажити повідомлення в режимі польоту"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Не вдалося завантажити повідомлення"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Нуль"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Один"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Два"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Три"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Чотири"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"П’ять"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Шість"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Сім"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Вісім"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Дев’ять"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Не вдається надіслати повідомлення. Помилка <xliff:g id="ERRORCODE">%2$d</xliff:g>, оператор <xliff:g id="CARRIERNAME">%1$s</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Не вдається надіслати повідомлення. Помилка <xliff:g id="ERRORCODE">%1$d</xliff:g>, невідомий оператор"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Пересилання: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Повідомлення не надіслано: послугу не активовано в мережі"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Повідомлення не надіслано. Недійсна адреса одержувача"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Повідомлення не надіслано. Повідомлення недійсне"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Повідомлення не надіслано. Вміст не підтримується"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Повідомлення не надіслано. Повідомлення не підтримується"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Повідомлення не надіслано: текст задовгий"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Нове повідомлення"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Переглянути"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Зображення"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Не вдалося знайти відповідний додаток"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Видалити отримувача"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Нове повідомлення"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Скасувати"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Редагування точки доступу"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Не вказано"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Назва"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"Назва точки доступу"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Проксі MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Порт MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Тип назви точки доступу"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Видалити назву точки доступу"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Нова назва точки доступу"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Зберегти"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Відхилити"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Поле \"Назва\" не може бути порожнім."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Поле назви точки доступу не може бути порожнім."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Поле MCC має містити 3 цифри."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Поле MNC має містити 2 або 3 цифри."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Відновлення налаштувань назви точки доступу за умовчанням."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Відновити налаштування за умовчанням"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Налаштування назви точки доступу за умовчанням відновлено."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Без назви"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Назви точок доступу"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Назви точок доступу"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Нова назва точки доступу"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Цей користувач не може вказувати назву точки доступу"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Копіювати в буфер обміну?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Копіювати"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"на SIM-карту <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Загальні"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Розширені"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Загальні налаштування"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Додаткові налаштування"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM-карта \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Надсилати окремі SMS усім отримувачам. Відповіді надходитимуть лише вам"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Надсилати одне MMS усім отримувачам"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Невідомий номер"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Нове повідомлення"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Нове повідомлення."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Вибір SIM-карти"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Вибір SIM-карти: вибрано <xliff:g id="SIM_0">%1$s</xliff:g>"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Змінити тему"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Вибрати SIM-карту або змінити тему"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Торкніться й утримуйте, щоб записати аудіо"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Почати нову бесіду"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Повідомлення"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Список у додатку Повідомлення"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Повідомлення"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Нове повідомлення"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Список бесід"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Завантаження бесід"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Завантаження повідомлень"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Переглянути інші бесіди"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Переглянути більше повідомлень"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Бесіду видалено"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Бесіду видалено. Торкніться, щоб переглянути іншу бесіду в додатку Повідомлення"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Заблоковано"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Розблоковано"</string>
+    <string name="db_full" msgid="8459265782521418031">"Замало пам’яті. Деякі дані можуть не зберегтись."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Вибрати вкладені файли"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Підтвердити вибір"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Вибрано <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Видаліть один або декілька вкладених файлів і повторіть спробу."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Спробуйте надіслати повідомлення, але адресат може його не отримати, якщо ви не видалите один або декілька вкладених файлів."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"У повідомленні можна надіслати лише одне відео. Видаліть зайві відео та спробуйте знову."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Не вдалося завантажити вкладенні файли."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Усе одно надіслати"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Не вдалося почати бесіду"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Вибрано <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-ur/arrays.xml b/res/values-ur/arrays.xml
new file mode 100644
index 0000000..fa4e5da
--- /dev/null
+++ b/res/values-ur/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"بلا عنوان"</item>
+    <item msgid="272485471009191934">"بلا عنوان"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"ہاں"</item>
+    <item msgid="6049132459802288033">"نہیں"</item>
+    <item msgid="3084376867445867895">"ٹھیک ہے"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"شکریہ"</item>
+    <item msgid="4881335087096496747">"میں متفق ہوں"</item>
+    <item msgid="2422296858597420738">"اچھا"</item>
+    <item msgid="4805581752819452687">"راستے میں ہوں"</item>
+    <item msgid="4746700499431366214">"ٹھیک ہے، میں بعد میں آپ سے رابطہ کرتا ہوں"</item>
+    <item msgid="4342041517788201970">"‎:)‎"</item>
+    <item msgid="7439437911747961187">"‎:(‎"</item>
+  </string-array>
+</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
new file mode 100644
index 0000000..68217ca
--- /dev/null
+++ b/res/values-ur/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"پیغام رسانی"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"پیغام رسانی"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"گفتگو منتخب کریں"</string>
+    <string name="action_settings" msgid="1329008122345201684">"ترتیبات"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"پیغام بھیجیں"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"ایک منسلکہ شامل کریں"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"مدد"</string>
+    <string name="welcome" msgid="2857560951820802321">"خوش آمدید"</string>
+    <string name="skip" msgid="7238879696319945853">"نظر انداز کریں"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"اگلا &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"آگے"</string>
+    <string name="exit" msgid="1905187380359981199">"باہر نکلیں"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"ترتیبات &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"ترتیبات"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"‏پیغام رسانی کو SMS، فون اور رابطوں کیلئے اجازت درکار ہے۔"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"آپ ترتیبات &gt; ایپس &gt; پیغام رسانی &gt; اجازتوں میں جا کر اجازتیں تبدیل کر سکتے ہیں۔"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"آپ ترتیبات، ایپس، پیغام رسانی، اجازتوں میں جا کر اجازتیں تبدیل کر سکتے ہیں۔"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"اکثر و بیشتر"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"سبھی رابطے"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"<xliff:g id="DESTINATION">%s</xliff:g> پر بھیجیں"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"تصاویر یا ویڈیو کیپچر کریں"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"اس آلہ سے تصاویر منتخب کریں"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"آڈیو ریکارڈ کریں"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"تصویر منتخب کریں"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"میڈیا منتخب کردہ ہے۔"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"میڈیا غیر منتخب کردہ ہے۔"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> کو منتخب کیا گیا"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"تصویر <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"تصویر"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"آڈیو ریکارڈ کریں"</string>
+    <string name="action_share" msgid="2143483844803153871">"اشتراک کریں"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"ابھی ابھی"</string>
+    <string name="posted_now" msgid="867560789350406701">"ابھی"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> منٹ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> منٹ</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> گھنٹے</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> گھنٹہ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> دن</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> دن</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ہفتے</item>
+      <item quantity="one">ایک ہفتہ</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> مہینے</item>
+      <item quantity="one">ایک ماہ</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> سال</item>
+      <item quantity="one">ایک سال</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"کلاس 0 پیغام"</string>
+    <string name="save" msgid="5081141452059463572">"محفوظ کریں"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"آلہ میں جگہ کم ہے۔ پیغام رسانی جگہ خالی کرنے کیلئے خودکار طریقے سے پرانے پیغامات حذف کر دے گی۔"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"اسٹوریج کی جگہ ختم ہو رہی ہے"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"جب تک آپ کے آلہ پر مزید جگہ دستیاب نہ ہو، ممکن ہے اس وقت تک پیغام رسانی نہ پیغامات بھیجے یا نہ موصول کرے۔"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"‏SMS کا کم اسٹوریج۔ آپ کو کچھ پیغامات کو حذف کرنے کی ضرورت پڑ سکتی ہے۔"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"اپنے فون نمبر کی توثیق کریں"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"یہ یک وقتی مرحلہ اس بات کو یقینی بنائے گا کہ پیغام رسانی آپ کے گروپ پیغامات کو مناسب طریقے سے ڈیلیور کرے گی۔"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"فون نمبر"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"میڈیا والے سبھی پیغامات کو حذف کریں"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g> سے پرانے پیغامات کو حذف کر دیں"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g> سے پہلے کے پیغامات کو خودکار طور پر حذف کریں"</string>
+    <string name="ignore" msgid="7063392681130898793">"نظر انداز کریں"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"میڈیا کے ساتھ سبھی پیغامات کو حذف کریں؟"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> سے پہلے کے پیغامات کو حذف کریں؟"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g> سے پہلے کے پیغامات کو حذف کریں اور خودکار طور پر حذف کرنے کو آن کریں؟"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> نے کہا"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"آپ نے کہا"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"پیغام منجانب <xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"آپ نے ایک پیغام بھیجا"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"بھیجا جا رہا ہے…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"بھیجا نہیں گیا۔ دوبارہ کوشش کرنے کیلئے ٹچ کریں۔"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"بھیجا نہیں گیا۔ دوبارہ کوشش کی جا رہی ہے…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"دوبارہ بھیجیں یا حذف کریں"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"براہ کرم ہنگامی سروسز کیلئے ایک صوتی کال کریں۔ آپ کا متنی پیغام اس وقت ڈیلیور نہیں کیا جا سکا۔"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"ناکام"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"‏ڈاؤن لوڈ کرنے کیلئے نیا MMS پیغام"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"‏نیا MMS پیغام"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"ڈاؤن لوڈ نہیں کیا جا سکا"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"دوبارہ کوشش کرنے کیلئے ٹچ کریں"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"ڈاؤن لوڈ کرنے کیلئے ٹچ کریں"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"ڈاؤن لوڈ کریں یا حذف کریں"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"ڈاؤن لوڈ ہو رہا ہے…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"پیغام کی میعاد ختم ہو گئی یا دستیاب نہیں ہے"</string>
+    <string name="mms_info" msgid="3402311750134118165">"سائز: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>، اختتامی میعاد: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"بھیجا نہیں جا سکتا۔ وصول کنندہ درست نہیں ہے۔"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"نیٹ ورک پر سروس فعال نہیں ہے"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"نیٹ ورک کے مسئلہ کی وجہ سے نہیں بھیجا جا سکا"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"پیغام کی میعاد ختم ہو گئی یا دستیاب نہیں ہے"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(بلا عنوان)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"نامعلوم ارسال کنندہ"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"ڈیلیور ہو گیا"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"پیغام <xliff:g id="SUBJECT">%1$s</xliff:g> کو <xliff:g id="FROM">%2$s</xliff:g> سے ڈاؤن لوڈ نہیں کیا جا سکا۔"</string>
+    <string name="low_memory" msgid="5300743415198486619">"کم میموری کی وجہ سے ڈیٹا بیس کی کارروائی مکمل نہیں ہو سکی"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"پیغام نہیں بھیجا گیا"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"پیغام رسانی میں کچھ پیغامات کو نہیں بھیجا گیا"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> گفتگوؤں میں <xliff:g id="MESSAGES_1">%d</xliff:g> پیغامات</item>
+      <item quantity="one">ایک گفتگو میں <xliff:g id="MESSAGES_0">%d</xliff:g> پیغامات</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"پیغام ڈاؤن لوڈ نہیں ہوا"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"پیغام رسانی میں کچھ پیغامات ڈاؤن لوڈ نہیں ہوئے"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"> <xliff:g id="CONVERSATIONS">%d</xliff:g> گفتگوؤں میں <xliff:g id="MESSAGES_1">%d</xliff:g> پیغامات</item>
+      <item quantity="one"> ایک گفتگو میں <xliff:g id="MESSAGES_0">%d</xliff:g> یغامات</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> پر پیغام نہیں بھیجا گیا"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"براہ کرم ہنگامی سروسز کیلئے ایک صوتی کال کریں۔ <xliff:g id="NUMBER">%1$s</xliff:g> پر آپ کا متنی پیغام اس وقت ڈیلیور نہیں کیا جا سکا۔"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> نئے پیغامات</item>
+      <item quantity="one">نیا پیغام</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"شروع کریں"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"کیمرہ دستیاب نہیں ہے"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"کیمرہ دستیاب نہیں ہے"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"ویڈیو کیپچر دستیاب نہیں ہے"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"میڈیا کو محفوظ نہیں کیا جا سکتا ہے"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"تصویر نہیں لی جا سکتی"</string>
+    <string name="back" msgid="1477626055115561645">"واپس جائیں"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"آرکائیو کردہ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"حذف کریں"</string>
+    <string name="action_archive" msgid="5437034800324083170">"آرکائیو کریں"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"آرکائیو سے نکالیں"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"اطلاعات آف کریں"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"اطلاعات آن کریں"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"رابطہ شامل کریں"</string>
+    <string name="action_download" msgid="7786338136368564146">"ڈاؤن لوڈ کریں"</string>
+    <string name="action_send" msgid="377635240181672039">"بھیجیں"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"حذف کریں"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"یہ پیغام حذف کریں؟"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"اس عمل کو کالعدم نہیں کیا جاسکتا۔"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"حذف کریں"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">ان گفتگوؤں کو حذف کریں؟</item>
+      <item quantity="one">اس گفتگو کو حذف کریں؟</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"حذف کریں"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"منسوخ کریں"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"بنام"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"متعدد تصاویر منتخب کریں"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"انتخاب کی توثیق کریں"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"‎+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"آڈیو کو ریکارڈ نہیں کیا جا سکتا ہے۔ دوبارہ کوشش کریں۔"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"آڈیو کو چلایا نہیں جا سکتا ہے۔ دوبارہ کوشش کریں۔"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"آڈیو کو محفوظ نہیں کیا جا سکا۔ دوبارہ کوشش کریں۔"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"ٹچ کریں اور دبائے رکھیں"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"، "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"تصویر"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"آڈیو کلپ"</string>
+    <string name="notification_video" msgid="4331423498662606204">"ویڈیو"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"رابطہ کارڈ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"ڈاؤن لوڈ کریں"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"‏SMS کے ذریعے جواب دیں"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"‏MMS کے ذریعے جواب دیں"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"جواب دیں"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> شرکت کنندگان</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> شرکت کنندہ</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"میں"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"رابطہ کو مسدود اور آرکائیو کر دیا گیا"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"رابطہ کو غیر مسدود کر دیا گیا اور آرکائیو سے نکال دیا گیا"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> کو آرکائیو کر دیا گیا"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> کو آرکائیو سے نکال دیا گیا"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"اطلاعات آف کر دی گئیں"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"اطلاعات آن کر دی گئیں"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"سب ٹھیک ہے۔ بھیجیں کو دوبارہ ٹچ کریں۔"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"‏پیغام رسانی کامیابی سے بطور ڈیفالٹ SMS ایپ سیٹ ہو گئی۔"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">منسلکہ جات کو مسترد کریں</item>
+      <item quantity="one">منسلکہ کو مسترد کریں</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"آڈیو منسلکہ"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"آڈیو منسلکہ چلائیں"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"موقوف کریں"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"پیغام منجانب <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"ناکام پیغام منجانب <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"پیغام منجانب <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"غیر ارسال کردہ پیغام بنام <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"پیغام بھیجا جا رہا ہے بنام <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"ناکام پیغام بنام <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"پیغام بنام <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"ناکام پیغام منجانب <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔ <xliff:g id="GROUPINFO">%4$s</xliff:g>۔"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"پیغام منجانب <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔ <xliff:g id="GROUPINFO">%4$s</xliff:g>۔"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"غیر ارسال کردہ پیغام بنام <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"پیغام بھیجا جا رہا ہے بنام <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"ناکام پیغام بنام <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"پیغام بنام <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>۔ وقت: <xliff:g id="TIME">%3$s</xliff:g>۔"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"ناکام پیغام۔ دوبارہ کوشش کرنے کیلئے ٹچ کریں۔"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> کے ساتھ گفتگو"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"موضوع حذف کریں"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"ویڈیو کیپچر کریں"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"ایک ساکت تصویر کیپچر کریں"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"تصویر لیں"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"ویڈیو ریکارڈ کرنا شروع کریں"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"پوری اسکرین کے کیمرہ پر سوئچ کریں"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"سامنے اور پیچھے کے کیمرے کے درمیان سوئچ کریں"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"ریکارڈنگ بند کریں اور ویڈیو منسلک کریں"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"ویڈیو ریکارڈ کرنے کو روکیں"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"پیغام رسانی تصاویر"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> تصاویر \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" البم میں محفوظ ہو گئیں</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> تصویر \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" البم میں محفوظ ہو گئی</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ویڈیوز \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" البم میں محفوظ ہو گئیں</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ویڈیو \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" البم میں محفوظ ہو گئی</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> منسلکہ جات \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\" البم میں محفوظ ہو گئیں</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> منسلکہ \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\" البم میں محفوظ ہو گئی</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> منسلکہ جات \'ڈاؤن لوڈز\' میں محفوظ ہو گئیں</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> منسلکہ \'ڈاؤن لوڈز\' میں محفوظ ہو گئی</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> منسلکہ جات کو محفوظ کر دیا گیا</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> منسلکہ کو محفوظ کر دیا گیا</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"> <xliff:g id="QUANTITY_1">%d</xliff:g> منسلکہ جات کو محفوظ نہیں کیا جا سکا</item>
+      <item quantity="one"> <xliff:g id="QUANTITY_0">%d</xliff:g> منسلکہ کو محفوظ نہیں کیا جا سکا</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"‏MMS منسلکہ کو محفوظ کر دیا گیا"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"ترتیبات"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"آرکائیو کردہ"</string>
+    <string name="action_close" msgid="1840519376200478419">"بند کریں"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"جدید ترین"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"ڈیبگ کریں"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"اطلاعات"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"آواز"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"خاموش"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"وائبریٹ"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"مسدود"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"‏SMS ڈیلیوری کی رپورٹس"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"‏اپنے ذریعہ بھیجے جانے والے ہر SMS کی ایک ڈیلیوری رپورٹ کی درخواست کریں"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"خودکار طور پر بازیافت کریں"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"‏خود کار طور پر MMS پیغامات کی بازیابی کریں"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"رومنگ کے وقت خود کار بازیابی"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"‏رومنگ میں رہتے ہوئے MMS کی خود کار طور پر بازيابی کریں"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"گروپ پیغام رسانی"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"‏متعدد وصول کنندگان ہونے کی صورت میں ایک پیغام بھیجنے کیلئے MMS استعمال کریں"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"‏ڈیفالٹ SMS ایپ"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"‏ڈیفالٹ SMS ایپ"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"آپ کا فون نمبر"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"نامعلوم"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"آؤٹ گوئنگ پیغامات کی آوازیں"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"‏SMS کو ڈمپ کریں"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"‏وصول کردہ SMS خام ڈیٹا کو خارجی اسٹوریج فائل میں ڈمپ کریں"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"‏MMS کو ڈمپ کریں"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"‏وصول کردہ MMS خام ڈیٹا کو خارجی اسٹوریج فائل میں ڈمپ کریں"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"وائرلیس الرٹس"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"پیغام کے اختیارات"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"متن کاپی کریں"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"تفصیلات دیکھیں"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"حذف کریں"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"فارورڈ کریں"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"پیغام کی تفصیلات"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"قسم: "</string>
+    <string name="text_message" msgid="7415419755252205721">"متنی پیغام"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"ملٹی میڈیا پیغام"</string>
+    <string name="from_label" msgid="1947831848146564875">"منجانب: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"بنام: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"ارسال کردہ: "</string>
+    <string name="received_label" msgid="4442494712757995203">"موصول کردہ: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"موضوع: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"سائز: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"ترجیح: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM:‎ "</string>
+    <string name="priority_high" msgid="728836357310908368">"اعلی"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"عام"</string>
+    <string name="priority_low" msgid="7398724779026801851">"کم"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>‎"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"ارسال کنندہ کا پتہ مخفی کر دیا گیا"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"منسلکات کو لوڈ کرتے وقت پیغام نہیں بھیجا جا سکتا۔"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"منسلکہ کو لوڈ نہیں کیا جا سکتا۔ دوبارہ کوشش کریں۔"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"نیٹ ورک تیار نہیں ہے۔ دوبارہ کوشش کریں۔"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"متن کو حذف کریں"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"متن اور اعداد درج کرنے کے بیچ سوئچ کریں"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"مزید شرکاء کو شامل کریں"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"شرکاء کی توثیق کریں"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"نئی گفتگو شروع کریں"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"اس آئٹم کو منتخب کریں"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"ویڈیو چلائیں"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"لوگ اور اختیارات"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"ڈیبگ کریں"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"لوگ اور اختیارات"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"عام"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"اس گفتگو میں موجود لوگ"</string>
+    <string name="action_call" msgid="6596167921517350362">"ایک کال کریں"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"پیغام بھیجیں"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"‏پیغام بھیجیں‎&lt;br/&gt;&lt;small&gt;‎از <xliff:g id="SIM_NAME">%s</xliff:g>‎&lt;/small&gt;‎"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">تصاویر بھیجیں</item>
+      <item quantity="one">تصویر بھیجیں</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">آڈیوز بھیجیں</item>
+      <item quantity="one">آڈیو بھیجیں</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">ویڈیوز بھیجیں</item>
+      <item quantity="one">ویڈیو بھیجیں</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">رابطہ کارڈز بھیجیں</item>
+      <item quantity="one">رابطہ کارڈ بھیجیں</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">منسلکہ جات بھیجیں</item>
+      <item quantity="one">منسلکہ بھیجیں</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> منسلکہ جات بھیجنے کیلئے تیار</item>
+      <item quantity="one">ایک منسلکہ بھیجنے کیلئے تیار</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"تاثرات بھیجیں"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"‏Google Play اسٹور میں دیکھیں"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"ورژن کی معلومات"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"‏ورژن ‎%1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"اوپن سورس لائسنسز"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"اطلاعات"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"منسلکہ کی حد تک پہنچ گئے"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"منسلکہ لوڈ کرنے میں ناکام۔"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"رابطوں میں شامل کریں؟"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"رابطہ شامل کریں"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"موضوع"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"موضوع: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"‎<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>‎"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"رابطہ کارڈ لوڈ کر رہا ہے"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"رابطہ کارڈ کو لوڈ نہیں کیا جا سکا"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"رابطہ کارڈ دیکھیں"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> رابطے</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> رابطہ</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"رابطہ کارڈز"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"سالگرہ"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"نوٹس"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"پیغام فارورڈ کریں"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"جواب دیں"</string>
+    <string name="plus_one" msgid="9010288417554932581">"‎+1‎"</string>
+    <string name="plus_n" msgid="8961547034116059566">"‎+%d‎"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"‏SMS غیر فعال ہے"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"‏بھیجنے کیلئے پیغام رسانی کو بطور ڈیفالٹ SMS ایپ سیٹ کریں"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"‏پیغام رسانی کو بطور ڈیفالٹ SMS ایپ سیٹ کریں"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"تبدیل کریں"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"‏پیغامات موصول کرنے کیلئے پیغام رسانی کو بطور ڈیفالٹ SMS ایپ سیٹ کریں"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"‏SMS پیغامات بھیجنے کیلئے کوئی ترجیحی SIM منتخب نہیں کیا گیا"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"آلہ کے مالک نے اس ایپ کی اجازت نہیں دی ہے۔"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"ٹھیک ہے"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"ایک گفتگو میں بہت زیادہ شرکاء"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">غلط رابطے</item>
+      <item quantity="one">غلط رابطہ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"کیمرے کی تصویر کو لوڈ نہیں کیا جا سکا"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"آپ: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"‎<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>:‎ "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"مسودہ"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"کوئی نئی گفتگو شروع کرنے پر، آپ اسے یہاں مندرج دیکھیں گے"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"آرکائیو کردہ گفتگوئیں یہاں ظاہر ہوتی ہیں"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"گفتگوئیں لوڈ ہو رہی ہیں…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"تصویر"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"آڈیو کلپ"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"ویڈیو"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"رابطہ کارڈ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"کالعدم کریں"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"دوبارہ کوشش کریں"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"ایک نیا پیغام شروع کرنے کیلئے رابطہ کا ایک نام یا فون نمبر درج کریں"</string>
+    <string name="action_block" msgid="9032076625645190136">"مسدود کریں"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"<xliff:g id="DESTINATION">%s</xliff:g> کو مسدود کریں"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"<xliff:g id="DESTINATION">%s</xliff:g> کو غیر مسدود کریں"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> کو مسدود کریں؟"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"آپ کو اس نمبر سے پیغامات موصول ہوتے رہیں گے لیکن مزید مطلع نہیں کیا جائے گا۔ اس گفتگو کو آرکائیو کر دیا جائے گا۔"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"مسدود رابطے"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"غیر مسدود کریں"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"مسدود رابطے"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"دستاویز لائبریری سے تصویر منتخب کریں"</string>
+    <string name="sending_message" msgid="6363584950085384929">"پیغام بھیجا جا رہا ہے"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"پیغام بھیج دیا گیا"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"سیلولر ڈیٹا آف ہے۔ اپنی ترتیبات چیک کریں۔"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"پیغامات کو ہوائی جہاز وضع میں نہیں بھیجا جا سکتا ہے"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"پیغام بھیجا نہیں جا سکا"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"پیغام ڈاؤن لوڈ ہو گیا"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"سیلولر ڈیٹا آف ہے۔ اپنی ترتیبات چیک کریں۔"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"ہوائی جہاز وضع میں پیغامات ڈاؤن لوڈ نہیں کیے جا سکتے ہیں"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"پیغام ڈاؤن لوڈ نہیں کیا جا سکا"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"صفر"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"ایک"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"دو"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"تین"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"چار"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"پانچ"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"چھ"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"سات"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"آٹھ"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"نو"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> کے ساتھ پیغام نہیں بھیجا جا سکتا، خرابی <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"نامعلوم کیرئیر کے ساتھ پیغام نہیں بھیجا جا سکتا، خرابی <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"آگے منتقل کریں: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"پیغام نہیں بھیجا گیا: سروس نیٹ ورک پر فعال نہیں ہے"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"پیغام نہیں بھیجا گیا: منزل مقصول کا غلط پتہ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"پیغام نہیں بھیجا گیا: غلط پیغام"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"پیغام نہیں بھیجا گیا: غیر تعاون یافتہ مواد"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"پیغام کو نہیں بھیجا گیا: غیر تعاون یافتہ پیغام"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"پیغام نہیں بھیجا گیا: کافی بڑا ہے"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"نیا پیغام"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"دیکھیں"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"تصویر"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"ایک مناسب ایپلیکیشن تلاش نہیں کی جا سکی"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"وصول کنندہ کو ہٹائیں"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"نیا پیغام"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"منسوخ کریں"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"رسائی کی جگہ میں ترمیم کریں"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"سیٹ نہیں ہے"</string>
+    <string name="apn_name" msgid="1572691851070894985">"نام"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"‏MMS پراکسی"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"‏MMS پورٹ"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"‏APN قسم"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"‏APN کو حذف کریں"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"‏نیا APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"محفوظ کریں"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"مسترد کریں"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"نام کی فیلڈ خالی نہیں رہ سکتی-"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"‏APN خالی نہيں رہ سکتا۔"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"‏MCC فیلڈ میں 3 ہندسے ہونا ضروری ہے۔"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"‏MNC فیلڈ میں 2 یا 3 ہندسے ہونا ضروری ہے-"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"‏ڈیفالٹ APN ترتیبات بحال ہو رہی ہیں-"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"ڈیفالٹ پر دوبارہ ترتیب دیں"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"‏ڈیفالٹ APN ترتیبات کو دوبارہ ترتیب دینے کا عمل مکمل ہو گیا-"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"بلا عنوان"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"رسائی کی جگہ کے نام"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APNs"</string>
+    <string name="menu_new" msgid="8286285392706532511">"‏نیا APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"رسائی کی جگہ کے نام کی ترتیبات اس صارف کیلئے دستیاب نہیں ہیں"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"کلپ بورڈ پر کاپی کریں؟"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"کاپی کریں"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"<xliff:g id="SIM_NAME">%s</xliff:g> پر"</string>
+    <string name="general_settings" msgid="5409336577057897710">"عام"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"جدید ترین"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"عام ترتیبات"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"جدید ترین ترتیبات"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"‎\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM‎"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"‏سبھی وصول کنندگان کو انفرادی SMS پیغامات بھیجیں۔ صرف آپ کو کوئی جوابات موصول ہوں گے"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"‏سبھی وصول کنندگان کو ایک MMS بھیجیں"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"نامعلوم نمبر"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"نیا پیغام"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"نیا پیغام۔"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"‏SIM کا انتخاب کنندہ"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"‏منتخب شدہ <xliff:g id="SIM_0">%1$s</xliff:g>، SIM کا انتخاب کنندہ"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"موضوع میں ترمیم کریں"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"‏SIM منتخب کریں یا موضوع میں ترمیم کریں"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"آڈیو ریکارڈ کرنے کیلئے ٹچ کریں اور پکڑ کر رکھیں"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"نئی گفتگو شروع کریں"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"پیغام رسانی"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"پیغام رسانی کی فہرست"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"پیغام رسانی"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"نیا پیغام"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"گفتگو کی فہرست"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"گفتگوئیں لوڈ ہو رہی ہیں"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"پیغامات لوڈ ہو رہے ہیں"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"مزید گفتگوئیں دیکھیں"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"مزید پیغامات دیکھیں"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"گفتگو کو حذف کر دیا گیا"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"گفتگو حذف ہوگئی۔ پیغام رسانی کی ایک دوسری گفتگو دکھانے کیلئے ٹچ کریں"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"مسدود"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"غیر مسدود"</string>
+    <string name="db_full" msgid="8459265782521418031">"اسٹوریج کی جگہ کم ہے۔ کچھ ڈیٹا ضائع ہو سکتا ہے۔"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"منسلکات منتخب کریں"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"انتخاب کی توثیق کریں"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> کو منتخب کیا گیا"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"براہ کرم ایک یا مزید منسلکات ہٹائیں اور دوبارہ کوشش کریں۔"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"آپ اپنا پیغام بھیجنے کی کوشش کر سکتے ہیں، لیکن ہو سکتا ہے وہ تب تک ڈیلیور نہ ہو جب تک کہ آپ ایک یا مزيد منسلکات نہیں ہٹا دیتے۔"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"آپ فی پیغام صرف ایک ویڈیو بھیج سکتے ہیں۔ براہ کرم اضافی ویڈیوز ہٹائیں اور دوبارہ کوشش کریں۔"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"پیغام رسانی منسلکہ کو لوڈ کرنے میں ناکام رہی۔"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"بہر صورت بھیجیں"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"گفتگو شروع نہیں کی جا سکی"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> منتخب کردہ"</string>
+</resources>
diff --git a/res/values-uz/arrays.xml b/res/values-uz/arrays.xml
new file mode 100644
index 0000000..79b4c47
--- /dev/null
+++ b/res/values-uz/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"mavzu yo‘q"</item>
+    <item msgid="272485471009191934">"mavzu yo‘q"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Ha"</item>
+    <item msgid="6049132459802288033">"Yo‘q"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Ha-ha"</item>
+    <item msgid="2611328818571146775">"Rahmat"</item>
+    <item msgid="4881335087096496747">"Yaxshi"</item>
+    <item msgid="2422296858597420738">"Ajoyib"</item>
+    <item msgid="4805581752819452687">"Yo‘ldaman"</item>
+    <item msgid="4746700499431366214">"OK, keyinroq telefon qilaman"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
new file mode 100644
index 0000000..4d84ca1
--- /dev/null
+++ b/res/values-uz/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Xabarlar"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Xabarlar"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Suhbatni tanlang"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Sozlamalar"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Xabar yuborish"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Fayl biriktiring"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Yordam"</string>
+    <string name="welcome" msgid="2857560951820802321">"Xush kelibsiz"</string>
+    <string name="skip" msgid="7238879696319945853">"O’tkazib yuborish"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Keyingi &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Keyingi"</string>
+    <string name="exit" msgid="1905187380359981199">"Chiqish"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Sozlamalar &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Sozlamalar"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"SMS/MMS xizmatiga SMS, Telefon va Kontaktlardan foydalanish uchun ruxsat zarur."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Ruxsatnomalarni bu yerdan o‘zgartiring: Sozlamalar &gt; Ilovalar &gt; SMS/MMS &gt; Ruxsatnomalar"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Ruxsatnomalarni bu yerdan o‘zgartiring: Sozlamalar &gt; Ilovalar &gt; SMS/MMS &gt; Ruxsatnomalar"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Tez-tez"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Barcha kontaktlar"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Yuborish: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Rasm yoki video tasvirga olish"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Ushbu qurilmadan rasmlarni tanlang"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Audio yozish"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Rasmni tanlang"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Media tanlandi."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Mediani tanlash bekor qilindi."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> ta tanlandi"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"tasvir <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"tasvir"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Audio yozish"</string>
+    <string name="action_share" msgid="2143483844803153871">"Ulashish"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Hozir"</string>
+    <string name="posted_now" msgid="867560789350406701">"Hozir"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> daqiqa</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> daqiqa</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> soat</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> soat</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> kun</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> kun</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hafta</item>
+      <item quantity="one">bir hafta</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> oy</item>
+      <item quantity="one">bir oy</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> yil</item>
+      <item quantity="one">bir yil</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0-toifa xabari"</string>
+    <string name="save" msgid="5081141452059463572">"Saqlash"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Qurilma xotirasidagi bo‘sh joy kam qolmoqda. Joy bo‘shatish uchun eskiroq xabarlar avtomatik o‘chirib tashlanadi."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Xotirada bo‘sh joy tugamoqda"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Qurilmangizda bo‘sh joy kam qolsa, SMS/MMS xizmati xabarlarni yubora yoki qabul qila olmay qolishi mumkin."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"SMS uchun xotirada joy kam. Sizdan ba’zi xabarlarni o‘chirish talab qilinishi mumkin."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Telefon raqamingizni tasdiqlang"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Bu bir martalik bosqich bajarilsa, SMS/MMS xizmati guruh xabarlarini to‘g‘ri yuboradigan bo‘ladi."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Telefon raqami"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Barcha multimediali xabarlarni o‘chirish"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"<xliff:g id="DURATION">%s</xliff:g>dan eski xabarlar o‘chirilsin"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"<xliff:g id="DURATION">%s</xliff:g>dan oldingi xabarlar avtomatik o‘chirilsin"</string>
+    <string name="ignore" msgid="7063392681130898793">"E’tiborsiz qoldirish"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Media faylli barcha xabarlar o‘chirib tashlansinmi?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"<xliff:g id="DURATION">%s</xliff:g> dan oldingi barcha xabarlar o‘chirib tashlansinmi?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"<xliff:g id="DURATION">%s</xliff:g>dan oldingi xabarlar o‘chirilib, avtomatik o‘chirish funksiyasi yoqilsinmi?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> dedi"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Siz dedingiz"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"<xliff:g id="SENDER">%s</xliff:g> yuborgan xabar"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Siz xabar yubordingiz"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Yuborilmoqda…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Yuborilmadi. Qayta urinish uchun bosing."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Yuborilmadi. Qayta urinilmoqda…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Qayta yuboring yoki o‘chirib tashlang"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Favqulodda xizmatlarga ovozli qo‘ng‘iroq qiling. Favqulodda xizmat raqamlariga yuborilgan SMS xabarlarni hozirda yetkazib bo‘lmaydi."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Xabar yuborilmadi"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Yuklab olish uchun yangi MMS xabari"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Yangi MMS xabari"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Yuklab olinmadi"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Qayta urinish uchun bosing"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Yuklab olish uchun bosing"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Yuklab oling yoki o‘chirib tashlang"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Yuklab olinmoqda…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Xabar eskirgan yoki mavjud emas"</string>
+    <string name="mms_info" msgid="3402311750134118165">"hajmi: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, tugash muddati: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Yuborib bo‘lmadi. Qabul qiluvchi noto‘g‘ri ko‘rsatilgan."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Xizmat tarmoqda faollashtirilmagan"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Tarmoqdagi muammo tufayli yuborib bo‘lmadi"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Xabar eskirgan yoki mavjud emas"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Mavzu yo‘q)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Noma’lum yuboruvchi"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Yetkazildi"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"“<xliff:g id="SUBJECT">%1$s</xliff:g>” to‘g‘risidagi xabarni (yuboruvchi: <xliff:g id="FROM">%2$s</xliff:g>) yuklab bo‘lmadi."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Xotirada kam joy qolganligi sababli ma’lumotlar bazasi amalini bajarib bo‘lmaydi"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Xabar yuborilmadi"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"SMS/MMS xizmatidagi ayrim xabarlar yuborilmadi"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other">Suhbatlar: <xliff:g id="CONVERSATIONS">%d</xliff:g>, xabarlar: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="one">Suhbatdagi xabarlar soni: <xliff:g id="MESSAGES_0">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Xabar yuklab olinmadi"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"SMS/MMS xizmatidagi ayrim xabarlar yuklab olinmadi"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other">Suhbatlar: <xliff:g id="CONVERSATIONS">%d</xliff:g>, xabarlar: <xliff:g id="MESSAGES_1">%d</xliff:g></item>
+      <item quantity="one">Suhbatdagi xabarlar soni: <xliff:g id="MESSAGES_0">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"<xliff:g id="NUMBER">%1$s</xliff:g> raqamiga xabar yuborilmadi"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Favqulodda xizmatlarga ovozli qo‘ng‘iroq qiling. <xliff:g id="NUMBER">%1$s</xliff:g> raqamiga yuborgan SMS xabaringizni hozir yetkazib bo‘lmaydi."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> ta yangi xabar</item>
+      <item quantity="one">Yangi xabar</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Boshlash"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Kamera tayyor emas"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Kamera tayyor emas"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Videoga olib bo‘lmaydi"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Media faylni saqlab bo‘lmadi"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Rasmga olib bo‘lmadi"</string>
+    <string name="back" msgid="1477626055115561645">"Orqaga"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Arxivlangan"</string>
+    <string name="action_delete" msgid="4076795795307486019">"O‘chirish"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Arxivlash"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Arxivdan chiqarish"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Bildirishnomalarni o‘chirib qo‘yish"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Bildirishnomalarni yoqish"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Kontakt qo‘shish"</string>
+    <string name="action_download" msgid="7786338136368564146">"Yuklab olish"</string>
+    <string name="action_send" msgid="377635240181672039">"Yuborish"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"O‘chirish"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Ushbu xabar o‘chirilsinmi?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Ushbu amalni bekor qilib bo‘lmaydi."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"O‘chirish"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Bu suhbatlar o’chirib tashlansinmi?</item>
+      <item quantity="one">Bu suhbat o’chirib tashlansinmi?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"O‘chirish"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Bekor qilish"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Kimga:"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Bir nechta rasm tanlash"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Tanlovni tasdiqlash"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g> ta"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Audioni yozib bo‘lmadi. Qaytadan urining."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Audioni ijro qilib bo‘lmadi. Qaytadan urining."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Audioni saqlab bo‘lmadi. Qaytadan urining."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Bosib turing"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Rasm"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Audio-klip"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Kontaktlar kartasi"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Yuklab olish"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"SMS orqali javob berish"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"MMS orqali javob"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Javob berish"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ta ishtirokchi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ta ishtirokchi</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Men"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Kontakt bloklandi va arxivlandi"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Kontakt blokdan va arxivdan chiqarildi"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> ta qayd arxivlandi"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> ta qayd arxivdan chiqarildi"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Bildirishnomalar o‘chirib qo‘yildi"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Bildirishnomalar yoqildi"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Hammasi tayyor. Endi “Yuborish” tugmasini bosing."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"SMS/MMS xizmati birlamchi SMS ilovasi sifatida o‘rnatildi."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Biriktirmalarni olib tashlash</item>
+      <item quantity="one">Biriktirmani olib tashlash</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Ovozli biriktirma"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Audio biriktirmani ijro qilish"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"To‘xtatib turish"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g> yuborgan xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g> yuborgan muvaffaqiyatsiz xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g> yuborgan xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"<xliff:g id="CONTACT">%1$s</xliff:g>ga yuborilmay qolgan xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"<xliff:g id="CONTACT">%1$s</xliff:g>ga xabar yuborilmoqda: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"<xliff:g id="CONTACT">%1$s</xliff:g>ga yuborilgan muvaffaqiyatsiz xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"<xliff:g id="CONTACT">%1$s</xliff:g>ga xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g> yuborgan muvaffaqiyatsiz xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g> yuborgan xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"<xliff:g id="GROUP">%1$s</xliff:g> guruhiga yuborilmay qolgan xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"<xliff:g id="GROUP">%1$s</xliff:g> guruhiga xabar yuborilmoqda: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"<xliff:g id="GROUP">%1$s</xliff:g> guruhiga yuborilgan muvaffaqiyatsiz xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"<xliff:g id="GROUP">%1$s</xliff:g> guruhiga xabar: <xliff:g id="MESSAGE">%2$s</xliff:g>. Vaqt: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Muvaffaqiyatsiz xabar. Qayta urinish uchun bosing."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"<xliff:g id="PARTICIPANTS">%s</xliff:g> bilan suhbat"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Mavzuni o‘chirish"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Video tasvirga olish"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Harakatsiz rasmni suratga olish"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Rasmga olish"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Video tasvirga olishni boshlash"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"To‘liq ekranli kameraga o‘tish"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Old va orqa kamera o‘rtasida almashish"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Tasvirga olishni to‘xtatish va faylni biriktirish"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Videoga olishni to‘xtatish"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"SMS/MMS rasmlari"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ta rasm “<xliff:g id="ALBUMNAME_3">%s</xliff:g>” albomiga saqlandi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta rasm “<xliff:g id="ALBUMNAME_1">%s</xliff:g>” albomiga saqlandi</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ta video “<xliff:g id="ALBUMNAME_3">%s</xliff:g>” albomiga saqlandi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta video “<xliff:g id="ALBUMNAME_1">%s</xliff:g>” albomiga saqlandi</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ta biriktirma “<xliff:g id="ALBUMNAME_3">%s</xliff:g>” albomiga saqlandi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta biriktirma “<xliff:g id="ALBUMNAME_1">%s</xliff:g>” albomiga saqlandi</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ta biriktirma “Yuklanishlar” jildiga saqlandi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta biriktirma “Yuklanishlar” jildiga saqlandi</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ta biriktirma saqlandi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta biriktirma saqlandi</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> ta biriktirmani saqlab bo’lmadi</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ta biriktirmani saqlab bo’lmadi</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"MMS fayli saqlandi"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Sozlamalar"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Arxivlangan"</string>
+    <string name="action_close" msgid="1840519376200478419">"Yopish"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Qo‘shimcha"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Tuzatish"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Bildirishnomalar"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Ovoz"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Ovozsiz"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Tebranish"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Bloklandi"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"SMS xabarlarning yetkazilganlik hisobotlari"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Yuborilgan har bir SMS uchun yetkazilganlik hisobotini talab qilish"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Avtomatik yuklanish"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"MMS xabarlarni avtomatik yuklab olish"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Rouming vaqtida avtomatik yuklab olish"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Rouming vaqtida MMS xabarlarni avtomatik yuklab olish"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Guruh xabarlari"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Bitta xabarni bir nechta qabul qiluvchiga yuborish uchun MMS xabardan foydalanilsin"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Birlamchi SMS ilovasi"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Birlamchi SMS ilovasi"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Telefon raqamingiz"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Noma’lum"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Chiquvchi xabar ovozlari"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"SMS xabarni o‘tkazish"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"SMS orqali olingan qayta ishlanmagan ma’lumotlarni tashqi xotiraga o‘tkazish"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"MMS xabarni o‘tkazish"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"MMS orqali olingan qayta ishlanmagan ma’lumotlarni tashqi xotiraga o‘tkazish"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Aholini ogohlantirish"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Xabar sozlamalari"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Matndan nusxa olish"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Tafsilotlarni ko‘rish"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"O‘chirish"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Qayta yo‘naltirish"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Xabar tafsilotlari"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Turi: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Matnli xabar"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Multimediali xabar"</string>
+    <string name="from_label" msgid="1947831848146564875">"Kimdan: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Kimga: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Yuborildi: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Qabul qilindi: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Mavzu: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Hajmi: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Ustivorlik: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM-karta: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Yuqori"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"O‘rtacha"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Past"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"<xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>-SIM karta"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Yuboruvchining manzili yashirilgan"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Biriktirilgan fayllarni yuklab olayotganda xabar yuborib bo‘lmaydi."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Biriktirma faylini yuklab bo‘lmadi. Qaytadan urining."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Tarmoq hali tayyor emas. Qaytadan urining."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Matnni o‘chirish"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Harf va raqam kiritish o‘rtasida almashish"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Yana ishtirokchi qo‘shish"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Ishtirokchilarni tasdiqlang"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Yangi suhbat boshlash"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Ushbu variantni tanlash"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Videoni ijro qilish"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Odamlar va tanlamalar"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Tuzatish"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Odamlar va tanlamalar"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Umumiy"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Ushbu suhbat ishtirokchilari"</string>
+    <string name="action_call" msgid="6596167921517350362">"Qo‘ng‘iroq qilish"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Xabar yuborish"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;<xliff:g id="SIM_NAME">%s</xliff:g> orqali&lt;/small&gt; xabar yuboring"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Rasmlarni yuborish</item>
+      <item quantity="one">Rasmni yuborish</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Audio faylni yuborish</item>
+      <item quantity="one">Audio faylni yuborish</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Videolarni yuborish</item>
+      <item quantity="one">Videoni yuborish</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Kontaktlar kartasini yuborish</item>
+      <item quantity="one">Kontaktlar kartasini yuborish</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Biriktirmani yuborish</item>
+      <item quantity="one">Biriktirmani yuborish</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> ta biriktirma yuborishga tayyor</item>
+      <item quantity="one">Biriktirma yuborishga tayyor</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Fikr va mulohaza yuborish"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Play Marketdan qidirish"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Versiyasi"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"%1$s versiya"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Ochiq kodli DT litsenziyalari"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Bildirishnomalar"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Biriktirma chekloviga yetdi"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Biriktirmani yuklab bo‘lmadi."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Kontaktlarga qo‘shilsinmi?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Kontakt qo‘shish"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Mavzu"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Mavzu: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Kontaktlar kartasi yuklanmoqda"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Kontaktlar kartasini yuklab bo‘lmadi"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Kontaktlar kartasini ko‘rish"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ta kontakt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ta kontakt</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Kontakt kartalari"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Tug‘ilgan kun"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Qaydlar"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Xabarni qayta yo‘naltirish"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Javob berish"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"SMS o‘chirib qo‘yilgan"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Yuborish uchun SMS/MMS xizmatini birlamchi SMS ilovasi sifatida o‘rnating"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"SMS/MMS xizmatini birlamchi SMS ilovasi sifatida o‘rnating"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"O‘zgartirish"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Xabarlarni qabul qilish uchun SMS/MMS xizmatini birlamchi SMS ilovasi sifatida o‘rnating"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"SMS xabarlarni yuborish uchun ma’qul SIM-karta tanlanmagan"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Qurilma egasi ushbu ilovadan foydalanishga ruxsat bermagan."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Suhbatdagi ishtirokchilar soni juda ko‘p"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Kontaktlar topilmadi</item>
+      <item quantity="one">Kontakt topilmadi</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Kameradagi rasmni yuklab bo‘lmadi"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Siz: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Qoralama"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Yangi suhbat boshlasangiz, u bu yerda ko‘rinadi"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Arxivlangan suhbatlar bu yerda ko‘rinadi"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Suhbatlar yuklanmoqda…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Rasm"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Audio-klip"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Kontaktlar kartasi"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Bekor qilish"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Qayta urinish"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Yangi xabar yozish uchun kontaktning ismi yoki telefon raqamini kiriting"</string>
+    <string name="action_block" msgid="9032076625645190136">"Bloklash"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Bloklash:<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Blokdan chiqarish: <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"<xliff:g id="DESTINATION">%s</xliff:g> bloklansinmi?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Sizga ushbu raqamdan xabarlar kelishi mumkin, biroq bu haqda siz xabardor qilinmaysiz. Ushbu suhbat esa arxivlanadi."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Bloklangan kontaktlar"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"BLOKDAN CHIQARISH"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Bloklangan kontaktlar"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Hujjatlar kutubxonasidan rasm tanlang"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Xabar yuborilmoqda"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Xabar yuborildi"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Mobil internet o‘chirilgan. Sozlamalarni tekshiring."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Parvoz rejimida xabarlarni yuborib bo‘lmaydi"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Xabar yuborilmadi"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Xabar yuklab olindi"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Mobil internet o‘chirilgan. Sozlamalarni tekshiring."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Parvoz rejimida xabarlarni yuklab olib bo‘lmaydi"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Xabarni yuklab olib bo‘lmadi"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Nol"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Bir"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Ikki"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Uch"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"To‘rt"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Besh"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Olti"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Yetti"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Sakkiz"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"To‘qqiz"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"<xliff:g id="CARRIERNAME">%1$s</xliff:g> orqali xabar yuborib bo‘lmadi, xatolik kodi: <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Noma’lum aloqa operatori orqali xabar yuborib bo‘lmadi, xatolik kodi: <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Fwd: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Xabar yuborilmadi: xizmat tarmoqda faollashtirilmagan"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Xabar yuborilmadi: qabul qiluvchining manzili noto‘g‘ri"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Xabar yuborilmadi: xabar noto‘g‘ri"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Xabar yuborilmadi: kontent turi qo‘llab-quvvatlanmaydi"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Xabar yuborilmadi: xabar turi qo‘llab-quvvatlanmaydi"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Xabar yuborilmadi: juda katta"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Yangi xabar"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Ko‘rish"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Rasm"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Mos ilovani topib bo‘lmadi"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Qabul qiluvchini o‘chirish"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Yangi xabar"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Bekor qilish"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Ulanish nuqtasi sozlamalari"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Sozlanmagan"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Nomi"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS proksi-serveri"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS porti"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN turi"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"APNni o‘chirish"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"Yangi APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Saqlash"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Bekor qilish"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"APN nomi maydonchasini to‘ldirish shart."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN maydonchasini to‘ldirish shart."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC 3 ta raqamdan iborat bo‘lishi shart."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC 2 yoki 3 ta raqamdan iborat bo‘lishi shart."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Standart APN sozlamalari qayta tiklanmoqda."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Standart sozlamalarni tiklash"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Standart sozlamalar tiklandi."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Nomsiz"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Ulanish nuqtalari"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"Yangi APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Ushbu foydalanuvchi uchun Ulanish nuqtasi nomi (APN) sozlamalari mavjud emas"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Vaqtinchalik xotiraga nusxa olinsinmi?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Nusxa olish"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ushbu SIM-kartaga: <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Umumiy"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Qo‘shimcha"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Umumiy sozlamalar"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Qo‘shimcha sozlamalar"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"“<xliff:g id="SIM_NAME">%s</xliff:g>” SIM kartasi"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Har bir qabul qiluvchiga alohida SMS xabar yuboring. Faqat siz barcha javoblarni olishingiz mumkin"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Barcha qabul qiluvchilarga bir xil MMS xabar yuboring"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Noma’lum raqam"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Yangi xabar"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Yangi xabar."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM kartani tanlash"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> SIM-kartasi tanlangan"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Mavzuni tahrirlash"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"SIM kartani tanlang yoki mavzuni tahrirlang"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Audio yozib olish uchun bosib turing"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Yangi suhbat boshlash"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"SMS/MMS"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"SMS/MMS chatlari"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"SMS/MMS"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Yangi xabar"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Suhbatlar ro‘yxati"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Suhbatlar yuklanmoqda"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Xabarlar yuklanmoqda"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Ko‘proq suhbatlarni ko‘rish"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Boshqa xabarlarni ko‘rish"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Suhbat o‘chirib tashlandi"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Suhbat o‘chirib tashlandi. SMS/MMS xizmatidagi boshqa suhbatni ko‘rish uchun bosing."</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Bloklandi"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Blokdan chiqarildi"</string>
+    <string name="db_full" msgid="8459265782521418031">"Xotirada joy kam qoldi. Ba’zi ma’lumotlar saqlanmasligi mumkin."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Biriktirmalarni tanlash"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Tanlovni tasdiqlash"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> ta tanlandi"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Bir yoki bir nechta biriktirmani olib tashlab, keyin qayta urinib ko‘ring."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Xabarni yuborib ko‘rishingiz mumkin, lekin undagi bir yoki bir nechta biriktirma olib tashlanmaguncha qabul qiluvchiga yetib bormasligi mumkin."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Siz bitta xabarda faqat bitta video jo‘nata olasiz. Ortiqcha videolarni olib tashlang va qaytadan urinib ko‘ring."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Biriktirmani yuklab bo‘lmadi."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Baribir yuborilsin"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Suhbatni boshlab bo‘lmadi"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"<xliff:g id="SELECTED_SIM">%s</xliff:g> tanlandi"</string>
+</resources>
diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml
new file mode 100644
index 0000000..01cec58
--- /dev/null
+++ b/res/values-v17/styles.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <style name="GalleryGridItemViewCheckBoxStyle">
+        <item name="android:paddingEnd">4dp</item>
+    </style>
+
+    <style name="AttachmentGridItemViewCheckBoxStyle">
+        <item name="android:paddingEnd">4dp</item>
+    </style>
+
+    <style name="PeopleAndOptionsItemStyle">
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+    </style>
+
+    <style name="AudioAttachmentViewStyle">
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+    </style>
+
+    <style name="VcardAttachmentSingleStyle">
+        <item name="android:paddingStart">@dimen/message_text_left_right_padding</item>
+        <item name="android:paddingEnd">@dimen/message_text_left_right_padding</item>
+    </style>
+
+    <style name="PeopleListItemViewStyle">
+        <item name="android:paddingStart">16dp</item>
+    </style>
+
+    <style name="MessageVcardAttachmentStyle">
+        <item name="android:paddingStart">@dimen/message_text_left_right_padding</item>
+        <item name="android:paddingEnd">@dimen/message_text_left_right_padding</item>
+    </style>
+
+    <style name="CameraChooserFrameStyle">
+        <item name="android:paddingStart">16dp</item>
+    </style>
+
+    <style name="AddContactConfirmationTextStyle">
+        <item name="android:paddingStart">12dp</item>
+        <item name="android:paddingEnd">24dp</item>
+    </style>
+
+    <style name="ContactListItemDetailType">
+        <item name="android:paddingStart">12dp</item>
+    </style>
+
+    <style name="DebugMmsConfigItemStyle">
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+    </style>
+
+    <style name="ApnPreferenceLayoutStyle">
+        <item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item>
+        <item name="android:paddingEnd">?android:attr/listPreferredItemPaddingEnd</item>
+    </style>
+
+    <style name="CopyContactDialogTextStyle">
+        <item name="android:paddingStart">@dimen/copy_contact_dialog_left_padding</item>
+        <item name="android:paddingEnd">@dimen/copy_contact_dialog_right_padding</item>
+    </style>
+</resources>
diff --git a/res/values-v21/colors.xml b/res/values-v21/colors.xml
new file mode 100644
index 0000000..d51ad04
--- /dev/null
+++ b/res/values-v21/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <color name="notification_sender_text">#DE000000</color>
+    <color name="notification_secondary_text">#8A000000</color>
+    <color name="notification_tertiary_text">#8A000000</color>
+    <color name="notification_subject_color">#DE000000</color>
+</resources>
diff --git a/res/values-v21/dimens.xml b/res/values-v21/dimens.xml
new file mode 100644
index 0000000..466d2c8
--- /dev/null
+++ b/res/values-v21/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <dimen name="fab_bottom_margin">16dp</dimen>
+    <dimen name="fab_left_right_margin">16dp</dimen>
+    <dimen name="fab_size">56dp</dimen>
+    <dimen name="fab_padding_bottom">0dp</dimen>
+</resources>
diff --git a/res/values-v21/styles.xml b/res/values-v21/styles.xml
new file mode 100644
index 0000000..aef5d1c
--- /dev/null
+++ b/res/values-v21/styles.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <style name="BugleTheme.ConversationActivity"
+        parent="@style/BugleTheme.ConversationActivityBase">
+        <item name="android:colorEdgeEffect">@color/conversation_edge_effect</item>
+    </style>
+
+    <style name="BugleTheme.DialogActivity" parent="@style/Theme.AppCompat.Light.Dialog">
+        <item name="android:windowNoTitle">false</item>
+        <item name="android:background">@android:color/white</item>
+    </style>
+
+    <style name="ContactListItemDrawableIndicator">
+        <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
+    </style>
+
+    <style name="ConversationActionBarTitleTextStyle" parent="BugleActionBarTitleTextStyle">
+      <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
+    </style>
+
+    <style name="WidgetConversationListItemStyle">
+        <item name="android:background">@drawable/widget_item_background</item>
+        <item name="android:layout_height">72dp</item>
+    </style>
+
+</resources>
diff --git a/res/values-vi/arrays.xml b/res/values-vi/arrays.xml
new file mode 100644
index 0000000..b16f18b
--- /dev/null
+++ b/res/values-vi/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"không có chủ đề"</item>
+    <item msgid="272485471009191934">"không có chủ đề"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Có"</item>
+    <item msgid="6049132459802288033">"Không"</item>
+    <item msgid="3084376867445867895">"OK"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Xin cảm ơn"</item>
+    <item msgid="4881335087096496747">"Tôi đồng ý"</item>
+    <item msgid="2422296858597420738">"Tuyệt vời"</item>
+    <item msgid="4805581752819452687">"Đang trên đường"</item>
+    <item msgid="4746700499431366214">"OK, tôi sẽ liên hệ lại với bạn sau"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
new file mode 100644
index 0000000..4923847
--- /dev/null
+++ b/res/values-vi/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Nhắn tin"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Nhắn tin"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Chọn cuộc hội thoại"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Cài đặt"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Gửi tin nhắn"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Thêm tệp đính kèm"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Trợ giúp"</string>
+    <string name="welcome" msgid="2857560951820802321">"Chào mừng"</string>
+    <string name="skip" msgid="7238879696319945853">"Bỏ qua"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Tiếp theo &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Tiếp theo"</string>
+    <string name="exit" msgid="1905187380359981199">"Thoát"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Cài đặt &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Cài đặt"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Nhắn tin cần quyền truy cập vào SMS, Điện thoại và Danh bạ."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Bạn có thể thay đổi các quyền trong Cài đặt &gt; Ứng dụng &gt; Nhắn tin &gt; Quyền."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Bạn có thể thay đổi các quyền trong Cài đặt, Ứng dụng, Nhắn tin, Quyền."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Liên hệ thường xuyên"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Tất cả liên hệ"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Gửi đến <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Chụp ảnh hoặc quay video"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Chọn hình ảnh từ thiết bị này"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Ghi âm"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Chọn ảnh"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Phương tiện được chọn."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Phương tiện không được chọn."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"Đã chọn <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"hình ảnh <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"hình ảnh"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Ghi âm"</string>
+    <string name="action_share" msgid="2143483844803153871">"Chia sẻ"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Vừa đăng"</string>
+    <string name="posted_now" msgid="867560789350406701">"Hiện tại"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> phút</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> phút</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> giờ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> giờ</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ngày</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ngày</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tuần</item>
+      <item quantity="one">một tuần</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tháng</item>
+      <item quantity="one">một tháng</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> năm</item>
+      <item quantity="one">một năm</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Thông báo hạng 0"</string>
+    <string name="save" msgid="5081141452059463572">"Lưu"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Thiết bị sắp hết bộ nhớ. Nhắn tin sẽ tự động xóa các tin nhắn cũ để giải phóng dung lượng."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Sắp hết dung lượng lưu trữ"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Nhắn tin không thể gửi hoặc nhận tin nhắn cho tới khi có thêm bộ nhớ trên thiết bị của bạn."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Sắp hết dung lượng SMS. Bạn có thể cần xóa tin nhắn."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Xác nhận số điện thoại của bạn"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Bước thực hiện một lần này sẽ đảm bảo ứng dụng Nhắn tin gửi tin nhắn nhóm của bạn đúng cách."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Số điện thoại"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Xóa tất cả tin nhắn có phương tiện"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Xóa tin nhắn cũ hơn <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Tự động xóa tin nhắn cũ hơn <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Bỏ qua"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Xóa tất cả tin nhắn có phương tiện?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Xóa tin nhắn cũ hơn <xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Xóa tin nhắn cũ hơn <xliff:g id="DURATION">%s</xliff:g> và bật tự động xóa?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> đã nói"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Bạn đã nói"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Tin nhắn từ <xliff:g id="SENDER">%s</xliff:g>:"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Bạn đã gửi tin nhắn"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Đang gửi…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Không gửi được. Hãy chạm để thử lại."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Không gửi được. Đang thử lại…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Gửi lại hoặc xóa"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Vui lòng thực hiện cuộc gọi thoại tới các dịch vụ khẩn cấp. Chúng tôi hiện không thể gửi tin nhắn văn bản của bạn."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Không thành công"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Tin nhắn MMS mới cần tải xuống"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Tin nhắn MMS mới"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Không thể tải xuống"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Chạm để thử lại"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Chạm để tải xuống"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Tải xuống hoặc xóa"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Đang tải xuống..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Tin nhắn đã hết hạn hoặc không khả dụng"</string>
+    <string name="mms_info" msgid="3402311750134118165">"kích thước: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, hết hạn: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Không thể gửi. Người nhận không hợp lệ."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Dịch vụ không được kích hoạt trên mạng"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Không thể gửi do sự cố mạng"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Tin nhắn đã hết hạn hoặc không khả dụng"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Không có chủ đề)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Người gửi không xác định"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Đã gửi"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Không thể tải xuống tin nhắn <xliff:g id="SUBJECT">%1$s</xliff:g> từ <xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Không thể hoàn tất thao tác liên quan đến cơ sở dữ liệu do sắp hết bộ nhớ"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Không gửi được tin nhắn"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Không gửi được một số tin nhắn trong Nhắn tin"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> tin nhắn trong <xliff:g id="CONVERSATIONS">%d</xliff:g> cuộc trò chuyện</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> tin nhắn trong một cuộc trò chuyện</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Không tải xuống được tin nhắn"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Không tải xuống được một số tin nhắn trong Nhắn tin"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> tin nhắn trong <xliff:g id="CONVERSATIONS">%d</xliff:g> cuộc trò chuyện</item>
+      <item quantity="one"><xliff:g id="MESSAGES_0">%d</xliff:g> tin nhắn trong một cuộc trò chuyện</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Tin nhắn tới <xliff:g id="NUMBER">%1$s</xliff:g> chưa được gửi"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Vui lòng thực hiện cuộc gọi thoại tới các dịch vụ khẩn cấp. Chúng tôi hiện không thể gửi tin nhắn văn bản của bạn tới <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> tin nhắn mới</item>
+      <item quantity="one">Tin nhắn mới</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Bắt đầu"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Máy ảnh không khả dụng"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Máy ảnh không khả dụng"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Quay video không khả dụng"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Không thể lưu phương tiện"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Không thể chụp ảnh"</string>
+    <string name="back" msgid="1477626055115561645">"Quay lại"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Đã lưu trữ"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Xóa"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Lưu trữ"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Hủy lưu trữ"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Tắt thông báo"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Bật thông báo"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Thêm liên hệ"</string>
+    <string name="action_download" msgid="7786338136368564146">"Tải xuống"</string>
+    <string name="action_send" msgid="377635240181672039">"Gửi"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Xóa"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Xóa tin nhắn này?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Không thể hoàn tác tác vụ này."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Xóa"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">Xóa những cuộc trò chuyện này?</item>
+      <item quantity="one">Xóa cuộc trò chuyện này?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Xóa"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Hủy"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Đến"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Chọn nhiều hình ảnh"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Xác nhận lựa chọn"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Không thể ghi âm thanh. Hãy thử lại."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Không thể phát âm thanh. Hãy thử lại."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Không thể lưu âm thanh. Hãy thử lại."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Chạm và giữ"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Hình ảnh"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Clip âm thanh"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Video"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Thẻ liên hệ"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Tải xuống"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Trả lời qua SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Trả lời qua MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Trả lời"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> người tham gia</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> người tham gia</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Tôi"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Đã chặn và lưu trữ địa chỉ liên hệ"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Đã bỏ chặn và hủy lưu trữ liên hệ"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"Đã lưu trữ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"Đã hủy lưu trữ <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Đã tắt thông báo"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Đã bật thông báo"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Đã hoàn tất. Hãy chạm vào Gửi lần nữa."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Đã đặt thành công Nhắn tin là ứng dụng SMS mặc định."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">Hủy tệp đính kèm</item>
+      <item quantity="one">Hủy tệp đính kèm</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Tệp âm thanh đính kèm"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Phát tệp âm thanh đính kèm"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Tạm dừng"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Tin nhắn từ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Không gửi được tin nhắn từ  <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Tin nhắn từ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Chưa gửi được tin nhắn tới  <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Đang gửi tin nhắn tới <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Không gửi được tin nhắn tới  <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Tin nhắn tới  <xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Không gửi được tin nhắn từ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Tin nhắn từ <xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Chưa gửi được tin nhắn tới <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Đang gửi tin nhắn tới <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Không gửi được tin nhắn tới  <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Tin nhắn tới <xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Thời gian: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Không gửi được tin nhắn. Hãy chạm để thử lại."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Cuộc trò chuyện với <xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Xóa chủ đề"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Quay video"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Chụp ảnh tĩnh"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Chụp ảnh"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Bắt đầu quay video"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Chuyển sang máy ảnh toàn màn hình"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Chuyển đổi giữa máy ảnh trước và sau"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Dừng quay và đính kèm video"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Dừng ghi video"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Ảnh trong Nhắn tin"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> ảnh đã được lưu vào album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> ảnh đã được lưu vào album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> video đã được lưu vào album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> video đã được lưu vào album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> tệp đính kèm đã được lưu vào album \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> tệp đính kèm đã được lưu vào album \"<xliff:g id="ALBUMNAME_1">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> tệp đính kèm đã được lưu vào \"Nội dung tải xuống\"</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> tệp đính kèm đã được lưu vào \"Nội dung tải xuống\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">Đã lưu <xliff:g id="QUANTITY_1">%d</xliff:g> tệp đính kèm</item>
+      <item quantity="one">Đã lưu <xliff:g id="QUANTITY_0">%d</xliff:g> tệp đính kèm</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">Không thể lưu <xliff:g id="QUANTITY_1">%d</xliff:g> tệp đính kèm</item>
+      <item quantity="one">Không thể lưu <xliff:g id="QUANTITY_0">%d</xliff:g> tệp đính kèm</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Đã lưu tệp đính kèm MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Cài đặt"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Đã lưu trữ"</string>
+    <string name="action_close" msgid="1840519376200478419">"Đóng"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Nâng cao"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Gỡ lỗi"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Thông báo"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Âm thanh"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Im lặng"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Rung"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Đã chặn"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Báo cáo gửi SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Yêu cầu báo cáo gửi cho mỗi SMS bạn gửi"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Tự động truy xuất"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Tự động truy xuất tin nhắn MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Tự động truy xuất khi chuyển vùng"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Tự động truy xuất MMS khi chuyển vùng"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Nhắn tin theo nhóm"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Sử dụng MMS để gửi một tin nhắn duy nhất khi có nhiều người nhận"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Ứng dụng SMS mặc định"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Ứng dụng SMS mặc định"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Số điện thoại của bạn"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Không xác định"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Âm thanh tin nhắn đi"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Kết xuất SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Kết xuất dữ liệu thô SMS đã nhận vào tệp bộ nhớ ngoài"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Kết xuất MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Kết xuất dữ liệu thô MMS đã nhận vào tệp bộ nhớ ngoài"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Cảnh báo không dây"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Tùy chọn tin nhắn"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Sao chép văn bản"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Xem chi tiết"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Xóa"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Chuyển tiếp"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Chi tiết tin nhắn"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Loại: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Tin nhắn văn bản"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Tin nhắn đa phương tiện"</string>
+    <string name="from_label" msgid="1947831848146564875">"Người gửi: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Người nhận: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Đã gửi: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Đã nhận: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Chủ đề: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Kích cỡ: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Mức độ ưu tiên: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Cao"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Bình thường"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Thấp"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Địa chỉ người gửi bị ẩn"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Không thể gửi tin nhắn trong khi tải tệp đính kèm."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Không thể tải tệp đính kèm. Hãy thử lại."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Mạng chưa sẵn sàng. Hãy thử lại."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Xóa văn bản"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Chuyển đổi giữa nhập văn bản và số"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Thêm người tham gia khác"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Xác nhận người tham gia"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Bắt đầu cuộc trò chuyện mới"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Chọn mục này"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Phát video"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Danh bạ và tùy chọn"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Gỡ lỗi"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Danh bạ và tùy chọn"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Chung"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Mọi người trong cuộc hội thoại này"</string>
+    <string name="action_call" msgid="6596167921517350362">"Gọi điện"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Gửi tin nhắn"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Gửi tin nhắn&lt;br/&gt;&lt;nhỏ&gt;từ <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/nhỏ&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">Gửi ảnh</item>
+      <item quantity="one">Gửi ảnh</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">Gửi âm thanh</item>
+      <item quantity="one">Gửi âm thanh</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">Gửi video</item>
+      <item quantity="one">Gửi video</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">Gửi danh thiếp</item>
+      <item quantity="one">Gửi danh thiếp</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">Gửi tệp đính kèm</item>
+      <item quantity="one">Gửi tệp đính kèm</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> tệp đính kèm đã sẵn sàng gửi</item>
+      <item quantity="one">Một tệp đính kèm đã sẵn sàng gửi</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Gửi phản hồi"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Xem trong Cửa hàng Google Play"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Thông tin phiên bản"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Phiên bản %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Giấy phép nguồn mở"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Thông báo"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Đã đạt đến giới hạn tệp đính kèm"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Không tải được tệp đính kèm."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Thêm vào Danh bạ?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Thêm liên hệ"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Chủ đề"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Chủ đề: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Đang tải thẻ liên hệ"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Không thể tải danh thiếp"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Xem thẻ liên hệ"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> liên hệ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> liên hệ</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Danh thiếp"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Ngày sinh"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Ghi chú"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Chuyển tiếp thư"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Trả lời"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"Đã tắt tính năng nhắn tin SMS"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Để gửi, hãy đặt Nhắn tin là ứng dụng SMS mặc định"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Đặt Nhắn tin là ứng dụng SMS mặc định"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Thay đổi"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Để nhận tin nhắn, hãy đặt Nhắn tin là ứng dụng SMS mặc định"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Không có SIM ưu tiên nào được chọn để gửi tin nhắn SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Ứng dụng này không được chủ sở hữu thiết bị cho phép."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"OK"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Có quá nhiều người tham gia trong một cuộc trò chuyện"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">Liên hệ không hợp lệ</item>
+      <item quantity="one">Liên hệ không hợp lệ</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Không thể tải hình ảnh trong máy ảnh"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Bạn: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Thư nháp"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Sau khi bạn bắt đầu một cuộc trò chuyện mới, bạn sẽ thấy cuộc trò chuyện đó được liệt kê ở đây"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Các cuộc trò chuyện đã lưu trữ xuất hiện ở đây"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Đang tải cuộc trò chuyện..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Hình ảnh"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Clip âm thanh"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Video"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Thẻ liên hệ"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Hoàn tác"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Thử lại"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Nhập tên liên hệ hoặc số điện thoại để bắt đầu tin nhắn mới"</string>
+    <string name="action_block" msgid="9032076625645190136">"Chặn"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Chặn <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Bỏ chặn <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Chặn <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Bạn sẽ tiếp tục nhận tin nhắn từ số này nhưng bạn sẽ không được thông báo nữa. Cuộc trò chuyện này sẽ được lưu trữ."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Địa chỉ liên hệ bị chặn"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"BỎ CHẶN"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Địa chỉ liên hệ bị chặn"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Chọn hình ảnh từ thư viện tài liệu"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Đang gửi tin nhắn"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Đã gửi tin nhắn"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Dữ liệu di động đã bị tắt. Hãy kiểm tra cài đặt của bạn."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Không thể gửi tin nhắn ở Chế độ trên máy bay"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Không thể gửi thư"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Đã tải tin nhắn xuống"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Dữ liệu di động đã bị tắt. Hãy kiểm tra cài đặt của bạn."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Không thể tải xuống tin nhắn ở Chế độ trên máy bay"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Không thể tải xuống tin nhắn"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Không"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Một"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Hai"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Ba"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Bốn"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Năm"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Sáu"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Bảy"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Tám"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Chín"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Không thể gửi tin nhắn bằng <xliff:g id="CARRIERNAME">%1$s</xliff:g>, lỗi <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Không thể gửi tin nhắn bằng nhà cung cấp dịch vụ không xác định, lỗi <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Chuyển tiếp: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Không gửi được tin nhắn: dịch vụ chưa được kích hoạt trên mạng"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Không gửi được tin nhắn: địa chỉ đích không hợp lệ"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Không gửi được tin nhắn: tin nhắn không hợp lệ"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Không gửi được tin nhắn: nội dung không được hỗ trợ"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Không gửi được tin nhắn: tin nhắn không được hỗ trợ"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Không gửi được tin nhắn: quá lớn"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Tin nhắn mới"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Xem"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Hình ảnh"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Không thể tìm thấy ứng dụng thích hợp"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Xóa người nhận"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Tin nhắn mới"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Hủy"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Chỉnh sửa điểm truy cập"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Chưa đặt"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Tên"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Proxy của MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Cổng MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Loại APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Xóa APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"APN mới"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Lưu"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Hủy"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Không được để trống trường Tên."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"Không được để trống APN."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Trường MCC phải có 3 chữ số."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Trường MNC phải có 2 hoặc 3 chữ số."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Đang khôi phục cài đặt APN mặc định."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Đặt lại về mặc định"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Đặt lại cài đặt APN mặc định đã hoàn tất."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Không có tiêu đề"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Tên điểm truy cập"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"APN mới"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Cài đặt Tên điểm truy cập không khả dụng cho người dùng này"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Sao chép vào khay nhớ tạm?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Sao chép"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"tới <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Chung"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Nâng cao"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Cài đặt chung"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Cài đặt nâng cao"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM \"<xliff:g id="SIM_NAME">%s</xliff:g>\""</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Gửi từng tin nhắn SMS cho tất cả người nhận. Chỉ bạn mới nhận được mọi tin nhắn trả lời"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Gửi một MMS cho tất cả người nhận"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Số điện thoại không xác định"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Tin nhắn mới"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Tin nhắn mới."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Bộ chọn SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"Đã chọn <xliff:g id="SIM_0">%1$s</xliff:g>, bộ chọn SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Chỉnh sửa chủ đề"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Chọn SIM hoặc chỉnh sửa chủ đề"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Chạm và giữ để ghi âm"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Bắt đầu cuộc trò chuyện mới"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Nhắn tin"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Danh sách Nhắn tin"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Nhắn tin"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Tin nhắn mới"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Danh sách cuộc hội thoại"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Đang tải cuộc trò chuyện..."</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Đang tải thư"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Xem các cuộc hội thoại khác"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Xem thêm tin nhắn"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Đã xóa cuộc hội thoại"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Đã xóa cuộc trò chuyện. Chạm để hiển thị cuộc trò chuyện khác trong Nhắn tin"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Đã chặn"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Đã bỏ chặn"</string>
+    <string name="db_full" msgid="8459265782521418031">"Dung lượng bộ nhớ thấp. Một số dữ liệu có thể bị mất."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Chọn tài liệu đính kèm"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Xác nhận lựa chọn"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"Đã chọn <xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Vui lòng xóa một hoặc nhiều tệp đính kèm và thử lại."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Bạn có thể thử gửi tin nhắn của mình nhưng tin nhắn có thể không gửi được trừ khi bạn xóa một hoặc nhiều tệp đính kèm."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Bạn chỉ có thể gửi một video cho mỗi tin nhắn. Hãy xóa các video khác rồi thử lại."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Ứng dụng Nhắn tin không tải được tệp đính kèm."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Vẫn gửi"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Không thể bắt đầu cuộc trò chuyện"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"Đã chọn <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-zh-rCN/arrays.xml b/res/values-zh-rCN/arrays.xml
new file mode 100644
index 0000000..9512884
--- /dev/null
+++ b/res/values-zh-rCN/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"无主题"</item>
+    <item msgid="272485471009191934">"无主题"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"是的"</item>
+    <item msgid="6049132459802288033">"不"</item>
+    <item msgid="3084376867445867895">"好"</item>
+    <item msgid="3155097332660174689">"呵呵"</item>
+    <item msgid="2611328818571146775">"谢谢"</item>
+    <item msgid="4881335087096496747">"同意"</item>
+    <item msgid="2422296858597420738">"不错"</item>
+    <item msgid="4805581752819452687">"在路上"</item>
+    <item msgid="4746700499431366214">"稍后再回复你"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..77dbfae
--- /dev/null
+++ b/res/values-zh-rCN/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"短信"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"短信"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"选择对话"</string>
+    <string name="action_settings" msgid="1329008122345201684">"设置"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"发送信息"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"添加附件"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"帮助"</string>
+    <string name="welcome" msgid="2857560951820802321">"欢迎使用"</string>
+    <string name="skip" msgid="7238879696319945853">"跳过"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"下一步 &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"下一步"</string>
+    <string name="exit" msgid="1905187380359981199">"退出"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"设置 &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"设置"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"“短信”应用需要获得“短信”、“电话”和“通讯录”的访问权限。"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"您可以在“设置”&gt;“应用”&gt;“短信”&gt;“权限”中更改权限。"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"您可以依次触摸“设置”、“应用”、“短信”和“权限”来更改权限。"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"常用联系人"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"所有联系人"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"发送到<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"拍照或录像"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"选择此设备上的图片"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"录制语音"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"选择照片"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"已选择此媒体。"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"已取消选择此媒体。"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"已选择<xliff:g id="COUNT">%d</xliff:g>项"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"图片(<xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>)"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"图片"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"录制语音"</string>
+    <string name="action_share" msgid="2143483844803153871">"分享"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"刚刚"</string>
+    <string name="posted_now" msgid="867560789350406701">"刚刚"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 分钟</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 分钟</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 小时</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 小时</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 天</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 天</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 周</item>
+      <item quantity="one">1 周</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 个月</item>
+      <item quantity="one">1 个月</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 年</item>
+      <item quantity="one">1 年</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"0级信息"</string>
+    <string name="save" msgid="5081141452059463572">"保存"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"设备存储空间不足。“短信”将自动删除较早的信息,以便腾出存储空间。"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"存储空间不足"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"除非您的设备上腾出更多可用空间,否则“短信”可能无法收发信息。"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"短信存储空间不足,建议您删除部分信息。"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"确认您的电话号码"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"执行这个一次性步骤可确保“短信”正确地传送您的群发信息。"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"电话号码"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"删除所有含媒体内容的信息"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"删除<xliff:g id="DURATION">%s</xliff:g>以前的信息"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"自动删除超过 <xliff:g id="DURATION">%s</xliff:g>以前的信息"</string>
+    <string name="ignore" msgid="7063392681130898793">"忽略"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"要删除所有含媒体内容的信息吗?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"要删除超过 <xliff:g id="DURATION">%s</xliff:g>以前的信息吗?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"要删除超过 <xliff:g id="DURATION">%s</xliff:g>以前的信息并开启自动删除功能吗?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>说"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"您说"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"来自<xliff:g id="SENDER">%s</xliff:g>的信息"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"您发送了一条信息"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"正在发送…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"发送失败。触摸即可重试。"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"发送失败。正在重试…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"重新发送或删除"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"请拨打语音电话寻求紧急服务。目前您的信息无法成功发送。"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"失败"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"待下载的新彩信"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"新彩信"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"无法下载"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"触摸即可重试"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"触摸即可下载"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"下载或删除"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"正在下载…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"信息已过期或无法查看"</string>
+    <string name="mms_info" msgid="3402311750134118165">"信息大小:<xliff:g id="MESSAGESIZE">%1$s</xliff:g>,过期时间:<xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"无法发送。收件人无效。"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"您尚未在网络上启用该服务。"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"遇到网络问题,发送失败"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"信息已过期或无法查看"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(无主题)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"未知发件人"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"已送达"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"无法下载来自<xliff:g id="FROM">%2$s</xliff:g>的信息“<xliff:g id="SUBJECT">%1$s</xliff:g>”。"</string>
+    <string name="low_memory" msgid="5300743415198486619">"内存不足,无法完成数据库操作"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"信息发送失败"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"“短信”未发送部分信息"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> 个对话中的 <xliff:g id="MESSAGES_1">%d</xliff:g> 条信息</item>
+      <item quantity="one">1 个对话中的 <xliff:g id="MESSAGES_0">%d</xliff:g> 条信息</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"信息下载失败"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"“短信”未下载部分信息"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> 个对话中的 <xliff:g id="MESSAGES_1">%d</xliff:g> 条信息</item>
+      <item quantity="one">1 个对话中的 <xliff:g id="MESSAGES_0">%d</xliff:g> 条信息</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"未能将信息发送至 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"请拨打语音电话寻求紧急服务。目前您的信息无法发送至 <xliff:g id="NUMBER">%1$s</xliff:g>。"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> 条新信息</item>
+      <item quantity="one">新信息</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"发起"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"无法使用相机"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"无法使用相机"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"无法使用视频拍摄功能"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"无法保存媒体"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"无法拍照"</string>
+    <string name="back" msgid="1477626055115561645">"返回"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"已归档的对话"</string>
+    <string name="action_delete" msgid="4076795795307486019">"删除"</string>
+    <string name="action_archive" msgid="5437034800324083170">"归档"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"取消归档"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"关闭通知"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"开启通知"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"添加到通讯录"</string>
+    <string name="action_download" msgid="7786338136368564146">"下载"</string>
+    <string name="action_send" msgid="377635240181672039">"发送"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"删除"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"要删除此信息吗?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"该操作无法撤消。"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"删除"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">要删除这些对话吗?</item>
+      <item quantity="one">要删除此对话吗?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"删除"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"取消"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"收件人"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"选择多张图片"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"确认选择"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"无法录制语音,请重试。"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"无法播放语音,请重试。"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"无法保存语音,请重试。"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"触摸并按住"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"、 "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"图片"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"语音"</string>
+    <string name="notification_video" msgid="4331423498662606204">"视频"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"名片"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"下载"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"通过短信回复"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"通过彩信回复"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"回复"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 位参与者</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 位参与者</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"我"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"联系人已被屏蔽且已归档"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"已取消屏蔽并取消归档联系人"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"已归档 <xliff:g id="COUNT">%d</xliff:g> 个"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"已取消归档 <xliff:g id="COUNT">%d</xliff:g> 个"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"通知已关闭"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"通知已开启"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"设置已完成。请再次触摸“发送”。"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"已成功地将“短信”设为默认短信应用。"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">舍弃附件</item>
+      <item quantity="one">舍弃附件</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"语音附件"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"播放语音附件"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"暂停"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"<xliff:g id="SENDER">%1$s</xliff:g>发来了消息:<xliff:g id="MESSAGE">%2$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>未能成功发送的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>发来的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"要发送给<xliff:g id="CONTACT">%1$s</xliff:g>的草稿信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"正在向<xliff:g id="CONTACT">%1$s</xliff:g>发送的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"未能成功发送给<xliff:g id="CONTACT">%1$s</xliff:g>的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"发送给<xliff:g id="CONTACT">%1$s</xliff:g>的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>未能成功发送的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>发来的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"要发送给<xliff:g id="GROUP">%1$s</xliff:g>的草稿信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"正在向<xliff:g id="GROUP">%1$s</xliff:g>发送的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"未能成功发送给<xliff:g id="GROUP">%1$s</xliff:g>的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"发送给<xliff:g id="GROUP">%1$s</xliff:g>的信息,内容为:<xliff:g id="MESSAGE">%2$s</xliff:g>。时间为:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"信息发送失败。触摸即可重试。"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"与<xliff:g id="PARTICIPANTS">%s</xliff:g>的对话"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"删除主题"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"拍摄视频"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"拍摄静态照片"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"拍照"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"开始录制视频"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"切换到全屏相机模式"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"在前置和后置相机之间切换"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"停止拍摄并添加视频附件"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"停止录制视频"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"“短信”中的照片"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 张照片已保存至“<xliff:g id="ALBUMNAME_3">%s</xliff:g>”相册</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 张照片已保存至“<xliff:g id="ALBUMNAME_1">%s</xliff:g>”相册</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 个视频已保存至“<xliff:g id="ALBUMNAME_3">%s</xliff:g>”相册</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 个视频已保存至“<xliff:g id="ALBUMNAME_1">%s</xliff:g>”相册</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 个附件已保存至“<xliff:g id="ALBUMNAME_3">%s</xliff:g>”相册</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 个附件已保存至“<xliff:g id="ALBUMNAME_1">%s</xliff:g>”相册</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> 个附件已保存至“下载内容”</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 个附件已保存至“下载内容”</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">已保存 <xliff:g id="QUANTITY_1">%d</xliff:g> 个附件</item>
+      <item quantity="one">已保存 <xliff:g id="QUANTITY_0">%d</xliff:g> 个附件</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">无法保存 <xliff:g id="QUANTITY_1">%d</xliff:g> 个附件</item>
+      <item quantity="one">无法保存 <xliff:g id="QUANTITY_0">%d</xliff:g> 个附件</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"保存的彩信附件"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"设置"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"已归档的对话"</string>
+    <string name="action_close" msgid="1840519376200478419">"关闭"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"彩信"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"高级"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"调试"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"通知"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"提示音"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"静音"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"振动"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"已屏蔽"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"短信送达情况报告"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"了解您发的每条短信的送达情况"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"自动检索"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"自动检索彩信"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"漫游时自动检索"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"漫游时自动检索彩信"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"群发彩信"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"有多个收件人时,也使用彩信发送信息"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"默认短信应用"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"默认短信应用"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"您的手机号码"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"未知"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"信息发送提示音"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"转储短信"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"将收到的短信原始数据转储到外部存储文件中"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"转储彩信"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"将收到的彩信原始数据转储到外部存储文件中"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"无线警报"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"信息选项"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"复制文字"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"查看详情"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"删除"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"转发"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"信息详情"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"类型: "</string>
+    <string name="text_message" msgid="7415419755252205721">"文字信息"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"多媒体信息"</string>
+    <string name="from_label" msgid="1947831848146564875">"发件人: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"收件人: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"发送时间: "</string>
+    <string name="received_label" msgid="4442494712757995203">"接收时间: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"主题: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"大小: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"优先级: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM 卡: "</string>
+    <string name="priority_high" msgid="728836357310908368">"高"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"中"</string>
+    <string name="priority_low" msgid="7398724779026801851">"低"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM 卡 <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"隐藏的发件人地址"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"附件尚未加载完毕,无法发送信息。"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"无法加载附件,请重试。"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"网络尚未就绪,请重试。"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"删除文字"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"在文字和数字输入模式间切换"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"添加更多参与者"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"确认参与者"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"发起新的对话"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"选择此项内容"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"播放视频"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"参与者名单和选项"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"调试"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"参与者名单和选项"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"常规"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"此对话的参与者"</string>
+    <string name="action_call" msgid="6596167921517350362">"拨打电话"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"发送信息"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"发送信息&lt;br/&gt;&lt;small&gt;(通过<xliff:g id="SIM_NAME">%s</xliff:g>)&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">发送照片</item>
+      <item quantity="one">发送照片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">发送语音</item>
+      <item quantity="one">发送语音</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">发送视频</item>
+      <item quantity="one">发送视频</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">发送名片</item>
+      <item quantity="one">发送名片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">发送附件</item>
+      <item quantity="one">发送附件</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> 个附件待发送</item>
+      <item quantity="one">1 个附件待发送</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"发送反馈"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"在 Google Play 商店中查看"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"版本信息"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"版本%1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"开放源代码许可"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"通知"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"已达到附件上限"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"加载附件失败。"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"要添加到通讯录吗?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"添加到通讯录"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"主题"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"主题: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"正在加载名片"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"无法加载名片"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"查看名片"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 位联系人</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 位联系人</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"名片"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"生日"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"备注"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"转发信息"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"回复"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"短信功能已停用"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"要发送信息,请将“短信”设为默认短信应用"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"将“短信”设为默认短信应用"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"更改"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"要接收信息,请将“短信”设为默认短信应用"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"未选择用于发送短信的首选 SIM 卡"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"此应用未获得设备机主授权。"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"确定"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"对话中的参与者过多"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">联系人无效</item>
+      <item quantity="one">联系人无效</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"无法加载相机图像"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"你: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"草稿"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"您的短信对话将列在此处"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"已归档的对话会显示在此处"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"正在加载对话…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"照片"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"语音"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"视频"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"名片"</string>
+    <string name="mms_text" msgid="1528791558806015806">"彩信"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"撤消"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"重试"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"要发送新信息,请输入联系人姓名或电话号码"</string>
+    <string name="action_block" msgid="9032076625645190136">"屏蔽"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"屏蔽<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"取消屏蔽<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"要屏蔽<xliff:g id="DESTINATION">%s</xliff:g>吗?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"您将继续接收来自此号码的信息,但不会再收到相关通知。此对话将被归档。"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"屏蔽的联系人"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"取消屏蔽"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"屏蔽的联系人"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"从文档库中选择图片"</string>
+    <string name="sending_message" msgid="6363584950085384929">"正在发送消息"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"消息已发送"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"移动数据网络已关闭。请检查您的设置。"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"在飞行模式下无法发送信息"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"无法发送信息"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"彩信已下载"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"移动数据网络已关闭。请检查您的设置。"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"在飞行模式下无法下载信息"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"无法下载信息"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"0"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"1"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"2"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"3"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"4"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"5"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"6"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"7"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"8"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"9"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"无法发送消息(运营商:<xliff:g id="CARRIERNAME">%1$s</xliff:g>,错误代码:<xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"无法发送消息(运营商:未知,错误代码:<xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"转发:<xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"信息发送失败:服务未在网络上激活"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"信息发送失败:目标地址无效"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"信息发送失败:信息无效"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"信息发送失败:内容不受支持"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"信息发送失败:信息不受支持"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"信息发送失败:信息过长"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"新信息"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"查看"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"图片"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"找不到合适的应用"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"移除收件人"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"新消息"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"取消"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"修改接入点"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"未设置"</string>
+    <string name="apn_name" msgid="1572691851070894985">"名称"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"彩信代理"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"彩信端口"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN 类型"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"删除 APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"新建 APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"保存"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"舍弃"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"“名称”字段不能为空。"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN 不能为空。"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC 字段必须为 3 位数。"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC 字段必须为 2 位数或 3 位数。"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"正在恢复默认 APN 设置。"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"重置为默认值"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"已重置默认 APN 设置。"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"未命名"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"接入点名称"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"新建 APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"此用户无权修改接入点名称设置"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"要复制到剪贴板吗?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"复制"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"发至<xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"常规"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"高级"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"常规设置"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"高级设置"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"SIM 卡 “<xliff:g id="SIM_NAME">%s</xliff:g>”"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"将单条短信发送给所有收件人。只有您能收到相应回复"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"将单条彩信发送给所有收件人"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"未知号码"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"新信息"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"新信息。"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM 卡选择器"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"已选择<xliff:g id="SIM_0">%1$s</xliff:g>,SIM 卡选择器"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"修改主题"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"选择 SIM 卡或修改主题"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"触摸并按住即可录制语音"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"发起新的对话"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"短信"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"短信列表"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"短信"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"新信息"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"对话列表"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"正在加载对话"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"正在加载信息"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"查看更多对话"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"查看更多信息"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"对话已删除"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"对话已删除。触摸可显示其他“短信”对话"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"已屏蔽"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"已取消屏蔽"</string>
+    <string name="db_full" msgid="8459265782521418031">"存储空间不足,部分数据可能会丢失。"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"选择附件"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"确认选择"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"已选择 <xliff:g id="COUNT">%d</xliff:g> 个附件"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"请移除一个或多个附件,然后重试。"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"您可以尝试发送信息,但您可能需要移除一个或多个附件才能成功发送。"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"您在每条消息中只能发送一个视频。请移除多余的视频,然后重试。"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"“短信”无法加载附件。"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"仍然发送"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"无法发起对话"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"已选择<xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-zh-rHK/arrays.xml b/res/values-zh-rHK/arrays.xml
new file mode 100644
index 0000000..ab1cad4
--- /dev/null
+++ b/res/values-zh-rHK/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"沒有主旨"</item>
+    <item msgid="272485471009191934">"無主旨"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"是"</item>
+    <item msgid="6049132459802288033">"否"</item>
+    <item msgid="3084376867445867895">"確定"</item>
+    <item msgid="3155097332660174689">"呵呵"</item>
+    <item msgid="2611328818571146775">"謝謝"</item>
+    <item msgid="4881335087096496747">"我同意"</item>
+    <item msgid="2422296858597420738">"很好"</item>
+    <item msgid="4805581752819452687">"我正在路上"</item>
+    <item msgid="4746700499431366214">"好,我稍後再回覆您"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..a5c690f
--- /dev/null
+++ b/res/values-zh-rHK/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"訊息"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"訊息"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"選取對話群組"</string>
+    <string name="action_settings" msgid="1329008122345201684">"設定"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"傳送訊息"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"新增附件"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"說明"</string>
+    <string name="welcome" msgid="2857560951820802321">"歡迎"</string>
+    <string name="skip" msgid="7238879696319945853">"略過"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"繼續 &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"下一步"</string>
+    <string name="exit" msgid="1905187380359981199">"結束"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"設定 &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"設定"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"「短訊」需要存取短訊、手機和聯絡人的權限。"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"您可以前往 [設定] &gt; [應用程式] &gt; [短訊] &gt; [權限] 變更權限。"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"您可以前往 [設定]、[應用程式]、[短訊]、[權限] 變更權限。"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"常用聯絡人"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"所有聯絡人"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"傳送至 <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"拍照或錄影"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"從這部裝置選擇圖片"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"錄音"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"選擇相片"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"已選取媒體。"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"已取消選取媒體。"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"已選取 <xliff:g id="COUNT">%d</xliff:g> 個項目"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"<xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>的圖片"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"圖片"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"錄音"</string>
+    <string name="action_share" msgid="2143483844803153871">"分享"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"剛剛"</string>
+    <string name="posted_now" msgid="867560789350406701">"現在"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>分鐘</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>分鐘</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>小時</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>小時</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>天</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>天</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>個星期</item>
+      <item quantity="one">一個星期</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>個月</item>
+      <item quantity="one">一個月</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>年</item>
+      <item quantity="one">一年</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"等級 0 訊息"</string>
+    <string name="save" msgid="5081141452059463572">"儲存"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"裝置儲存空間不足。「短訊」會自動刪除較舊的訊息以騰出空間。"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"儲存空間即將用盡"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"「短訊」需要更多裝置空間方可發送或接收訊息。"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"短訊儲存空間即將用完,建議您刪除部分訊息。"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"確認您的電話號碼"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"這個單一步驟能確保「短訊」正確發送群組訊息。"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"電話號碼"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"刪除所有附有媒體的訊息"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"自動刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息"</string>
+    <string name="ignore" msgid="7063392681130898793">"略過"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"要刪除所有附有媒體檔案的訊息嗎?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"要刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息嗎?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"要刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息並開啟自動刪除嗎?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"傳送者:<xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"您說"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"來自<xliff:g id="SENDER">%s</xliff:g>的訊息"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"您傳送了訊息"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"正在傳送…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"訊息傳送失敗,輕觸即可再試一次。"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"訊息傳送失敗,正在重試…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"重新傳送或刪除"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"請致電緊急服務。目前,您的短訊無法送達。"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"失敗"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"下載新的多媒體訊息"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"新的多媒體訊息"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"無法下載"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"輕觸即可再試一次"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"輕觸即可下載"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"下載或刪除"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"正在下載…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"訊息已過期或無法取得"</string>
+    <string name="mms_info" msgid="3402311750134118165">"大小:<xliff:g id="MESSAGESIZE">%1$s</xliff:g>,期限:<xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"收件者無效,因此無法傳送訊息。"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"您還未在網絡上啟用這項服務"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"網絡發生問題,因此無法傳送"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"訊息已過期或無法取得"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(沒有主旨)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"未知的寄件者"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"已傳送"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"無法下載 <xliff:g id="FROM">%2$s</xliff:g> 傳送的這則訊息「<xliff:g id="SUBJECT">%1$s</xliff:g>」。"</string>
+    <string name="low_memory" msgid="5300743415198486619">"記憶體不足,因此無法完成資料庫操作"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"無法傳送訊息"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"部分訊息未能在「短訊」中發送"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>個對話中的<xliff:g id="MESSAGES_1">%d</xliff:g>則訊息</item>
+      <item quantity="one">一個對話中的<xliff:g id="MESSAGES_0">%d</xliff:g>則訊息</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"仍未下載訊息"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"部分訊息未能在「短訊」中下載"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g>個對話中的<xliff:g id="MESSAGES_1">%d</xliff:g>則訊息</item>
+      <item quantity="one">一個對話中的<xliff:g id="MESSAGES_0">%d</xliff:g>則訊息</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"未能傳送訊息至 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"請致電緊急服務。目前,您的短訊無法送達至 <xliff:g id="NUMBER">%1$s</xliff:g>。"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> 則新訊息</item>
+      <item quantity="one">新訊息</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"開始"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"無法使用相機"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"無法使用相機"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"無法錄製影片"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"無法儲存媒體檔案"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"無法拍照"</string>
+    <string name="back" msgid="1477626055115561645">"返回"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"已封存"</string>
+    <string name="action_delete" msgid="4076795795307486019">"刪除"</string>
+    <string name="action_archive" msgid="5437034800324083170">"封存"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"取消封存"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"關閉通知"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"開啟通知"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"新增聯絡人"</string>
+    <string name="action_download" msgid="7786338136368564146">"下載"</string>
+    <string name="action_send" msgid="377635240181672039">"傳送"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"刪除"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"要刪除這個訊息嗎?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"此操作將無法復原。"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"刪除"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">要刪除這些對話嗎?</item>
+      <item quantity="one">要刪除這個對話嗎?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"刪除"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"取消"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"收件者︰"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"選取多個圖片"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"確認選取"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"超過 <xliff:g id="COUNT">%d</xliff:g> 個項目"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"無法錄製語音,請再試一次。"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"無法播放語音,請再試一次。"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"無法儲存語音,請再試一次。"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"輕觸並按住"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"、 "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"圖片"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"錄音片段"</string>
+    <string name="notification_video" msgid="4331423498662606204">"影片"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"聯絡人卡"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"下載"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"透過短訊回覆"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"透過 MMS 回覆"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"回覆"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>位參加者</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>位參加者</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"我"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"已封鎖並封存聯絡人"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"已解除封鎖並取消封存聯絡人"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"已封存 <xliff:g id="COUNT">%d</xliff:g> 個對話記錄"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"已取消封存 <xliff:g id="COUNT">%d</xliff:g> 個項目"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"已關閉通知"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"已開啟通知"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"準備就緒,輕觸 [重新傳送]。"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"已成功將「短訊」設定為預設短訊應用程式。"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">捨棄附件</item>
+      <item quantity="one">捨棄附件</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"音效檔案附件"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"播放音效檔案附件"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"暫停"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"來自<xliff:g id="SENDER">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>未能成功傳送的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>傳送的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"尚未傳送給<xliff:g id="CONTACT">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"正在傳送給<xliff:g id="CONTACT">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"未能成功傳送給<xliff:g id="CONTACT">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"傳送給<xliff:g id="CONTACT">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>未能成功傳送的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>傳送的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"尚未傳送給<xliff:g id="GROUP">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"正在傳送給<xliff:g id="GROUP">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"未能成功傳送給<xliff:g id="GROUP">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"傳送給<xliff:g id="GROUP">%1$s</xliff:g>的訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"未能成功傳送的訊息。輕觸即可重試。"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"與<xliff:g id="PARTICIPANTS">%s</xliff:g>的對話"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"刪除主旨"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"拍攝影片"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"拍攝靜態圖像"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"拍照"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"開始錄製影片"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"切換至全屏攝像"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"切換前置和後置鏡頭"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"停止錄製並附加影片"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"停止錄製影片"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"「短訊」相片"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 張相片已儲存至「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 張相片已儲存至「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 部影片已儲存至「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 部影片已儲存至「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 個附件已儲存至「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 個附件已儲存至「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> 個附件已儲存至「下載」</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 個附件已儲存至「下載」</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">已儲存<xliff:g id="QUANTITY_1">%d</xliff:g>個附件</item>
+      <item quantity="one">已儲存<xliff:g id="QUANTITY_0">%d</xliff:g>個附件</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">無法儲存<xliff:g id="QUANTITY_1">%d</xliff:g>個附件</item>
+      <item quantity="one">無法儲存<xliff:g id="QUANTITY_0">%d</xliff:g>個附件</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"已儲存的 MMS 附件"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"設定"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"已封存"</string>
+    <string name="action_close" msgid="1840519376200478419">"關閉"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"進階"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"除錯"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"通知"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"音效"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"靜音"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"震動"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"已封鎖"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"短訊傳送報告"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"每次發送短訊後要求發送報告"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"自動擷取"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"自動擷取 MMS 訊息"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"漫遊時自動擷取"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"漫遊時自動擷取 MMS 訊息"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"群組短訊"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"有多位收件者時只發送一則 MMS 訊息"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"預設短訊應用程式"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"預設短訊應用程式"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"您的電話號碼"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"不明"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"傳送訊息音效"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"傾印短訊"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"將收到的短訊原始資料傾印到外部儲存檔案"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"傾印 MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"將收到的 MMS 原始資料傾印到外部儲存檔案"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"無線警示"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"訊息選項"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"複製文字"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"查看詳情"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"刪除"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"轉寄"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"訊息詳情"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"類型: "</string>
+    <string name="text_message" msgid="7415419755252205721">"短訊"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"多媒體訊息"</string>
+    <string name="from_label" msgid="1947831848146564875">"寄件者: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"收件者: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"傳送時間: "</string>
+    <string name="received_label" msgid="4442494712757995203">"接收時間: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"主旨: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"大小: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"重要: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM 卡: "</string>
+    <string name="priority_high" msgid="728836357310908368">"高"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"正常"</string>
+    <string name="priority_low" msgid="7398724779026801851">"低"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM 卡 <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"隱藏的寄件者地址"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"載入附件時無法傳送訊息。"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"無法載入附件,請再試一次。"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"網絡尚未準備好,請再試一次。"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"刪除文本"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"切換文字和數字輸入"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"新增更多參與者"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"確認參與者"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"開始新的對話"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"選取這個項目"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"播放影片"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"參與者和選項"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"除錯"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"參與者和選項"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"一般"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"這個對話的參與者"</string>
+    <string name="action_call" msgid="6596167921517350362">"進行通話"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"傳送訊息"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;br/&gt;&lt;small&gt;從 <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt; 發送短訊"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">傳送相片</item>
+      <item quantity="one">傳送相片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">傳送音效檔案</item>
+      <item quantity="one">傳送音效檔案</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">傳送影片</item>
+      <item quantity="one">傳送影片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">傳送聯絡資料</item>
+      <item quantity="one">傳送聯絡資料</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">傳送附件</item>
+      <item quantity="one">傳送附件</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g>個附件正等待傳送</item>
+      <item quantity="one">一個附件正等待傳送</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"傳送意見"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"前往 Google Play 商店查看"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"版本資料"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"%1$s 版"</string>
+    <string name="menu_license" msgid="1157954180701135202">"開放原始碼授權"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"通知"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"已達到附件限制"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"未能成功載入附件。"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"新增至聯絡人?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"新增聯絡人"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"主旨"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"主旨: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g>:<xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"正在載入聯絡人卡片"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"無法載入聯絡人資訊卡"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"查看聯絡人卡片"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 個聯絡人</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 個聯絡人</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"聯絡人資訊卡"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"生日"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"附註"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"轉寄郵件"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"回覆"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"短訊功能已停用"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"將「短訊」設定為預設短訊應用程式,即可發送訊息"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"將「短訊」設定為預設短訊應用程式"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"變更"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"將「短訊」設定為預設短訊應用程式,即可接收訊息"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"尚未選取傳送短訊的首選 SIM"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"裝置擁有者不允許使用該應用程式。"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"確定"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"參與對話的人過多"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">無效的聯絡人</item>
+      <item quantity="one">無效的聯絡人</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"無法載入相機圖片"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"您: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"草稿"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"只要有新對話,便會在此列出"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"封存的對話顯示在這裏"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"正在載入對話…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"圖片"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"錄音片段"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"影片"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"聯絡人卡"</string>
+    <string name="mms_text" msgid="1528791558806015806">"MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"復原"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"重試"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"如要傳送新訊息,請輸入聯絡人姓名或電話號碼"</string>
+    <string name="action_block" msgid="9032076625645190136">"封鎖"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"封鎖<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"解除封鎖<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"要封鎖 <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"您將繼續接收這個電話號碼傳來的訊息,但不會再收到通知。這個對話將被封存。"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"已封鎖的聯絡人"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"解除封鎖"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"已封鎖的聯絡人"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"從文件庫選擇圖片"</string>
+    <string name="sending_message" msgid="6363584950085384929">"正在傳送訊息"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"已傳送訊息"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"流動數據已關閉,請檢查您的設定。"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"無法在飛行模式下傳送訊息"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"無法傳送訊息"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"已下載訊息"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"流動數據已關閉,請檢查您的設定。"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"在飛行模式下無法下載訊息"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"無法下載訊息"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"0"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"1"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"2"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"3"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"4"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"5"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"6"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"7"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"8"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"9"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"無法經<xliff:g id="CARRIERNAME">%1$s</xliff:g>傳送訊息,錯誤:<xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"無法經不明流動網絡供應商傳送訊息,錯誤:<xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"轉寄:<xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"無法傳送訊息:未在網絡上啟用服務"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"無法傳送訊息:目的地位址無效"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"無法傳送訊息:訊息無效"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"無法傳送訊息:不支援的內容"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"無法傳送訊息:不支援的訊息"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"無法傳送訊息:太大"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"新訊息"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"檢視"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"圖片"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"找不到合適的應用程式"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"移除收件者"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"新訊息"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"取消"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"編輯接入點"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"未設定"</string>
+    <string name="apn_name" msgid="1572691851070894985">"名稱"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"MMS 代理"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"MMS 通訊埠"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN 類型"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"刪除 APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"新增 APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"儲存"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"捨棄"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"[名稱] 欄位不可留空。"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN 不可留空。"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC 欄位必須為 3 位數。"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC 欄位必須要有 2 或 3 位數。"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"正在還原預設 APN 設定。"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"重設回預設值"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"重設預設 APN 設定已完成。"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"未命名"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"接入點名稱"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"新增 APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"這位使用者無法修改存取點名稱設定"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"要複製到剪貼簿嗎?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"複製"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"至 <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"一般"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"進階"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"一般設定"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"進階設定"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"「<xliff:g id="SIM_NAME">%s</xliff:g>」SIM 卡"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"向所有收件者逐一傳送短訊。只有您會收到回覆"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"向所有收件者傳送一封 MMS"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"電話號碼不明"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"新訊息"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"新訊息。"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM 選取器"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"已選擇<xliff:g id="SIM_0">%1$s</xliff:g>,SIM 選取器"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"編輯主旨"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"選取 SIM 或編輯主旨"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"輕觸並按住即可錄製音效檔案"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"開始新的對話"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"短訊"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"「短訊」清單"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"短訊"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"新訊息"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"對話群組清單"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"正在載入對話"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"正在載入訊息"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"查看更多對話"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"查看更多訊息"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"對話群組已刪除"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"已刪除對話,輕觸即可查看其他「短訊」對話"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"已封鎖"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"已解除封鎖"</string>
+    <string name="db_full" msgid="8459265782521418031">"儲存空間不足。部分資料可能會遺失。"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"選取附件"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"確認選取"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"已選取 <xliff:g id="COUNT">%d</xliff:g> 個附件"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"請移除一個或多個附件,然後再試一次。"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"您可以嘗試傳送訊息,但可能要移除一個或多個附件才可送達。"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"每封郵件只可傳送一部影片。請移除額外的影片,然後再試一次。"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"「短訊」無法載入附件。"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"直接傳送"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"無法開始對話"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"已選取 <xliff:g id="SELECTED_SIM">%s</xliff:g>"</string>
+</resources>
diff --git a/res/values-zh-rTW/arrays.xml b/res/values-zh-rTW/arrays.xml
new file mode 100644
index 0000000..3226b70
--- /dev/null
+++ b/res/values-zh-rTW/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"無主旨"</item>
+    <item msgid="272485471009191934">"無主旨"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"是"</item>
+    <item msgid="6049132459802288033">"否"</item>
+    <item msgid="3084376867445867895">"確定"</item>
+    <item msgid="3155097332660174689">"呵呵"</item>
+    <item msgid="2611328818571146775">"謝謝"</item>
+    <item msgid="4881335087096496747">"我同意"</item>
+    <item msgid="2422296858597420738">"很好"</item>
+    <item msgid="4805581752819452687">"我正在路上"</item>
+    <item msgid="4746700499431366214">"好,我稍後再回覆您"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..c911ea7
--- /dev/null
+++ b/res/values-zh-rTW/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"簡訊"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"簡訊"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"選取對話"</string>
+    <string name="action_settings" msgid="1329008122345201684">"設定"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"傳送訊息"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"新增附件"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"説明"</string>
+    <string name="welcome" msgid="2857560951820802321">"歡迎使用"</string>
+    <string name="skip" msgid="7238879696319945853">"略過"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"繼續 &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"繼續"</string>
+    <string name="exit" msgid="1905187380359981199">"結束"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"設定 &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"設定"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"「簡訊」需要取得簡訊、電話和聯絡人應用程式的存取權限。"</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"如要變更權限,請依序前往 [設定] &gt; [應用程式] &gt; [簡訊] &gt; [權限]。"</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"如要變更權限,請依序前往 [設定]、[應用程式]、[簡訊] 及 [權限]。"</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"常用聯絡人"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"所有聯絡人"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"傳送至 <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"拍照或錄影"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"選擇這個裝置上的圖片"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"錄音"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"選擇相片"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"已選取媒體。"</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"已取消選取媒體。"</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"已選取 <xliff:g id="COUNT">%d</xliff:g> 個項目"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"圖片 (<xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>)"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"圖片"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"錄音"</string>
+    <string name="action_share" msgid="2143483844803153871">"分享"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"剛剛"</string>
+    <string name="posted_now" msgid="867560789350406701">"最新"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 分鐘</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 分鐘</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 小時</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 小時</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 天</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 天</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 週</item>
+      <item quantity="one">1 週</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 個月</item>
+      <item quantity="one">1 個月</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 年</item>
+      <item quantity="one">1 年</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"等級 0 訊息"</string>
+    <string name="save" msgid="5081141452059463572">"儲存"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"裝置儲存空間不足,「簡訊」會自動刪除較舊簡訊以釋出空間。"</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"儲存空間不足"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"在裝置可用空間增加前,「簡訊」可能無法收發訊息。"</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"簡訊儲存空間即將用完,建議您刪除部分訊息。"</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"驗證您的手機號碼"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"這個一次性步驟可確保「簡訊」正確傳送群組訊息。"</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"手機號碼"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"刪除所有內含媒體的訊息"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"自動刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息"</string>
+    <string name="ignore" msgid="7063392681130898793">"忽略"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"刪除所有內含媒體的訊息?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"刪除超過 <xliff:g id="DURATION">%s</xliff:g>的訊息並開啟自動刪除設定?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g>說了"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"您說了"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"來自<xliff:g id="SENDER">%s</xliff:g>的訊息"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"您傳送了訊息"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"傳送中…"</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"傳送失敗,輕觸即可再試一次。"</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"傳送失敗,正在嘗試重新傳送…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"重新傳送或刪除"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"目前無法傳送您的簡訊,請撥打語音電話聯絡緊急服務。"</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"失敗"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"可下載新的多媒體訊息"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"新的多媒體訊息"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"無法下載"</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"輕觸即可再試一次"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"輕觸即可下載"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"下載或刪除"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"下載中…"</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"訊息已過期或無法存取"</string>
+    <string name="mms_info" msgid="3402311750134118165">"大小:<xliff:g id="MESSAGESIZE">%1$s</xliff:g>,期限:<xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"收件者無效,因此無法傳送訊息。"</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"尚未透過網路啟用服務"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"網路發生問題,因此無法傳送"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"訊息已過期或無法存取"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(無主旨)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"寄件者不明"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"已傳送"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"無法下載來自 <xliff:g id="FROM">%2$s</xliff:g> 的這則訊息:<xliff:g id="SUBJECT">%1$s</xliff:g>。"</string>
+    <string name="low_memory" msgid="5300743415198486619">"記憶體不足,因此無法完成資料庫作業"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"訊息未傳送"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"「簡訊」未傳送部分訊息"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> 個對話中的 <xliff:g id="MESSAGES_1">%d</xliff:g> 則訊息</item>
+      <item quantity="one">1 個對話中的 <xliff:g id="MESSAGES_0">%d</xliff:g> 則訊息</item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"訊息未順利下載"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"「簡訊」未下載部分訊息"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="other"><xliff:g id="CONVERSATIONS">%d</xliff:g> 個對話中的 <xliff:g id="MESSAGES_1">%d</xliff:g> 則訊息</item>
+      <item quantity="one">1 個對話中的 <xliff:g id="MESSAGES_0">%d</xliff:g> 則訊息</item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"無法傳送訊息給 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"目前無法將您的簡訊傳送至 <xliff:g id="NUMBER">%1$s</xliff:g>,請撥打語音電話聯絡緊急服務。"</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> 則新訊息</item>
+      <item quantity="one">新訊息</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"發起"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"無法使用相機"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"無法使用相機"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"無法錄影"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"無法儲存媒體"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"無法拍照"</string>
+    <string name="back" msgid="1477626055115561645">"返回"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"已封存"</string>
+    <string name="action_delete" msgid="4076795795307486019">"刪除"</string>
+    <string name="action_archive" msgid="5437034800324083170">"封存"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"取消封存"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"關閉通知"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"開啟通知"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"新增聯絡人"</string>
+    <string name="action_download" msgid="7786338136368564146">"下載"</string>
+    <string name="action_send" msgid="377635240181672039">"傳送"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"刪除"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"刪除這則訊息?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"這項操作無法復原。"</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"刪除"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="other">要刪除這些對話嗎?</item>
+      <item quantity="one">要刪除這個對話嗎?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"刪除"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"取消"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"收件者"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"選取多張圖片"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"確認選取"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"超過 <xliff:g id="COUNT">%d</xliff:g> 個項目"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"無法錄製音訊,請再試一次。"</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"無法播放音訊,請再試一次。"</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"無法儲存音訊,請再試一次。"</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"輕觸並按住"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">"、 "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"圖片"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"音訊剪輯"</string>
+    <string name="notification_video" msgid="4331423498662606204">"影片"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"聯絡人卡片"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"下載"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"透過簡訊回覆"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"透過多媒體訊息回覆"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"回覆"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 位參與者</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 位參與者</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"我"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"已封鎖並封存聯絡人"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"已解除封鎖及解除封存聯絡人"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"已封存 <xliff:g id="COUNT">%d</xliff:g> 個"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"已解除封存 <xliff:g id="COUNT">%d</xliff:g> 個"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"已關閉通知功能"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"已開啟通知功能"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"設定程序已完成,請再次輕觸 [傳送]。"</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"已成功將「簡訊」設為預設的簡訊應用程式。"</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="other">捨棄附件</item>
+      <item quantity="one">捨棄附件</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"音訊附件"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"播放音訊附件"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"暫停"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"收到<xliff:g id="SENDER">%1$s</xliff:g>傳送的訊息,內容如下:<xliff:g id="MESSAGE">%2$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"<xliff:g id="SENDER">%1$s</xliff:g>嘗試傳送訊息但未成功:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"<xliff:g id="SENDER">%1$s</xliff:g>傳送了訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"給<xliff:g id="CONTACT">%1$s</xliff:g>的訊息尚未送出:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"正在傳送訊息給<xliff:g id="CONTACT">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"無法傳送訊息給<xliff:g id="CONTACT">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"已傳送訊息給<xliff:g id="CONTACT">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"<xliff:g id="SENDER">%1$s</xliff:g>嘗試傳送訊息但未成功:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"<xliff:g id="SENDER">%1$s</xliff:g>傳送了訊息:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。<xliff:g id="GROUPINFO">%4$s</xliff:g>。"</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"給<xliff:g id="GROUP">%1$s</xliff:g>的訊息尚未送出:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"正在傳送訊息給<xliff:g id="GROUP">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"無法傳送訊息給<xliff:g id="GROUP">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"已傳送訊息給<xliff:g id="GROUP">%1$s</xliff:g>:<xliff:g id="MESSAGE">%2$s</xliff:g>。時間:<xliff:g id="TIME">%3$s</xliff:g>。"</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"訊息傳送失敗,輕觸即可重試。"</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"與<xliff:g id="PARTICIPANTS">%s</xliff:g>的對話"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"刪除主旨"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"錄影"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"拍攝靜態影像"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"拍照"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"開始錄影"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"切換至全螢幕相機"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"切換使用前置與後置鏡頭"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"停止錄影並附加影片"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"停止錄影"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"簡訊相片"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 張相片已儲存到「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 張相片已儲存到「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 段影片已儲存到「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 段影片已儲存到「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> 份附件已儲存到「<xliff:g id="ALBUMNAME_3">%s</xliff:g>」相簿</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 份附件已儲存到「<xliff:g id="ALBUMNAME_1">%s</xliff:g>」相簿</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> 份附件已儲存到「下載內容」</item>
+      <item quantity="one"><xliff:g id="QUANTITY_0">%d</xliff:g> 份附件已儲存到「下載內容」</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="other">已儲存 <xliff:g id="QUANTITY_1">%d</xliff:g> 個附件</item>
+      <item quantity="one">已儲存 <xliff:g id="QUANTITY_0">%d</xliff:g> 個附件</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="other">無法儲存 <xliff:g id="QUANTITY_1">%d</xliff:g> 個附件</item>
+      <item quantity="one">無法儲存 <xliff:g id="QUANTITY_0">%d</xliff:g> 個附件</item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"已儲存的多媒體訊息附件"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"設定"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"已封存"</string>
+    <string name="action_close" msgid="1840519376200478419">"關閉"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"多媒體訊息"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"進階"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"偵錯"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"通知"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"音效"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"靜音"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"震動"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"已封鎖"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"簡訊傳送報告"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"傳送簡訊後要求傳送回條"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"自動擷取"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"自動擷取多媒體訊息"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"漫遊時自動擷取"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"漫遊時自動擷取多媒體訊息"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"群組簡訊"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"有多位收件者時,也使用多媒體訊息傳送訊息"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"預設簡訊應用程式"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"預設簡訊應用程式"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"您的電話號碼"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"不明"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"訊息傳送音效"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"傾印簡訊"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"將收到的簡訊原始資料傾印到外部儲存空間檔案"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"傾印多媒體訊息"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"將收到的多媒體訊息原始資料傾印到外部儲存空間檔案"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"無線災害示警"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"訊息選項"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"複製文字"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"查看詳細資料"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"刪除"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"轉寄"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"訊息詳細資料"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"類型: "</string>
+    <string name="text_message" msgid="7415419755252205721">"簡訊"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"多媒體訊息"</string>
+    <string name="from_label" msgid="1947831848146564875">"寄件者: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"收件者: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"傳送時間: "</string>
+    <string name="received_label" msgid="4442494712757995203">"接收時間: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"主旨: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"大小: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"優先順序: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM 卡: "</string>
+    <string name="priority_high" msgid="728836357310908368">"高"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"一般"</string>
+    <string name="priority_low" msgid="7398724779026801851">"低"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM 卡 <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"隱藏的寄件者地址"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"載入附件時無法傳送訊息。"</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"無法載入附件,請再試一次。"</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"網路尚未就緒,請再試一次。"</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"刪除文字"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"切換輸入的文字和數字"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"新增更多參與者"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"確認參與者"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"發起新對話"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"選取此項目"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"播放影片"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"參與者和選項"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"偵錯"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"參與者和選項"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"一般"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"這個對話的參與者"</string>
+    <string name="action_call" msgid="6596167921517350362">"進行通話"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"傳送簡訊"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"&lt;small&gt;透過 <xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;&lt;br&gt; 傳送訊息"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="other">傳送相片</item>
+      <item quantity="one">傳送相片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="other">傳送音訊</item>
+      <item quantity="one">傳送音訊</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="other">傳送影片</item>
+      <item quantity="one">傳送影片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="other">傳送聯絡人卡片</item>
+      <item quantity="one">傳送聯絡人卡片</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="other">傳送附件</item>
+      <item quantity="one">傳送附件</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="other">有 <xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> 個附件可隨郵件傳送</item>
+      <item quantity="one">有 1 個附件可隨郵件傳送</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"提供意見"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"前往 Google Play 商店查看"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"版本資訊"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"版本 %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"開放原始碼授權"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"通知"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"已達附件數量上限"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"無法載入附件。"</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"加到聯絡人?"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"新增聯絡人"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"主旨"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"主旨: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g>:<xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"正在載入聯絡人卡片"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"無法載入聯絡人卡片"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"查看聯絡人卡片"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> 位聯絡人</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> 位聯絡人</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"聯絡人卡片"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"生日"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"附註"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"轉寄郵件"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"回覆"</string>
+    <string name="plus_one" msgid="9010288417554932581">"還有 1 位參與者"</string>
+    <string name="plus_n" msgid="8961547034116059566">"還有 %d 位參與者"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"簡訊功能已停用"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"如要傳送訊息,請將「簡訊」設為預設的簡訊應用程式"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"將「簡訊」設為預設的簡訊應用程式"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"變更"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"如要接收訊息,請將「簡訊」設為預設的簡訊應用程式"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"尚未選取傳送簡訊時慣用的 SIM 卡"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"裝置擁有者不允許這個應用程式的要求。"</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"確定"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"對話參與者人數過多"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="other">聯絡人無效</item>
+      <item quantity="one">聯絡人無效</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"無法載入相機圖片"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"您: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"草稿"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"這裡會列出您發起的新對話"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"封存的對話會顯示在這裡"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"正在載入對話…"</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"圖片"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"音訊剪輯"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"影片"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"聯絡人卡片"</string>
+    <string name="mms_text" msgid="1528791558806015806">"多媒體訊息"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"復原"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"重試"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"輸入聯絡人名稱或電話號碼,即可開始傳送新訊息"</string>
+    <string name="action_block" msgid="9032076625645190136">"封鎖"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"封鎖 <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"解除封鎖 <xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"封鎖 <xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"您將持續接收來自這個號碼的訊息,但不會再收到通知。此對話將由系統封存。"</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"封鎖的聯絡人"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"解除封鎖"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"封鎖的聯絡人"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"選擇文件庫中的圖片"</string>
+    <string name="sending_message" msgid="6363584950085384929">"正在傳送訊息"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"訊息成功送出"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"行動數據已關閉。請檢查您的設定。"</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"飛航模式下無法傳送訊息"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"無法傳送訊息"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"訊息下載完成"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"行動數據已關閉。請檢查您的設定。"</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"在飛航模式下無法下載訊息"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"無法下載訊息"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"0"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"1"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"2"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"3"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"4"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"5"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"6"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"7"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"8"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"9"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"無法透過<xliff:g id="CARRIERNAME">%1$s</xliff:g>傳送訊息 (錯誤代碼:<xliff:g id="ERRORCODE">%2$d</xliff:g>)"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"無法透過不明行動通訊業者傳送訊息 (錯誤代碼:<xliff:g id="ERRORCODE">%1$d</xliff:g>)"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"轉寄:<xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"訊息未傳送:未在網路上啟用服務"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"無法傳送訊息:目的地位址無效"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"無法傳送訊息:訊息無效"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"無法傳送訊息:不支援的內容"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"無法傳送訊息:不支援的訊息"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"訊息未傳送:內容過大"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"新訊息"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"查看"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"圖片"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"找不到適用的應用程式"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"移除收件者"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"新訊息"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"取消"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"編輯存取點"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"未設定"</string>
+    <string name="apn_name" msgid="1572691851070894985">"名稱"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"多媒體訊息 Proxy"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"多媒體訊息通訊埠"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"APN 類型"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"刪除 APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"新增 APN"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"儲存"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"捨棄"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"名稱欄位不可留空。"</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"APN 不可留空。"</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"MCC 欄位的值必須為 3 碼。"</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"MNC 欄位的值必須為 2 或 3 碼。"</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"正在還原預設 APN 設定。"</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"重設為預設值"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"預設 APN 設定的重設程序已完成。"</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"未命名"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"存取點名稱"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"新增 APN"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"這位使用者無法修改存取點名稱設定"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"複製到剪貼簿?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"複製"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"傳送至 <xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"一般"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"進階"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"一般設定"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"進階設定"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"「<xliff:g id="SIM_NAME">%s</xliff:g>」SIM 卡"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"分別傳送簡訊給所有收件者 (如有任何回覆,只有您會收到)"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"傳送一則多媒體訊息給所有收件者"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"不明號碼"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"新訊息"</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"新訊息。"</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"SIM 卡選取器"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"已選取「<xliff:g id="SIM_0">%1$s</xliff:g>」,SIM 卡選取器"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"編輯主旨"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"選取 SIM 卡或編輯主旨"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"輕觸並按住即可錄製音訊"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"發起新對話"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"簡訊"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"訊息清單"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"簡訊"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"新訊息"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"會話群組清單"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"正在載入對話"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"正在載入訊息"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"查看更多對話"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"查看更多訊息"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"對話已刪除"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"已刪除對話。輕觸即可顯示其他「簡訊」對話"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"已封鎖"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"已解除封鎖"</string>
+    <string name="db_full" msgid="8459265782521418031">"儲存空間即將用盡,部分資料可能會遺失。"</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"選取附件"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"確認選取項目"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"選取了 <xliff:g id="COUNT">%d</xliff:g> 個附件"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"請移除一或多個附件,然後再試一次。"</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"您可以嘗試傳送訊息,但可能必須移除一或多個附件才能順利傳送。"</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"每則訊息只能傳送一部影片。請移除額外的影片,然後再試一次。"</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"「簡訊」無法載入附件。"</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"確定傳送"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"無法發起對話"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"已選取「<xliff:g id="SELECTED_SIM">%s</xliff:g>」"</string>
+</resources>
diff --git a/res/values-zu/arrays.xml b/res/values-zu/arrays.xml
new file mode 100644
index 0000000..50eafe1
--- /dev/null
+++ b/res/values-zu/arrays.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="empty_subject_strings">
+    <item msgid="8900116186849071724">"asikho isihloko"</item>
+    <item msgid="272485471009191934">"asikho isihloko"</item>
+  </string-array>
+  <string-array name="notification_reply_choices">
+    <item msgid="1875991048685328264">"Yebo"</item>
+    <item msgid="6049132459802288033">"Cha"</item>
+    <item msgid="3084376867445867895">"KULUNGILE"</item>
+    <item msgid="3155097332660174689">"Hehe"</item>
+    <item msgid="2611328818571146775">"Siyabonga"</item>
+    <item msgid="4881335087096496747">"Ngiyavuma"</item>
+    <item msgid="2422296858597420738">"I-Nice"</item>
+    <item msgid="4805581752819452687">"Ngisendleleni"</item>
+    <item msgid="4746700499431366214">"KULUNGILE, mangibuye kuwe emuva kwesikhathi"</item>
+    <item msgid="4342041517788201970">":)"</item>
+    <item msgid="7439437911747961187">":("</item>
+  </string-array>
+</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
new file mode 100644
index 0000000..0221bcd
--- /dev/null
+++ b/res/values-zu/strings.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="3062916848713424329">"Imilayezo"</string>
+    <string name="share_intent_label" msgid="6920483598866144717">"Imilayezo"</string>
+    <string name="share_intent_activity_label" msgid="2939454246983196756">"Khetha ingxoxo"</string>
+    <string name="action_settings" msgid="1329008122345201684">"Izilungiselelo"</string>
+    <string name="sendButtonContentDescription" msgid="8422114979691093956">"Thumela umlayezo"</string>
+    <string name="attachMediaButtonContentDescription" msgid="2758624209216276682">"Engeza okunamathiselwe kwi-imeyili"</string>
+    <string name="help_and_feedback_activity_label" msgid="8070710971014835182">"Usizo"</string>
+    <string name="welcome" msgid="2857560951820802321">"Siyakwamukela"</string>
+    <string name="skip" msgid="7238879696319945853">"Yeqa"</string>
+    <string name="next_with_arrow" msgid="2840729397885031655">"Okulandelayo &gt;"</string>
+    <string name="next" msgid="4496962051601713843">"Okulandelayo"</string>
+    <string name="exit" msgid="1905187380359981199">"Phuma"</string>
+    <string name="settings_with_arrow" msgid="8534633224579301342">"Izilungiselelo &gt;"</string>
+    <string name="settings" msgid="1045695083932447399">"Izilungiselelo"</string>
+    <string name="required_permissions_promo" msgid="3898014894175251590">"Ukulayeza kudinga imvume ku-SMS, ifoni noxhumana nabo."</string>
+    <string name="enable_permission_procedure" msgid="2778471831376319587">"Ungaguqula izimvume ku-Izilungiselelo &gt; Izinhlelo zokusebenza &gt; Isilayezi &gt; Izimvume."</string>
+    <string name="enable_permission_procedure_description" msgid="8672121020793945630">"Ungaguqula izimvume ku-Izilungiselelo, Izinhlelo zokusebenza, Isilayezi, Izimvume."</string>
+    <string name="contact_picker_frequents_tab_title" msgid="7157326165824706883">"Imvamisa"</string>
+    <string name="contact_picker_all_contacts_tab_title" msgid="1424746082040243161">"Bonke oxhumana nabo"</string>
+    <string name="contact_list_send_to_text" msgid="3167455944684758290">"Thumela ku-<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="mediapicker_cameraChooserDescription" msgid="8498255650058981250">"Thwebula izithombe noma ividiyo"</string>
+    <string name="mediapicker_galleryChooserDescription" msgid="1227741581156455777">"Khetha izithombe kusuka kule divayisi"</string>
+    <string name="mediapicker_audioChooserDescription" msgid="3660616501040372452">"Rekhoda umsindo"</string>
+    <string name="mediapicker_gallery_title" msgid="3169528536727885763">"Khetha isithombe"</string>
+    <string name="mediapicker_gallery_item_selected_content_description" msgid="2569545441879514283">"Imidiya ikhethiwe."</string>
+    <string name="mediapicker_gallery_item_unselected_content_description" msgid="40021674722525910">"Imidiya isuswe ukukhetha."</string>
+    <string name="mediapicker_gallery_title_selection" msgid="3621616141966436510">"<xliff:g id="COUNT">%d</xliff:g> okukhethiwe"</string>
+    <string name="mediapicker_gallery_image_item_description" msgid="8812237405495409901">"isithombe <xliff:g id="DATE">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g>"</string>
+    <string name="mediapicker_gallery_image_item_description_no_date" msgid="8142175029053370662">"Isithombe"</string>
+    <string name="mediapicker_audio_title" msgid="5455016591560739789">"Rekhoda umsindo"</string>
+    <string name="action_share" msgid="2143483844803153871">"Yaba"</string>
+    <string name="posted_just_now" msgid="6632467048088811568">"Khona manje"</string>
+    <string name="posted_now" msgid="867560789350406701">"Manje"</string>
+    <plurals name="num_minutes_ago" formatted="false" msgid="4085627474543076735">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> amaminithi</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> amaminithi</item>
+    </plurals>
+    <plurals name="num_hours_ago" formatted="false" msgid="8010868301590914325">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> amahora</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> amahora</item>
+    </plurals>
+    <plurals name="num_days_ago" formatted="false" msgid="8753803762044567843">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> izinsuku</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> izinsuku</item>
+    </plurals>
+    <plurals name="week_count" formatted="false" msgid="1301973226125551953">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> amaviki</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> amaviki</item>
+    </plurals>
+    <plurals name="month_count" formatted="false" msgid="4858515363324110232">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g>izinyanga</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>izinyanga</item>
+    </plurals>
+    <plurals name="year_count" formatted="false" msgid="4522546496183798317">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> iminyaka</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> iminyaka</item>
+    </plurals>
+    <string name="class_0_message_activity" msgid="4603850264073169854">"Umlayezo wesigaba esingu-0"</string>
+    <string name="save" msgid="5081141452059463572">"Londoloza"</string>
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text" msgid="8836401937872068406">"Idivayisi manje inesikhala esincane. Imilayezo izosusa ngokuzenzakalelayo imilayezo emidala ukukhulula isikhala."</string>
+    <string name="sms_storage_low_title" msgid="7985379565293259177">"Isikhala sesitoreji siyaphela"</string>
+    <string name="sms_storage_low_text" msgid="7036247475855447830">"Ukulayeza kungenzeka kungathumeli noma kungamukeli imilayezo kuze kube ukuthi isikhala esiningi sitholakala kudivayisi yakho."</string>
+    <string name="sms_storage_low_notification_ticker" msgid="2393739822170029830">"Isitoreji se-SMS esiphansi. Kungahle kudingeke ukuba ususe imilayezo."</string>
+    <string name="enter_phone_number_title" msgid="7263355879949248448">"Qinisekisa inombolo yakho yefoni"</string>
+    <string name="enter_phone_number_text" msgid="4539767473801195966">"Lesi sinyathelo sesikhathi esisodwa sizoqinisekisa ukuthi Ukulayeza kuzothumela imilayezo yakho yeqembu ngokufanelekile."</string>
+    <string name="enter_phone_number_hint" msgid="6242965213882272822">"Inombolo yefoni"</string>
+    <string name="delete_all_media" msgid="5549693176734564386">"Susa yonke imilayezo ngemidiya"</string>
+    <string name="delete_oldest_messages" msgid="9204277306804390707">"Susa imilayezo emidala kuno-<xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="auto_delete_oldest_messages" msgid="7766679943833404968">"Susa ngokuzenzakalelayo imilayezo emidala kuno-<xliff:g id="DURATION">%s</xliff:g>"</string>
+    <string name="ignore" msgid="7063392681130898793">"Ziba"</string>
+    <string name="delete_all_media_confirmation" msgid="4601960420953525559">"Susa yonke imilayezo ngemidiya?"</string>
+    <string name="delete_oldest_messages_confirmation" msgid="6172297718425265784">"Sula imilayezo emidala kuno-<xliff:g id="DURATION">%s</xliff:g>?"</string>
+    <string name="auto_delete_oldest_messages_confirmation" msgid="9071499976729145269">"Susa imilayezo emidala kuno-<xliff:g id="DURATION">%s</xliff:g> bese uvule ukususa ngokuzenzakalelayo?"</string>
+    <string name="incoming_text_sender_content_description" msgid="2481078288502342745">"<xliff:g id="SENDER">%s</xliff:g> uthe"</string>
+    <string name="outgoing_text_sender_content_description" msgid="3492116976256510272">"Wena uthe"</string>
+    <string name="incoming_sender_content_description" msgid="7512757244515303701">"Umlayezo ovela ku-<xliff:g id="SENDER">%s</xliff:g>"</string>
+    <string name="outgoing_sender_content_description" msgid="5983163141994434778">"Uthumele umlayezo"</string>
+    <string name="message_status_sending" msgid="3306260780518886107">"Iyathumela..."</string>
+    <string name="message_status_send_failed" msgid="5443627648028194631">"Akuthunyelwe. Thinta ukuze uzame futhi."</string>
+    <string name="message_status_send_retrying" msgid="650840088043267981">"Akuthunyelwe. Iyazama futhi…"</string>
+    <string name="message_status_resend" msgid="7718458416521355708">"Thumela kabusha noma susa"</string>
+    <string name="message_status_send_failed_emergency_number" msgid="1738854184297159948">"Sicela wenze ikholi yezwi kumasevisi wesimo esiphuthumayo. Umlayezo wakho wombhalo awukwazanga ukulethwa ngalesi sikhathi."</string>
+    <string name="message_status_failed" msgid="8009695010381848311">"Yehlulekile"</string>
+    <string name="message_title_manual_download" msgid="2761223322277801061">"Umlayezo we-MMS omusha ongalandwa"</string>
+    <string name="message_title_downloading" msgid="6418481644146460124">"Umlayezo we-MMS omusha"</string>
+    <string name="message_title_download_failed" msgid="3867223594671090459">"Ayikwazanga ukulanda."</string>
+    <string name="message_status_download_failed" msgid="7298035414448355842">"Thinta ukuze uzame futhi"</string>
+    <string name="message_status_download" msgid="6527275493954932656">"Thinta ukuze ulande"</string>
+    <string name="message_status_download_action" msgid="285219832844160">"Landa noma susa"</string>
+    <string name="message_status_downloading" msgid="7159807805159805428">"Iyalanda..."</string>
+    <string name="message_status_download_error" msgid="6957738686287397519">"Umlayezo uphelelwe yisikhathi noma awutholakali"</string>
+    <string name="mms_info" msgid="3402311750134118165">"usayizi: <xliff:g id="MESSAGESIZE">%1$s</xliff:g>, ukuphela kwesikhathi: <xliff:g id="MESSAGEEXPIRE">%2$s</xliff:g>"</string>
+    <string name="invalid_destination" msgid="8214889988397524630">"Ayikwazi ukuthumela. Umamukeli awuvumelekile."</string>
+    <string name="service_not_activated" msgid="5512558652052977817">"Isevisi ayisebenzi kunethiwekhi"</string>
+    <string name="service_network_problem" msgid="3765738916704013318">"Ayikwazanga ukuthumela ngenxa yenkinga yenethiwekhi"</string>
+    <string name="service_message_not_found" msgid="8350935323904134751">"Umlayezo uphelelwe yisikhathi noma awutholakali"</string>
+    <string name="no_subject" msgid="5587715902648568767">"(Asikho isihloko)"</string>
+    <string name="unknown_sender" msgid="504272434917395677">"Umthumeli ongaziwa"</string>
+    <string name="delivered_status_content_description" msgid="3433965196058436991">"Kuthunyelwe"</string>
+    <string name="dl_failure_notification" msgid="8744588243554006189">"Ayikwazanga ukulanda umlayezo we-<xliff:g id="SUBJECT">%1$s</xliff:g> kusuka ku-<xliff:g id="FROM">%2$s</xliff:g>."</string>
+    <string name="low_memory" msgid="5300743415198486619">"Ayikwazanga ukuqedela umsebenzi wemininingo egciniwe ngenxa yememori ephansi"</string>
+    <string name="notification_send_failures_line1_singular" msgid="6783835440207655217">"Umlayezo awuthunyelwanga"</string>
+    <string name="notification_send_failures_line1_plural" msgid="7228944748028969272">"Eminye imilayezo ayithunyelwe Ekulayezeni"</string>
+    <plurals name="notification_send_failures" formatted="false" msgid="6938919932879650691">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> imilayezo kwizingxoxo ezingu-<xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> imilayezo kwizingxoxo ezingu-<xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_download_failures_line1_singular" msgid="4424772073720626885">"Umlayezo awuzange ulandwe"</string>
+    <string name="notification_download_failures_line1_plural" msgid="1697982467160426345">"Eminye imilayezo ayilandiwe Ekulayezeni"</string>
+    <plurals name="notification_download_failures" formatted="false" msgid="5341490525457911398">
+      <item quantity="one"><xliff:g id="MESSAGES_1">%d</xliff:g> imilayezo kwizingxoxo ezingu-<xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+      <item quantity="other"><xliff:g id="MESSAGES_1">%d</xliff:g> imilayezo kwizingxoxo ezingu-<xliff:g id="CONVERSATIONS">%d</xliff:g></item>
+    </plurals>
+    <string name="notification_emergency_send_failure_line1" msgid="6311715277789488996">"Umlayezo oya ku-<xliff:g id="NUMBER">%1$s</xliff:g> awuthunyelwanga"</string>
+    <string name="notification_emergency_send_failure_line2" msgid="6461481033351036996">"Sicela uwenze ikholi yezwi kumasevisi wesimo esiphuthumayo. Umlayezo wakho wobhalo ku-<xliff:g id="NUMBER">%1$s</xliff:g> awukwazanga ukulethwa ngalesi sikhathi."</string>
+    <plurals name="notification_new_messages" formatted="false" msgid="610594317958128842">
+      <item quantity="one"><xliff:g id="MESSAGES">%d</xliff:g> imilayezo emisha</item>
+      <item quantity="other"><xliff:g id="MESSAGES">%d</xliff:g> imilayezo emisha</item>
+    </plurals>
+    <string name="start_conversation" msgid="7984539515326392793">"Qala"</string>
+    <string name="camera_error_opening" msgid="2739332294400420426">"Ikhamera ayitholakali"</string>
+    <string name="camera_error_unknown" msgid="4283956364220459608">"Ikhamera ayitholakali"</string>
+    <string name="camera_error_video_init_fail" msgid="994632067015578879">"Ukuthwebula kwevidiyo akutholakali"</string>
+    <string name="camera_error_storage_fail" msgid="5536300789483863989">"Ayikwazi ukulondoloza imidiya"</string>
+    <string name="camera_error_failure_taking_picture" msgid="4894133709734862250">"Ayikwazi ukuthatha isithombe"</string>
+    <string name="back" msgid="1477626055115561645">"Phindela emuva"</string>
+    <string name="action_menu_show_archived" msgid="1628518043533374868">"Okufakwe kungobo yomlando"</string>
+    <string name="action_delete" msgid="4076795795307486019">"Susa"</string>
+    <string name="action_archive" msgid="5437034800324083170">"Faka kungobo yomlando"</string>
+    <string name="action_unarchive" msgid="139681611159869493">"Ungafaki kungobo yomlando"</string>
+    <string name="action_notification_off" msgid="4823658797441716246">"Vala izaziso"</string>
+    <string name="action_notification_on" msgid="8244389452685364211">"Vula isaziso"</string>
+    <string name="action_add_contact" msgid="8248615862739848672">"Engeza oxhumana naye"</string>
+    <string name="action_download" msgid="7786338136368564146">"Landa"</string>
+    <string name="action_send" msgid="377635240181672039">"Thumela"</string>
+    <string name="action_delete_message" msgid="2728883749416365507">"Susa"</string>
+    <string name="delete_message_confirmation_dialog_title" msgid="4723834210275712001">"Susa lo mlayezo?"</string>
+    <string name="delete_message_confirmation_dialog_text" msgid="3952533622691031375">"Lesi senzo asikwazi ukuhlehliswa."</string>
+    <string name="delete_message_confirmation_button" msgid="3888584614972573382">"Susa"</string>
+    <plurals name="delete_conversations_confirmation_dialog_title" formatted="false" msgid="2285567882353326800">
+      <item quantity="one">Susa lezi zingxoxo?</item>
+      <item quantity="other">Susa lezi zingxoxo?</item>
+    </plurals>
+    <string name="delete_conversation_confirmation_button" msgid="744574085809600863">"Susa"</string>
+    <string name="delete_conversation_decline_button" msgid="5470021965641900456">"Khansela"</string>
+    <string name="recipient_hint" msgid="1819710673158265515">"Ku-"</string>
+    <string name="action_multiselect" msgid="1219683118692013380">"Khetha izithombe eziningi"</string>
+    <string name="action_confirm_multiselect" msgid="8283370294120913166">"Qinisekisa ukukhetha"</string>
+    <string name="attachment_more_items" msgid="2861573099241369958">"+<xliff:g id="COUNT">%d</xliff:g>"</string>
+    <string name="audio_recording_start_failed" msgid="4442450764642560851">"Ayikwazi ukurekhoda umsindo. Zama futhi."</string>
+    <string name="audio_recording_replay_failed" msgid="3585760856463273828">"Ayikwazi ukudlala umsindo. Zama futhi."</string>
+    <string name="audio_recording_error" msgid="7762310055059024872">"Ayikwazanga ukulondoloza umsindo. Zama futhi."</string>
+    <string name="audio_picker_hint_text" msgid="6986250080467111491">"Thinta bese ubambe"</string>
+    <string name="enumeration_comma" msgid="7032804261692931808">", "</string>
+    <string name="notification_separator" msgid="3472521786709813414">"  "</string>
+    <string name="notification_ticker_separator" msgid="2027929074008933906">": "</string>
+    <string name="notification_space_separator" msgid="9007689386066977972">"  "</string>
+    <string name="notification_picture" msgid="1176665337098921822">"Isithombe"</string>
+    <string name="notification_audio" msgid="5926581589398218150">"Isiqeshana somsindo"</string>
+    <string name="notification_video" msgid="4331423498662606204">"Ividiyo"</string>
+    <string name="notification_vcard" msgid="7658061674440552878">"Ikhadi loxhumana naye"</string>
+    <string name="notification_download_mms" msgid="6206807985355359528">"Landa"</string>
+    <string name="notification_reply_via_sms" msgid="6990127304684161722">"Phendula nge-SMS"</string>
+    <string name="notification_reply_via_mms" msgid="6706012871186064035">"Phendula nge-MMS"</string>
+    <string name="notification_reply_prompt" msgid="1836023392294480241">"Phendula"</string>
+    <plurals name="wearable_participant_count" formatted="false" msgid="3037889420270036143">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> ababambiqhaza</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ababambiqhaza</item>
+    </plurals>
+    <string name="unknown_self_participant" msgid="3186565052350548852">"Mina"</string>
+    <string name="blocked_toast_message" msgid="7903364256385612569">"Oxhumana naye uvinjiwe futhi wafakwa kungobo yomlando"</string>
+    <string name="unblocked_toast_message" msgid="4927617874263586622">"Oxhumana naye uvulelwe futhi wakhishwa kungobo yomlando"</string>
+    <string name="archived_toast_message" msgid="8109348891515322512">"<xliff:g id="COUNT">%d</xliff:g> kufakwe kungobo yomlando"</string>
+    <string name="unarchived_toast_message" msgid="5010777423084203833">"<xliff:g id="COUNT">%d</xliff:g> kukhishwe kungobo yomlando"</string>
+    <string name="notification_off_toast_message" msgid="5203458459139408265">"Izaziso zivaliwe"</string>
+    <string name="notification_on_toast_message" msgid="1240626023754746310">"Izaziso zivuliwe"</string>
+    <string name="toast_after_setting_default_sms_app_for_message_send" msgid="2767997591700713113">"Konke kusethiwe. Thinta u-Thumela futhi."</string>
+    <string name="toast_after_setting_default_sms_app" msgid="2923745971897322476">"Ukulayeza kusethwe ngempumelelo njengohlelo lokusebenza oluzenzakalelayo lwe-SMS."</string>
+    <plurals name="attachment_preview_close_content_description" formatted="false" msgid="5631719319690969981">
+      <item quantity="one">Lahla okunamathiselwe</item>
+      <item quantity="other">Lahla okunamathiselwe</item>
+    </plurals>
+    <string name="audio_attachment_content_description" msgid="499334244765270108">"Ukunamathiselwa komsindo"</string>
+    <string name="audio_play_content_description" msgid="4932509227281251607">"Dala okunamathiselwe komsindo"</string>
+    <string name="audio_pause_content_description" msgid="7578169887065513701">"Misa isikhashana"</string>
+    <string name="incoming_message_announcement" msgid="6369259405539452011">"Umlayezo kusukela ku-<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_failed_message_prefix" msgid="6985644411445605747">"Umlayezo ohlulekile ophuma ku-<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_incoming_successful_message_prefix" msgid="6190814597935995703">"Umlayezo ophuma ku-<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_draft_message_prefix" msgid="8721053088385740646">"Umlayezo ongathunyelwe ku-<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_sending_message_prefix" msgid="3929653530203574220">"Ithumela umlayezo ku-<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_failed_message_prefix" msgid="7194065651879454314">"Umlayezo ohlulekile oya ku-<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="one_on_one_outgoing_successful_message_prefix" msgid="7128492863867327814">"Umlayezo oya ku-<xliff:g id="CONTACT">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_incoming_failed_message_prefix" msgid="7085805237707481779">"Umlayezo ohlulekile kusukela ku-<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_incoming_successful_message_prefix" msgid="7248506967059447054">"Umlayezo ophuma ku-<xliff:g id="SENDER">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>. <xliff:g id="GROUPINFO">%4$s</xliff:g>."</string>
+    <string name="group_outgoing_draft_message_prefix" msgid="1655013812805454648">"Umlayezo ongathunyelwe ku-<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_sending_message_prefix" msgid="7636874745414695556">"Ithumela umlayezo ku-<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_failed_message_prefix" msgid="5059983340377901592">"Umlayezo ohlulekile oya ku-<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="group_outgoing_successful_message_prefix" msgid="1593702642852987920">"Umlayezo oya ku-<xliff:g id="GROUP">%1$s</xliff:g>: <xliff:g id="MESSAGE">%2$s</xliff:g>. Isikhathi: <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="failed_message_content_description" msgid="7047161648867054936">"Umlayezo ohlulekile. Thinta ukuze uphinde uzame."</string>
+    <string name="group_conversation_description" msgid="2339270924401184182">"Ingxoxo no-<xliff:g id="PARTICIPANTS">%s</xliff:g>"</string>
+    <string name="delete_subject_content_description" msgid="8910749398836396698">"Sula isihloko"</string>
+    <string name="camera_switch_to_video_mode" msgid="2926868205952641428">"Thwebula ividiyo"</string>
+    <string name="camera_switch_to_still_mode" msgid="4419617715199157958">"Thwebula isithombe esimile"</string>
+    <string name="camera_take_picture" msgid="2573317952200799489">"Thatha isithombe"</string>
+    <string name="camera_start_recording" msgid="1736478301191221786">"Qala ukuqopha ividiyo"</string>
+    <string name="camera_switch_full_screen" msgid="6156039742035097276">"Shintshela kukhamela yesikrini esigcwele"</string>
+    <string name="camera_switch_camera_facing" msgid="1566112129296559159">"Shintsha phakathi kwekhamera yaphambilini neyasemuva"</string>
+    <string name="camera_stop_recording" msgid="5331592576107271152">"Misa ukurekhoda uphinde ushumeke ividiyo"</string>
+    <string name="camera_cancel_recording" msgid="6431544304743145818">"Misa ukurekhoda amavidiyo"</string>
+    <string name="photo_view_activity_title" msgid="6556006393051918135">"Ilayeza izithombe"</string>
+    <plurals name="photos_saved_to_album" formatted="false" msgid="7529478299745446838">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> izithombe zilondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> izithombe zilondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="videos_saved_to_album" formatted="false" msgid="6821121808257576788">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> amavidiyo alondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> amavidiyo alondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album" formatted="false" msgid="8407480699515308929">
+      <item quantity="one"><xliff:g id="QUANTITY_2">%d</xliff:g> okunamathiselwe kulondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_2">%d</xliff:g> okunamathiselwe kulondolozwe ku-albhamu \"<xliff:g id="ALBUMNAME_3">%s</xliff:g>\"</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads" formatted="false" msgid="1886864019411801995">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> Okunamathiselwe kulondolozwe kokuthi \"Okulandiwe\"</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> Okunamathiselwe kulondolozwe kokuthi \"Okulandiwe\"</item>
+    </plurals>
+    <plurals name="attachments_saved" formatted="false" msgid="6925000482183379648">
+      <item quantity="one"><xliff:g id="QUANTITY_1">%d</xliff:g> okunamathiselwe kulondoloziwe</item>
+      <item quantity="other"><xliff:g id="QUANTITY_1">%d</xliff:g> okunamathiselwe kulondoloziwe</item>
+    </plurals>
+    <plurals name="attachment_save_error" formatted="false" msgid="2068837227090109833">
+      <item quantity="one">Ayikwazanga ukulondoloza okunamathiselwe okungu-<xliff:g id="QUANTITY_1">%d</xliff:g></item>
+      <item quantity="other">Ayikwazanga ukulondoloza okunamathiselwe okungu-<xliff:g id="QUANTITY_1">%d</xliff:g></item>
+    </plurals>
+    <string name="attachment_file_description" msgid="3056972820372291694">"Ilondoloze okunamathiselwa kwe-MMS"</string>
+    <string name="settings_activity_title" msgid="3380813834835334258">"Izilungiselelo"</string>
+    <string name="archived_activity_title" msgid="4738212324460451188">"Okufakwe kungobo yomlando"</string>
+    <string name="action_close" msgid="1840519376200478419">"Vala"</string>
+    <string name="mms_messaging_category_pref_title" msgid="4816815152658525660">"I-MMS"</string>
+    <string name="advanced_category_pref_title" msgid="6411454224069259687">"Okuthuthukisiwe"</string>
+    <string name="debug_category_pref_title" msgid="8765138968242505061">"Lungisa iphutha"</string>
+    <string name="notifications_enabled_pref_title" msgid="4127288731844373795">"Izaziso"</string>
+    <string name="notification_sound_pref_title" msgid="3685506528957337849">"Umsindo"</string>
+    <string name="silent_ringtone" msgid="8073534180322059814">"Thulile"</string>
+    <string name="notification_vibrate_pref_title" msgid="6668564570045187390">"Dlidlizela"</string>
+    <string name="blocked_pref_title" msgid="2560554234438548817">"Ivinjelwe"</string>
+    <string name="delivery_reports_pref_title" msgid="5115727259825309087">"Imibiko yokulethwa kwe-SMS"</string>
+    <string name="delivery_reports_pref_summary" msgid="4272502420621500421">"Cela umbiko wokuthumela we-SMS ngayinye oyithumelayo"</string>
+    <string name="auto_retrieve_mms_pref_title" msgid="1316094876978218980">"Thola ngokuzenzakalekayo"</string>
+    <string name="auto_retrieve_mms_pref_summary" msgid="2253902455786205335">"Thola ngokuzenzakalela imilayezo ye-MMS"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_title" msgid="2918775628609759349">"Ukuthola okuzenzakalelayo kokuzula"</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary" msgid="7347177867673486983">"Thola ngokuzenzakalela i-MMS uma uzula"</string>
+    <string name="group_mms_pref_title" msgid="6553612309209383106">"Imilayezo yeqembu"</string>
+    <string name="group_mms_pref_summary" msgid="3758710015912690629">"Sebenzisa i-MMS ukuthumela umlayezo owodwa uma kunabamukeli abaningi"</string>
+    <string name="sms_disabled_pref_title" msgid="6352764741524717132">"Uhlelo lokusebenza oluzenzakalelayo le-SMS"</string>
+    <string name="sms_enabled_pref_title" msgid="2961457081888153323">"Uhlelo lokusebenza oluzenzakalelayo le-SMS"</string>
+    <!-- no translation found for default_sms_app (3907546126124760465) -->
+    <skip />
+    <string name="mms_phone_number_pref_title" msgid="5445275222817760638">"Inombolo yakho yefoni"</string>
+    <string name="unknown_phone_number_pref_display_value" msgid="5191326096424554297">"Akwaziwa"</string>
+    <string name="send_sound_pref_title" msgid="6284747469983942370">"Imisindo yemilayezo ephumayo"</string>
+    <string name="dump_sms_pref_title" msgid="4057657151746557281">"Lahla i-SMS"</string>
+    <string name="dump_sms_pref_summary" msgid="3694039770323225329">"Lahla idatha engahluziwe ye-SMS etholiwe kufayela lesitoreji sangaphandle"</string>
+    <string name="dump_mms_pref_title" msgid="6699074152055891680">"Lahla i-MMS"</string>
+    <string name="dump_mms_pref_summary" msgid="7901698352188687659">"Lahla idatha engahluziwe ye-MMS etholiwe kufayela lesitoreji sangaphandle"</string>
+    <string name="wireless_alerts_title" msgid="8218925605166939654">"Izexwayiso ezingenantambo"</string>
+    <string name="message_context_menu_title" msgid="5036023289586457642">"Izinketho zomlayezo"</string>
+    <string name="message_context_menu_copy_text" msgid="8241684826917957666">"Kopisha umbhalo"</string>
+    <string name="message_context_menu_view_details" msgid="2077089491219912840">"Buka imininingwane"</string>
+    <string name="message_context_menu_delete_message" msgid="4924354182554857475">"Susa"</string>
+    <string name="message_context_menu_forward_message" msgid="4848326950037554575">"Dlulisela phambili"</string>
+    <string name="message_details_title" msgid="8451487656255395372">"Imininingwane yomlayezo"</string>
+    <string name="message_type_label" msgid="6442873901113487978">"Uhlobo: "</string>
+    <string name="text_message" msgid="7415419755252205721">"Umlayezo wombhalo"</string>
+    <string name="multimedia_message" msgid="2199989099980111684">"Umlayezo wokuxhumana okuxubile"</string>
+    <string name="from_label" msgid="1947831848146564875">"Kusuka ku: "</string>
+    <string name="to_address_label" msgid="1816631887533235762">"Ku: "</string>
+    <string name="sent_label" msgid="5186286057597137301">"Okuthunyelwe: "</string>
+    <string name="received_label" msgid="4442494712757995203">"Okutholiwe: "</string>
+    <string name="subject_label" msgid="1887378451808609152">"Isihloko: "</string>
+    <string name="message_size_label" msgid="8840394477993741203">"Usayizi: "</string>
+    <string name="priority_label" msgid="5029073794896222902">"Okubalulekile: "</string>
+    <string name="sim_label" msgid="2706003016582772108">"SIM: "</string>
+    <string name="priority_high" msgid="728836357310908368">"Okuphezulu"</string>
+    <string name="priority_normal" msgid="8918221917628753075">"Okuvamile"</string>
+    <string name="priority_low" msgid="7398724779026801851">"Okuphansi"</string>
+    <string name="sim_slot_identifier" msgid="5934005977415016295">"SIM <xliff:g id="SIM_SLOT_NUMBER">%s</xliff:g>"</string>
+    <string name="hidden_sender_address" msgid="5054789216911282696">"Ikheli lomthumeli lifihliwe"</string>
+    <string name="cant_send_message_while_loading_attachments" msgid="4301887223941009907">"Ayikwazi ukuthumela umlayezo ngenkathi ilayisha izinamathiseli."</string>
+    <string name="fail_to_load_attachment" msgid="412233184776827353">"Ayikwazi ukulayisha okunamathiselwe. Zama futhi."</string>
+    <string name="cant_send_message_without_active_subscription" msgid="7130532514190813716">"Inethiwekhi ayilungile. Zama futhi."</string>
+    <string name="chips_text_delete_button_content_description" msgid="123760854728616068">"Susa umbhalo"</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description" msgid="1403198418131594073">"Shintsha phakathi kokufaka umbhalo nezinombolo"</string>
+    <string name="add_more_participants_button_content_description" msgid="12460574490350327">"Engeza ababambiqhaza abaningi"</string>
+    <string name="confrim_participants_button_content_description" msgid="7473740533133798616">"Qinisekisa ababambiqhazi"</string>
+    <string name="start_new_conversation" msgid="3924471215595992758">"Qala ingxoxo entsha"</string>
+    <string name="gallery_checkbox_content_description" msgid="2503122727700475428">"Khetha into"</string>
+    <string name="video_thumbnail_view_play_button_content_description" msgid="3506938388391260811">"Dlala ividiyo"</string>
+    <string name="action_people_and_options" msgid="2748020184252106661">"Abantu nezinketho"</string>
+    <string name="action_debug_options" msgid="2440658410677323714">"Lungisa iphutha"</string>
+    <string name="people_and_options_activity_title" msgid="5443749025829291736">"Abantu nezinketho"</string>
+    <string name="general_settings_title" msgid="4465312111301728995">"Okuvamile"</string>
+    <string name="participant_list_title" msgid="8624855187574757110">"Abantu kule ngxoxo"</string>
+    <string name="action_call" msgid="6596167921517350362">"Yenza ikholi"</string>
+    <string name="compose_message_view_hint_text" msgid="5214836453231753054">"Thumela umlayezo"</string>
+    <string name="compose_message_view_hint_text_multi_sim" msgid="2829154383848677160">"Thumela umlayezo&lt;br/&gt;&lt;small&gt;kusukela ku-<xliff:g id="SIM_NAME">%s</xliff:g>&lt;/small&gt;"</string>
+    <plurals name="compose_message_view_hint_text_photo" formatted="false" msgid="8937589900456604618">
+      <item quantity="one">Thumela izithombe</item>
+      <item quantity="other">Thumela izithombe</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_audio" formatted="false" msgid="5934090345811195170">
+      <item quantity="one">Thumela imisindo</item>
+      <item quantity="other">Thumela imisindo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_video" formatted="false" msgid="9188048653766960507">
+      <item quantity="one">Thumela amavidiyo</item>
+      <item quantity="other">Thumela amavidiyo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_vcard" formatted="false" msgid="933064969858631242">
+      <item quantity="one">Thumela amakhadi oxhumana nabo</item>
+      <item quantity="other">Thumela amakhadi oxhumana nabo</item>
+    </plurals>
+    <plurals name="compose_message_view_hint_text_attachments" formatted="false" msgid="1778518334602418000">
+      <item quantity="one">Thumela okunamathiselwe</item>
+      <item quantity="other">Thumela okunamathiselwe</item>
+    </plurals>
+    <plurals name="attachment_changed_accessibility_announcement" formatted="false" msgid="5592871135747616108">
+      <item quantity="one"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> okunamathiselwe  kukulungele ukuthunyelwa</item>
+      <item quantity="other"><xliff:g id="ATTACHMENT_COUNT">%d</xliff:g> okunamathiselwe  kukulungele ukuthunyelwa</item>
+    </plurals>
+    <string name="menu_send_feedback" msgid="479412726781330278">"Thumela impendulo"</string>
+    <string name="menu_view_in_store" msgid="3792488955421628684">"Buka ku-Google Play Isitolo"</string>
+    <string name="menu_version_info" msgid="6122616816253404821">"Ulwazi lwenguqulo"</string>
+    <string name="subtitle_format_for_version_number" msgid="446082111129170749">"Inguqulo %1$s"</string>
+    <string name="menu_license" msgid="1157954180701135202">"Amalayisense womthombo ovulekile"</string>
+    <string name="notifications_enabled_conversation_pref_title" msgid="1492686092760478206">"Izaziso"</string>
+    <string name="mms_attachment_limit_reached" msgid="8303890455085643301">"Kufinyelelwe kumkhawulo wokunamathiselwe kwi-imeyili"</string>
+    <string name="mms_attachment_load_failed" msgid="5697191348996648727">"Ihlulekile ukulayisha okunamathiselwe kwi-imeyili."</string>
+    <string name="add_contact_confirmation_dialog_title" msgid="1898307408816625598">"Engeza oxhumana nabo"</string>
+    <string name="add_contact_confirmation" msgid="1479380805406328264">"Engeza oxhumana naye"</string>
+    <string name="compose_message_view_subject_hint_text" msgid="6076616675845705660">"Isihloko"</string>
+    <string name="conversation_message_view_subject_text" msgid="5634274498769555505">"Isihloko: "</string>
+    <string name="notification_subject" msgid="5229975483160300625">"<xliff:g id="SUBJECT_LABEL">%1$s</xliff:g><xliff:g id="MESSAGETEXT">%2$s</xliff:g>"</string>
+    <string name="loading_vcard" msgid="3961520941271265083">"Ilayisha ikhadi loxhumana naye"</string>
+    <string name="failed_loading_vcard" msgid="7711070643740368402">"Ayikwazi ukulayisha ikhadi loxhumana naye"</string>
+    <string name="vcard_tap_hint" msgid="4940284329175200952">"Buka ikhadi lokuxhumana"</string>
+    <plurals name="vcard_multiple_display_name" formatted="false" msgid="2884224435488996028">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> oxhumana nabo</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> oxhumana nabo</item>
+    </plurals>
+    <string name="vcard_detail_activity_title" msgid="591540798943754991">"Amakhadi wokuxhumana"</string>
+    <string name="vcard_detail_birthday_label" msgid="7196021537629120021">"Usuku lokuzalwa"</string>
+    <string name="vcard_detail_notes_label" msgid="6104179009509800126">"Amanothi"</string>
+    <string name="forward_message_activity_title" msgid="4689730643900226699">"Dlulisa umlayezo"</string>
+    <string name="reply_activity_title" msgid="2967630094609648609">"Phendula"</string>
+    <string name="plus_one" msgid="9010288417554932581">"+1"</string>
+    <string name="plus_n" msgid="8961547034116059566">"+%d"</string>
+    <string name="sms_disabled" msgid="4988773371061820432">"I-SMS ikhutshaziwe"</string>
+    <string name="requires_default_sms_app_to_send" msgid="171048611973157166">"Ukuze uthumele, setha Ukulayeza njengohlelo lwakho lokusebenza oluzenzakalelayo lwe-SMS"</string>
+    <string name="requires_default_sms_app" msgid="7477365167876194810">"Setha Ukulayeza njengohlelo lokusebenza oluzenzakalelayo lwe-SMS"</string>
+    <string name="requires_default_sms_change_button" msgid="6717443481161057941">"Guqula"</string>
+    <string name="recommend_set_default_sms_app" msgid="7769636305626277844">"Ukuze uthole imilayezo, setha Ukulayeza njengohlelo lokusebenza oluzenzakalelayo lwe-SMS"</string>
+    <string name="no_preferred_sim_selected" msgid="8583927728936521140">"Ayikho i-SIM ethandwayo ekhethiwe yokuthumela imilayezo ye-SMS"</string>
+    <string name="requires_sms_permissions_message" msgid="2179684358095980506">"Lolu hlelo lokusebenza aluvumelekile umnikazi wedivayisi."</string>
+    <string name="requires_sms_permissions_close_button" msgid="8601569832171759435">"KULUNGILE"</string>
+    <string name="too_many_participants" msgid="5857516461210932810">"Ababambiqhaza abaningi kakhulu engxoxweni"</string>
+    <plurals name="add_invalid_contact_error" formatted="false" msgid="782438833843363189">
+      <item quantity="one">Oxhumana nabo abangavumelekile</item>
+      <item quantity="other">Oxhumana nabo abangavumelekile</item>
+    </plurals>
+    <string name="camera_media_failure" msgid="6532763214546593687">"Ayikwazanga ukulayisha isithombe sekhamera"</string>
+    <string name="conversation_list_item_view_sent_from_you_prefix" msgid="1735457801737604211">"Wena: "</string>
+    <string name="conversation_list_item_view_sent_from_other_prefix" msgid="9202622757034736175">"<xliff:g id="FIRSTNAMEOFSENDER">%s</xliff:g>: "</string>
+    <string name="conversation_list_item_view_draft_message" msgid="3592923997082845035">"Okusalungiswa"</string>
+    <string name="conversation_list_empty_text" msgid="7505706551294769667">"Uma uqala ingxoxo entsha, uzoyibona kuhlu lapha"</string>
+    <string name="archived_conversation_list_empty_text" msgid="6109126963298874571">"Izingxoxo ezifakwe kungobo yomlando zivela lapha"</string>
+    <string name="conversation_list_first_sync_text" msgid="3749751291444609993">"Ilayisha izingxoxo..."</string>
+    <string name="conversation_list_snippet_picture" msgid="5326960910088541826">"Isithombe"</string>
+    <string name="conversation_list_snippet_audio_clip" msgid="7894183429890407387">"Isiqeshana somsindo"</string>
+    <string name="conversation_list_snippet_video" msgid="7101059507173671233">"Ividiyo"</string>
+    <string name="conversation_list_snippet_vcard" msgid="5004837959112452394">"Ikhadi loxhumana naye"</string>
+    <string name="mms_text" msgid="1528791558806015806">"i-MMS"</string>
+    <string name="snack_bar_undo" msgid="4523395751563700308">"Hlehlisa"</string>
+    <string name="snack_bar_retry" msgid="7140970704902570020">"Zama futhi"</string>
+    <string name="contact_list_empty_text" msgid="1036353827229041942">"Faka igama loxhumana naye noma inombolo eyefoni ukuze uqale umlayezo omusha"</string>
+    <string name="action_block" msgid="9032076625645190136">"Vimba"</string>
+    <string name="block_contact_title" msgid="6968382557194643329">"Vimbela u-<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="unblock_contact_title" msgid="4719854710980066596">"Susa ukuvimbela u-<xliff:g id="DESTINATION">%s</xliff:g>"</string>
+    <string name="block_confirmation_title" msgid="8288283455512985682">"Vumba e-<xliff:g id="DESTINATION">%s</xliff:g>?"</string>
+    <string name="block_confirmation_message" msgid="185429978461824228">"Uzoqhubeka nokuthola imilayezo kusuka kule nombolo kodwa ngeke usaziswa. Le ngxoxo izofakwa kungobo yomlando."</string>
+    <string name="blocked_contacts_title" msgid="7709164518967312281">"Oxhumana nabo abavinjiwe"</string>
+    <string name="tap_to_unblock_message" msgid="1284284144816901647">"VULELA"</string>
+    <string name="view_blocked_contacts_title" msgid="7417596291306885403">"Oxhumana nabo abavinjiwe"</string>
+    <string name="pick_image_from_document_library_content_description" msgid="132845956503874378">"Khetha isithombe kusuka kulabhulali yedokhumenti"</string>
+    <string name="sending_message" msgid="6363584950085384929">"Ithumela umlayezo"</string>
+    <string name="send_message_success" msgid="4088006261869323324">"Umyalezo uthunyelwe"</string>
+    <string name="send_message_failure_no_data" msgid="7404080465234559802">"Idatha yeselula ivaliwe. Hlola izilungiselelo zakho."</string>
+    <string name="send_message_failure_airplane_mode" msgid="3966519541237053840">"Ayikwazi ukuthumela imilayezo kumodi yendiza"</string>
+    <string name="send_message_failure" msgid="5273892629851390023">"Umlayezo awukwazanga ukuthunyelwa"</string>
+    <string name="download_message_success" msgid="3514921076616367225">"Umlayezo ulandiwe"</string>
+    <string name="download_message_failure_no_data" msgid="6830055949399088532">"Idatha yeselula ivaliwe. Hlola izilungiselelo zakho."</string>
+    <string name="download_message_failure_airplane_mode" msgid="6752478540984118382">"Ayikwazi ukulanda imilayezo kumodi ye-Ndiza"</string>
+    <string name="download_message_failure" msgid="635370887537738004">"Umlayezo awukwazanga ukulandwa"</string>
+    <string name="content_description_for_number_zero" msgid="7992301592202897868">"Iqanda"</string>
+    <string name="content_description_for_number_one" msgid="3886554185135150473">"Kunye"</string>
+    <string name="content_description_for_number_two" msgid="1562486479385891146">"Kubili"</string>
+    <string name="content_description_for_number_three" msgid="8471442614073144385">"Kuthathu"</string>
+    <string name="content_description_for_number_four" msgid="7515917522043407213">"Kune"</string>
+    <string name="content_description_for_number_five" msgid="8078774905490022978">"Kuhlanu"</string>
+    <string name="content_description_for_number_six" msgid="9192012772645396654">"Isithupha"</string>
+    <string name="content_description_for_number_seven" msgid="5870011338757220060">"Yisikhombisa"</string>
+    <string name="content_description_for_number_eight" msgid="7078061834874737466">"Isishiyagalombili"</string>
+    <string name="content_description_for_number_nine" msgid="4276787959475295232">"Isishiyagalolunye"</string>
+    <string name="carrier_send_error" msgid="3796492439123251453">"Ayikwazi ukuthumela umlayezo nge-<xliff:g id="CARRIERNAME">%1$s</xliff:g>, iphutha <xliff:g id="ERRORCODE">%2$d</xliff:g>"</string>
+    <string name="carrier_send_error_unknown_carrier" msgid="1210665032244425938">"Ayikwazi ukuthumela umlayezo ngenkampani yenethiwekhi engaziwa, iphutha <xliff:g id="ERRORCODE">%1$d</xliff:g>"</string>
+    <string name="message_fwd" msgid="2144370964507743673">"Dlulisa: <xliff:g id="SUBJECT">%s</xliff:g>"</string>
+    <string name="mms_failure_outgoing_service" msgid="4662217039143124592">"Umlayezo awuthunyelwe: isevisi ayisebenzi kunethiwekhi"</string>
+    <string name="mms_failure_outgoing_address" msgid="6212773250215580849">"Umlayezo awuthunyelwe: ikheli lendawo okuya kulo alivumelekile"</string>
+    <string name="mms_failure_outgoing_corrupt" msgid="6132734324976690436">"Umlayezo awuthunyelwe: umlayezo ongavumelekile"</string>
+    <string name="mms_failure_outgoing_content" msgid="919220273446626565">"Umlayezo awuthunyelwe: okuqukethwe okungasekelwe"</string>
+    <string name="mms_failure_outgoing_unsupported" msgid="2614377585077448979">"Umlayezo awuthunyelwe: umlayezo ongasekelwe"</string>
+    <string name="mms_failure_outgoing_too_large" msgid="3917966922000717407">"Umlayezo awuthunyelwe: mkhulu kakhulu"</string>
+    <string name="in_conversation_notify_new_message_text" msgid="8207541514656839042">"Umlayezo omusha"</string>
+    <string name="in_conversation_notify_new_message_action" msgid="7311780674392006753">"Buka"</string>
+    <string name="message_image_content_description" msgid="621604138442762130">"Isithombe"</string>
+    <string name="activity_not_found_message" msgid="2355153262520375529">"Ayikwazanga ukuthola uhlelo lokusebenza olufanelekile"</string>
+    <string name="chips_delete_content_description" msgid="4655699207140895492">"Susa umamukeli"</string>
+    <string name="share_new_message" msgid="2135955613694195483">"Umlayezo omusha"</string>
+    <string name="share_cancel" msgid="6666929391961668469">"Khansela"</string>
+    <string name="apn_edit" msgid="2134993966166435648">"Hlela iphoyinti lokufinyelela"</string>
+    <string name="apn_not_set" msgid="463728018542184151">"Ayisethiwe"</string>
+    <string name="apn_name" msgid="1572691851070894985">"Igama"</string>
+    <string name="apn_apn" msgid="1197541953189716999">"I-APN"</string>
+    <string name="apn_mmsc" msgid="2584154739440281747">"I-MMSC"</string>
+    <string name="apn_mms_proxy" msgid="4343743931563107100">"Ummeleli we-MMS"</string>
+    <string name="apn_mms_port" msgid="6181253508404620479">"Imbobo ye-MMS"</string>
+    <string name="apn_mcc" msgid="8102023058623950736">"I-MCC"</string>
+    <string name="apn_mnc" msgid="1372437523197012866">"I-MNC"</string>
+    <string name="apn_type" msgid="8409755622399386584">"Uhlobo lwe-APN"</string>
+    <string name="menu_delete_apn" msgid="4947391038600888284">"Susa i-APN"</string>
+    <string name="menu_new_apn" msgid="1564461309350814037">"I-APN Entsha"</string>
+    <string name="menu_save_apn" msgid="5445335896951613691">"Londoloza"</string>
+    <string name="menu_discard_apn_change" msgid="310569150407968648">"Lahla"</string>
+    <string name="error_apn_name_empty" msgid="7770363665690646716">"Igama lenkambu akumele lingabi nalutho."</string>
+    <string name="error_apn_empty" msgid="6799644880052534839">"I-APN akumele ingabi nalutho."</string>
+    <string name="error_mcc_not3" msgid="3693788817630985838">"Inkundla ye-MCC kumele ibe namadijithi angu-3."</string>
+    <string name="error_mnc_not23" msgid="3726130455168743554">"Inkambu ye-MNC kumelwe ibe amadijithi angu-2 noma angu-3."</string>
+    <string name="restore_default_apn" msgid="7180447255249638396">"Ibuyisela izilungiselelo ze-APN zokuzenzakalelayo."</string>
+    <string name="menu_restore_default_apn" msgid="6342935229867973523">"Setha kabusha kube ngokuzenzakalelayo"</string>
+    <string name="restore_default_apn_completed" msgid="7421687541468349715">"Izilungiselelo ze-APN zokusethwa kabusha okuzenzakalelayo ziqediwe."</string>
+    <string name="untitled_apn" msgid="3110576506102839465">"Akunasihloko"</string>
+    <string name="sms_apns_title" msgid="1351513141821300879">"Amagama wephoyinti lokufinyelela"</string>
+    <string name="apn_settings" msgid="3179955111000379490">"Ama-APN"</string>
+    <string name="menu_new" msgid="8286285392706532511">"I-APN Entsha"</string>
+    <string name="apn_settings_not_available" msgid="5136389328322585717">"Izilungiselelo zegama le-Phoyinti Lokufinyelela azitholakali kulo msebenzisi"</string>
+    <string name="copy_to_clipboard_dialog_title" msgid="494269163973708182">"Kopisha kubhodi lokunamathisela?"</string>
+    <string name="copy_to_clipboard" msgid="1977083934277981786">"Kopisha"</string>
+    <string name="incoming_sim_name_text" msgid="4244076415705614525">"ukuya ku-<xliff:g id="SIM_NAME">%s</xliff:g>"</string>
+    <string name="general_settings" msgid="5409336577057897710">"Okuvamile"</string>
+    <string name="advanced_settings" msgid="5870459931510000742">"Okuthuthukisiwe"</string>
+    <string name="general_settings_activity_title" msgid="3012187932521771578">"Izilungiselelo ezijwayelekile"</string>
+    <string name="advanced_settings_activity_title" msgid="7397017836928206201">"Izilungiselelo ezithuthukisiwe"</string>
+    <string name="sim_specific_settings" msgid="948779178668552448">"\"<xliff:g id="SIM_NAME">%s</xliff:g>\" SIM"</string>
+    <string name="disable_group_mms" msgid="1016285369211000297">"Thumela imilayezo ye-SIM ngamunye kubo bonke abamukeli. Uwena kuphela ozothla izimpendulo"</string>
+    <string name="enable_group_mms" msgid="4311733160940564593">"Thumela i-SMS eyodwa kubo bonke abamukeli"</string>
+    <string name="sim_settings_unknown_number" msgid="1885996389432991383">"Inombolo engaziwa"</string>
+    <string name="secondary_user_new_message_title" msgid="201938947573987596">"Umlayezo omusha."</string>
+    <string name="secondary_user_new_message_ticker" msgid="2386669280323553032">"Umlayezo omusha."</string>
+    <string name="sim_selector_button_content_description" msgid="2407660715957787727">"Iskhethi se-SIM"</string>
+    <string name="sim_selector_button_content_description_with_selection" msgid="4042539046779910617">"<xliff:g id="SIM_0">%1$s</xliff:g> okukhethiwe, isikhethi se-SIM"</string>
+    <string name="send_button_long_click_description_no_sim_selector" msgid="979624100711380593">"Hlela isihloko"</string>
+    <string name="send_button_long_click_description_with_sim_selector" msgid="7670274457707760465">"Khetha i-SIM noma hlela isihloko"</string>
+    <string name="audio_record_view_content_description" msgid="29401157183728655">"Thinta futhi ubambe ukuze urekhode umsindo"</string>
+    <string name="widget_new_conversation_content_description" msgid="4214201569175733579">"Qala ingxoxo entsha"</string>
+    <string name="widget_title_content_description" msgid="5802836840910466231">"Imilayezo"</string>
+    <string name="widget_conversation_list_name" msgid="4005037639000611925">"Uhlu lokulayeza"</string>
+    <string name="widget_conversation_name" msgid="3900606239571892871">"Imilayezo"</string>
+    <string name="widget_new_message_content_description" msgid="2706347689522691188">"Umlayezo omusha"</string>
+    <string name="widget_conversation_list_content_description" msgid="4137121313374868821">"Uhlu lwengxoxo"</string>
+    <string name="loading_conversations" msgid="2890879017729068514">"Ilayisha izingxoxo"</string>
+    <string name="loading_messages" msgid="3894765818932489665">"Ilayisha"</string>
+    <string name="view_more_conversations" msgid="2430542054023217740">"Buka izingxoxo ezengeziwe"</string>
+    <string name="view_more_messages" msgid="6463224009407336178">"Buka eminye imilayezo"</string>
+    <string name="conversation_deleted" msgid="6088388615460305424">"Ingxoxo isusiwe"</string>
+    <string name="tap_to_configure" msgid="7591682335533041774">"Ingxoxo isusiwe. Thinta ukuze ubonise ingxoxo ehlukile yokulayeza"</string>
+    <string name="update_destination_blocked" msgid="4577227174205233981">"Uvinjelwe"</string>
+    <string name="update_destination_unblocked" msgid="5369499874676600478">"Uvulelwe"</string>
+    <string name="db_full" msgid="8459265782521418031">"Isikhala sesitoreji siphansi. Enye idatha ingalahleka."</string>
+    <string name="attachment_chooser_activity_title" msgid="4049093653421684774">"Khetha okunamathiselwe"</string>
+    <string name="action_confirm_selection" msgid="3787494008738625806">"Qinisekisa ukukhetha"</string>
+    <string name="attachment_chooser_selection" msgid="3616821885478549778">"<xliff:g id="COUNT">%d</xliff:g> okukhethiwe"</string>
+    <string name="attachment_limit_reached_dialog_message_when_composing" msgid="2983376679583030373">"Sicela ususe okunamathiselwe  kwi-imeyili okukodwa noma okuningi uphinde uzame futhi."</string>
+    <string name="attachment_limit_reached_dialog_message_when_sending" msgid="3917529855170816197">"Ungazama ukuthumela umlayezo wakho, kodwa kungenzeka ungathunyelwa ngaphandle kokuthi ususe okunamathiselwe kwi-imeyili okukodwa noma okuningi."</string>
+    <string name="video_attachment_limit_exceeded_when_sending" msgid="8545536951461996462">"Ungathumela ividiyo eyodwa kuphela ngomlayezo. Sicela ususe amavidiyo angeziwe uphinde uzame futhi."</string>
+    <string name="attachment_load_failed_dialog_message" msgid="4917927407363303333">"Ukulayeza kuhlulekile ukulayisha okunamathiselwe kwi-imeyili."</string>
+    <string name="attachment_limit_reached_send_anyway" msgid="2348790618093735551">"Thumela noma kunjalo"</string>
+    <string name="conversation_creation_failure" msgid="8597624563218724441">"Ayikwazanga ukuqala ingxoxo"</string>
+    <string name="link_display_format" msgid="8700344957248709584">"<xliff:g id="TEXT">%1$s</xliff:g> (<xliff:g id="URL">%2$s</xliff:g>)"</string>
+    <string name="selected_sim_content_message" msgid="4504796674843354505">"I-<xliff:g id="SELECTED_SIM">%s</xliff:g> ikhethiwe"</string>
+</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644
index 0000000..59e3206
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- String to match as no subject and filter out as a subject. For example, if the
+         subject string is "no subject", we won't display that. We'll pretend
+         no subject string was delivered. -->
+    <string-array name="empty_subject_strings">
+        <item>no subject</item>
+        <item>nosubject</item>
+    </string-array>
+
+    <!-- Choices for quick-reply to message notification. Users with an Android
+    Wear device (e.g. smartwatch) can reply to messages either by speaking their
+    response, or choosing one of these predefined options. -->
+    <string-array name="notification_reply_choices">
+        <item>Yes</item>
+        <item>No</item>
+        <item>OK</item>
+        <item>Hehe</item>
+        <item>Thanks</item>
+        <item>I agree</item>
+        <item>Nice</item>
+        <item>On my way</item>
+        <item>OK, let me get back to you later</item>
+        <item>:)</item>
+        <item>:(</item>
+    </string-array>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..233cf9c
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <declare-styleable name="ContactIconView">
+        <attr name="iconSize">
+            <enum name="normal" value="0" />
+            <enum name="large" value="1" />
+            <enum name="small" value="2" />
+        </attr>
+    </declare-styleable>
+    <declare-styleable name="SoundLevels">
+        <attr name="maxLevelRadius" format="dimension|reference" />
+        <attr name="minLevelRadius" format="dimension|reference" />
+        <attr name="primaryColor" format="color" />
+    </declare-styleable>
+    <declare-styleable name="AsyncImageView">
+        <attr name="fadeIn" format="boolean" />
+        <attr name="placeholderDrawable" format="reference" />
+        <attr name="cornerRadius" format="dimension|reference" />
+        <attr name="reveal" format="boolean" />
+    </declare-styleable>
+    <declare-styleable name="VideoThumbnailView">
+        <attr name="mode" format="integer">
+            <enum name="imageThumbnail" value="0" />
+            <enum name="playableVideo" value="1" />
+        </attr>
+        <attr name="playOnLoad" format="boolean" />
+        <attr name="loop" format="boolean" />
+        <attr name="allowCrop" format="boolean" />
+        <attr name="android:maxHeight" />
+    </declare-styleable>
+    <declare-styleable name="MaxHeightScrollView">
+        <attr name="android:maxHeight" />
+    </declare-styleable>
+    <declare-styleable name="ConversationNameView">
+        <attr name="textSize" format="dimension|reference" />
+        <attr name="textColor" format="color" />
+    </declare-styleable>
+    <declare-styleable name="AudioAttachmentView">
+        <attr name="layoutMode" format="integer">
+            <enum name="normal" value="0" />
+            <enum name="compact" value="1" />
+            <enum name="subcompact" value="2" />
+        </attr>
+    </declare-styleable>
+    <attr name="apnPreferenceStyle" format="reference" />
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..0ecd2c2
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <color name="primary_color">#689F38</color>
+    <color name="permission_check_activity_background">@color/primary_color</color>
+
+    <!--  Action bar -->
+    <color name="action_bar_title_text_color">#ffffff</color>
+    <color name="action_bar_background_color">@color/primary_color</color>
+    <color name="action_bar_background_color_dark">#537F2D</color>
+    <color name="contextual_action_bar_background_color">#ffffff</color>
+    <color name="archived_conversation_action_bar_background_color">#9D9D9D</color>
+    <color name="archived_conversation_action_bar_background_color_dark">#838383</color>
+
+    <!-- Conversation list -->
+    <color name="conversation_list_item_read">#636363</color>
+    <color name="conversation_list_item_unread">#323232</color>
+    <color name="conversation_list_error">#F05A24</color>
+    <color name="conversation_list_name">#DE000000</color>
+    <color name="conversation_list_details">#8A000000</color>
+
+    <color name="conversation_compose_divider_start">#44000000</color>
+
+    <color name="message_text">#000000</color>
+    <color name="timestamp_text_outgoing">#99323232</color>
+    <color name="timestamp_text_incoming">#99ffffff</color>
+    <color name="timestamp_text_failed">#99ff0000</color>
+    <color name="compose_send_text_color">#000000</color>
+
+    <color name="message_title_text">#ff323232</color>
+    <color name="message_download_failed_status_text">#000000</color>
+    <color name="message_info_text">#99ffffff</color>
+    <color name="message_info_text_incoming_download_failed">#6a6a6a</color>
+    <color name="message_download_failed_timestamp_text">#007fce</color>
+    <color name="message_failed_timestamp_text">#99ff0000</color>
+    <color name="message_action_status_text">#ffffffff</color>
+    <color name="message_action_info_text">#99ffffff</color>
+    <color name="message_action_timestamp_text">#ffffffff</color>
+
+    <color name="background_item_transparent">@android:color/transparent</color>
+    <color name="background_item_activated">#670099cc</color>
+    <color name="background_item_selected">#cc0099cc</color>
+    <color name="background_item_pressed">#6733b5e5</color>
+
+    <color name="subject_editor_bubble">#ffffffff</color>
+    <color name="message_text_color_incoming">#ffffffff</color>
+    <color name="message_text_color_incoming_download_failed">#6a6a6a</color>
+    <color name="message_text_color_outgoing">#ff323232</color>
+    <color name="conversation_background">#eeeeee</color>
+    <color name="conversation_edge_effect">#9d9d9d</color>
+    <color name="compose_message_send_color">@color/primary_color</color>
+    <color name="compose_message_send_color_pressed">#999999</color>
+    <color name="message_bubble_color_outgoing">#ffffffff</color>
+    <color name="message_error_bubble_color_incoming">#e2e2e2</color>
+    <color name="message_audio_button_color_incoming">#ffffffff</color>
+    <color name="message_bubble_color_selected">#8BC34A</color>
+    <color name="message_image_selected_tint">#80689F38</color>
+    <color name="generic_video_icon">#ff808080</color>
+
+    <!-- Base color used for color filtering. -->
+    <color name="color_filter_base_color">#ff0000</color>
+
+    <!-- Activity background color -->
+    <drawable name="class_zero_background">#7f040000</drawable>
+
+    <color name="contact_avatar_default_background">#d2d2d2</color>
+    <color name="contact_avatar_pressed_color">#40000000</color>
+    <color name="contact_list_text_primary">#4d4d4d</color>
+    <color name="contact_list_text_secondary">#999999</color>
+
+    <color name="compose_contact_text">@android:color/white</color>
+    <color name="compose_contact_faint_text">#a0ffffff</color>
+    <color name="compose_contact_divider">#44000000</color>
+    <color name="contact_picker_tab_pressed">#ddffffff</color>
+    <color name="contact_picker_tab_underline">@android:color/white</color>
+    <color name="contact_list_alphabet_header">@color/primary_color</color>
+    <color name="contact_picker_background">#ffffff</color>
+    <color name="chips_dropdown_background_activated">#4285f4</color>
+    <color name="chips_dropdown_background_pressed">#ededed</color>
+    <color name="chips_background_color">#33000000</color>
+    <color name="chips_text_color">@android:color/white</color>
+
+    <color name="camera_button_container_background">#80000000</color>
+
+    <color name="translucent_white">#80ffffff</color>
+
+    <color name="gallery_image_default_background">#eeeeee</color>
+    <color name="gallery_image_pressed">#6733b5e5</color>
+    <color name="attachment_preview_more_items_text_background">#44000000</color>
+
+    <color name="letter_tile_font_color">#ffffff</color>
+
+    <color name="audio_picker_level_primary_color">#29000000</color>
+    <color name="audio_record_control_button_stroke">#30000000</color>
+    <color name="audio_picker_hint_text_color">#40000000</color>
+    <color name="audio_picker_timer_text_color">#323232</color>
+    <color name="audio_attachment_timer_text_color">#323232</color>
+    <color name="audio_progress_bar_color">@color/primary_color</color>
+
+    <color name="contact_picker_hint_text_color">#40000000</color>
+
+    <color name="notification_sender_text">#9A9A9A</color>
+    <color name="notification_secondary_text">#FFFFFF</color>
+    <color name="notification_tertiary_text">#FFFFFF</color>
+    <color name="wearable_notification_participants_count">#a2a2a2</color>
+    <color name="notification_accent_color">@color/primary_color</color>
+    <color name="notification_warning_color">#ff0000</color>
+    <color name="notification_subject_color">#99aaaaaa</color>
+
+    <color name="participant_list_text_primary">#4d4d4d</color>
+    <color name="participant_list_text_secondary">#6d6d6d</color>
+    <color name="people_and_options_header_text">#6d6d6d</color>
+    <color name="people_and_options_list_divider">#cccccc</color>
+
+    <color name="fab_color">@color/primary_color</color>
+    <color name="fab_pressed_color">#3ea4dc</color>
+    <color name="fab_ripple">#40ffffff</color>
+
+    <color name="message_body_size_text_color">#555555</color>
+    <color name="mms_indicator_color">#8BC34A</color>
+    <color name="list_empty_text">#6d6d6d</color>
+    <color name="low_storage_action_item_color">#ff000000</color>
+    <color name="unblock_item_text_color">@color/primary_color</color>
+    <color name="open_conversation_animation_background_shadow">#40000000</color>
+    <color name="compose_notification_bar_background">@color/primary_color</color>
+
+    <color name="sim_selector_text_primary">#4d4d4d</color>
+    <color name="sim_selector_text_secondary">#999999</color>
+    <color name="sim_selector_background_end">#cceeeeee</color>
+    <color name="sim_selector_background_start">#ffeeeeee</color>
+    <color name="sim_indicator_color_light">#ffffff</color>
+    <color name="sim_indicator_color_dark">#323232</color>
+
+    <color name="text_highlight_color">#80689F38</color>
+    <color name="search_view_text_cursor">#b0dddddd</color>
+
+    <color name="button_bar_action_button_text_color">#03a9f4</color>
+    <color name="button_bar_cancel_button_text_color">#4d4d4d</color>
+
+    <color name="settings_list_text_primary">#4d4d4d</color>
+    <color name="settings_list_text_secondary">#6d6d6d</color>
+    <color name="group_mms_setting_text_color">#333333</color>
+    <color name="settings_item_title_text_primary">#000000</color>
+
+    <color name="contact_picker_button_text_color">@color/primary_color</color>
+
+    <color name="widget_text_color">#424242</color>
+    <color name="widget_incoming_text_color">@android:color/white</color>
+    <color name="widget_outgoing_text_color">#424242</color>
+    <color name="widget_background_color">#ffffff</color>
+    <color name="ripple_material_light">#40000000</color>
+    <color name="widget_conversation_title_color">#FFFFFF</color>
+
+    <color name="attachment_chooser_audio_background">#eeeeee</color>
+    <color name="attachment_chooser_vcard_background">#eeeeee</color>
+
+    <color name="fastscroll_track_color">#1e000000</color>
+    <color name="fastscroll_thumb_color">#42000000</color>
+    <color name="fastscroll_preview_text_color">#ffffff</color>
+
+    <color name="google_gray">#F1F1F1</color>
+</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
new file mode 100644
index 0000000..954f5ed
--- /dev/null
+++ b/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<resources>
+    <!-- The packaged version of APNs and MMS configurations -->
+    <integer name="apnsAndMmsConfigsVersion">0</integer>
+</resources>
diff --git a/res/values/constants.xml b/res/values/constants.xml
new file mode 100644
index 0000000..e494e95
--- /dev/null
+++ b/res/values/constants.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+
+    <!-- Preference keys for user-visible settings -->
+    <!-- Application-wide settings -->
+    <string name="notifications_category_pref_key" translatable="false">notifications_category</string>
+    <string name="mms_messaging_category_pref_key" translatable="false">mms_messaging_category</string>
+    <string name="advanced_category_pref_key" translatable="false">advanced_category</string>
+    <string name="notifications_enabled_pref_key" translatable="false">notifications_enabled</string>
+    <bool name="notifications_enabled_pref_default" translatable="false">true</bool>
+    <string name="notification_sound_pref_key" translatable="false">notification_sound</string>
+    <string name="notification_vibration_pref_key" translatable="false">notification_vibration</string>
+    <bool name="notification_vibration_pref_default" translatable="false">true</bool>
+    <string name="sms_disabled_pref_key" translatable="false">sms_disabled</string>
+    <string name="sms_enabled_pref_key" translatable="false">sms_enabled</string>
+    <string name="send_sound_pref_key" translatable="false">send_sound</string>
+    <bool name="send_sound_pref_default" translatable="false">true</bool>
+    <string name="advanced_pref_key" translatable="false">advanced_prefs</string>
+
+    <!-- Subscription-specific settings. The values of these pref keys must be prefixed with
+         "buglesub_" to allow for runtime checks -->
+    <string name="delivery_reports_pref_key" translatable="false">buglesub_delivery_reports</string>
+    <bool name="delivery_reports_pref_default" translatable="false">false</bool>
+    <string name="auto_retrieve_mms_pref_key" translatable="false">buglesub_auto_retrieve_mms</string>
+    <bool name="auto_retrieve_mms_pref_default" translatable="false">true</bool>
+    <string name="auto_retrieve_mms_when_roaming_pref_key" translatable="false">buglesub_auto_retrieve_mms_when_roaming</string>
+    <bool name="auto_retrieve_mms_when_roaming_pref_default" translatable="false">false</bool>
+    <string name="group_mms_pref_key" translatable="false">buglesub_group_messaging</string>
+    <bool name="group_mms_pref_default" translatable="false">true</bool>
+    <string name="mms_phone_number_pref_key" translatable="false">buglesub_mms_phone_number</string>
+    <string name="wireless_alerts_key" translatable="false">buglesub_wireless_alerts_key</string>
+    <string name="apn_list_pref_key" translatable="false">buglesub_apn_list</string>
+
+    <!-- Debug preferences -->
+    <string name="debug_pref_key" translatable="false">debug_category</string>
+    <string name="dump_sms_pref_key" translatable="false">dump_sms</string>
+    <bool name="dump_sms_pref_default" translatable="false">false</bool>
+    <string name="dump_mms_pref_key" translatable="false">dump_mms</string>
+    <bool name="dump_mms_pref_default" translatable="false">false</bool>
+
+
+    <!-- SMS/MMS settings keys -->
+    <!--
+    TODO: Several of these are currently unused but are expected to be needed to
+    implement SMS/MMS delivery and basic settings. Once we have the core functionality in place
+    we should do a pass to remove any unused values here.
+    -->
+    <string name="sms_apns_key" translatable="false">sms_apns_key</string>
+    <string name="use_local_apn_pref_key" translatable="false">use_local_apn_pref_key</string>
+    <bool name="use_local_apn_pref_default" translatable="false">false</bool>
+
+    <integer name="mediapicker_transition_duration">600</integer><!-- ms -->
+    <integer name="asyncimage_transition_duration">300</integer><!-- ms -->
+    <integer name="compose_transition_duration">300</integer><!-- ms -->
+    <integer name="camera_shutter_duration">200</integer><!-- ms -->
+    <fraction name="camera_shutter_max_alpha">70%</fraction>
+
+    <integer name="snackbar_translation_duration_ms">300</integer>
+
+    <!-- Notification preferences -->
+    <string name="notifications_group_children_key" translatable="false">notifications_group_children</string>
+
+    <!-- format string for creating new image files. Passed to java.text.SimpleDateFormat. -->
+    <string name="new_image_file_name_format" translatable="false">"'IMG'_yyyyMMdd_HHmmss"</string>
+    <!-- format string for creating new files of unknown type. Passed to java.text.SimpleDateFormat. -->
+    <string name="new_file_name_format" translatable="false">"yyyyMMdd_HHmmss"</string>
+
+    <!-- Swipe to Archive consts -->
+    <integer name="swipe_duration_ms">300</integer>
+    <integer name="swipe_max_fling_velocity_px_per_s">4000</integer>
+
+    <!-- Fab animation const -->
+    <integer name="fab_animation_duration_ms">300</integer>
+
+    <!-- Conversation list -> conversation animation const -->
+    <integer name="list_to_conversation_animation_duration_ms">300</integer>
+
+    <!-- Generic reveal view animation duration -->
+    <integer name="reveal_view_animation_duration">300</integer>
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100644
index 0000000..0795ebc
--- /dev/null
+++ b/res/values/dimens.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+
+    <dimen name="action_bar_height">56dp</dimen>
+    <dimen name="action_bar_elevation">8dp</dimen>
+    <dimen name="action_bar_text_size">20sp</dimen>
+    <dimen name="conversation_message_text_size">16sp</dimen>
+    <dimen name="conversation_status_text_size">12sp</dimen>
+    <dimen name="conversation_title_text_size">12sp</dimen>
+    <dimen name="conversation_info_text_size">12sp</dimen>
+    <dimen name="conversation_compose_send_text_size">16sp</dimen>
+    <dimen name="contact_icon_view_normal_size">42dp</dimen>
+    <dimen name="contact_icon_view_large_size">56dp</dimen>
+    <dimen name="contact_icon_view_small_size">12dp</dimen>
+    <dimen name="conversation_list_item_view_padding">16dp</dimen>
+    <dimen name="conversation_list_first_item_extra_padding">8dp</dimen>
+    <dimen name="conversation_list_image_preview_corner_radius">3dp</dimen>
+    <dimen name="conversation_list_image_preview_size">56dp</dimen>
+    <dimen name="conversation_list_contact_icon_size">56dp</dimen>
+    <dimen name="conversation_message_contact_icon_size">42dp</dimen>
+    <dimen name="conversation_message_photo_min_size">96dp</dimen>
+    <dimen name="conversation_list_notification_bell_padding">4dp</dimen>
+    <dimen name="conversation_list_empty_text_bottom_margin">30dp</dimen>
+    <dimen name="blocked_participant_list_item_view_padding">16dp</dimen>
+
+    <dimen name="message_bubble_arrow_width">9dp</dimen>
+    <dimen name="message_text_bottom_padding">12dp</dimen>
+    <dimen name="message_text_top_padding">10dp</dimen>
+    <dimen name="message_text_left_right_padding">14dp</dimen>
+    <dimen name="message_padding_default">18dp</dimen>
+    <dimen name="message_padding_same_author">2dp</dimen>
+    <dimen name="message_metadata_top_padding">4dp</dimen>
+    <dimen name="message_audio_attachment_padding">12dp</dimen>
+
+    <dimen name="mediapicker_default_chooser_height">215dp</dimen>
+    <dimen name="compose_message_contacts_container_margin">4dp</dimen>
+    <dimen name="compose_message_contacts_height">42dp</dimen>
+    <dimen name="compose_message_chip_height">36dp</dimen>
+    <dimen name="compose_message_chip_padding">3dp</dimen>
+    <dimen name="compose_message_fields_horizontal_margin">16dp</dimen>
+    <dimen name="compose_message_font_size">16sp</dimen>
+    <dimen name="compose_message_attachment_padding_sides">20dp</dimen>
+    <dimen name="compose_message_attachment_padding_topBottom">10dp</dimen>
+    <dimen name="compose_message_chips_view_max_height">133dp</dimen>
+    <dimen name="compose_message_subject_left_padding">52dp</dimen>
+    <dimen name="compose_message_subject_right_padding">64dp</dimen>
+    <dimen name="compose_message_subject_top_padding">4dp</dimen>
+    <dimen name="compose_message_subject_bottom_padding">6dp</dimen>
+    <dimen name="compose_message_subject_cancel_top_offset">-12dp</dimen>
+    <dimen name="compose_message_subject_cancel_left_margin">12dp</dimen>
+    <dimen name="compose_message_mms_indicator_padding_top">2dp</dimen>
+    <dimen name="compose_message_send_button_padding_right">12dp</dimen>
+    <dimen name="compose_message_text_box_padding_side">8dp</dimen>
+
+    <!-- Notification related dimensions. -->
+    <dimen name="notification_wearable_image_height">240dp</dimen>
+    <dimen name="notification_wearable_image_width">240dp</dimen>
+
+    <!-- Contact Picker related dimensions. -->
+    <dimen name="contact_list_text_size">16sp</dimen>
+    <dimen name="contact_list_detail_text_size">14sp</dimen>
+    <dimen name="contact_list_icon_size">42dp</dimen>
+    <dimen name="recipient_edit_text_size">20sp</dimen>
+    <dimen name="pager_tab_header_text_size">14sp</dimen>
+    <dimen name="pager_tab_underline_selected">2dp</dimen>
+    <dimen name="contact_list_alphabet_header_text_size">26dp</dimen>
+
+    <!-- Flings slower than this length / sec will be ignored -->
+    <dimen name="mediapicker_fling_threshold">150dp</dimen>
+    <!-- Flings faster than this length / sec will go from fullscreen straight to closed -->
+    <dimen name="mediapicker_big_fling_threshold">1000dp</dimen>
+    <dimen name="gallery_image_cell_size">110dp</dimen>
+    <dimen name="gallery_icon_size">40dp</dimen>
+    <dimen name="single_attachment_min_dimen">50dp</dimen>
+    <dimen name="single_attachment_max_height">150dp</dimen>
+    <dimen name="multiple_attachment_preview_height">130dp</dimen>
+    <dimen name="multiple_attachment_preview_width">260dp</dimen>
+    <dimen name="multiple_attachment_preview_padding">1dp</dimen>
+    <dimen name="attachment_preview_more_items_text_size">22sp</dimen>
+
+    <item name="letter_to_tile_ratio" type="dimen">67%</item>
+    <item name="sim_identifier_to_tile_ratio" type="dimen">28%</item>
+    <item name="small_sim_identifier_to_tile_ratio" type="dimen">75%</item>
+
+    <dimen name="audio_picker_text_size">16sp</dimen>
+    <dimen name="audio_attachment_text_size">14sp</dimen>
+    <dimen name="audio_progress_bar_height">6dp</dimen>
+
+    <dimen name="contact_picker_text_size">16sp</dimen>
+
+    <!-- Videos in the message list view should at least be this big in the smallest dimension -->
+    <dimen name="video_message_min_size">320dp</dimen>
+    <dimen name="attachment_rounded_corner_radius">3dp</dimen>
+    <dimen name="progress_indicator_default_stroke_width">2dp</dimen>
+    <dimen name="progress_indicator_default_radius">12dp</dimen>
+    <dimen name="participant_list_text_size">18sp</dimen>
+    <dimen name="participant_list_detail_text_size">14sp</dimen>
+    <dimen name="people_and_options_header_text_size">16sp</dimen>
+    <dimen name="image_attachment_fallback_width">240dp</dimen>
+    <dimen name="image_attachment_fallback_height">240dp</dimen>
+
+    <dimen name="fab_size">60dp</dimen>
+    <dimen name="fab_padding_bottom">4dp</dimen>
+    <dimen name="fab_elevation">2dp</dimen>
+    <dimen name="fab_elevation_pressed">6dp</dimen>
+    <dimen name="fab_bottom_margin">12dp</dimen>
+    <dimen name="fab_left_right_margin">14dp</dimen>
+    <dimen name="message_body_size_text_size">12sp</dimen>
+
+    <dimen name="vcard_detail_group_indicator_width">40dp</dimen>
+    <dimen name="mms_indicator_size">12sp</dimen>
+    <dimen name="conversation_fast_fling_threshold">10dp</dimen>
+    <dimen name="list_empty_text_size">14sp</dimen>
+    <dimen name="list_empty_text_top_margin">20dp</dimen>
+    <dimen name="list_empty_text_left_right_margin">60dp</dimen>
+    <dimen name="low_storage_action_item_text_size">16sp</dimen>
+
+    <dimen name="snack_bar_left_right_margin">24dp</dimen>
+    <dimen name="snack_bar_top_bottom_margin">18dp</dimen>
+
+    <dimen name="version_dialog_large_padding">24dp</dimen>
+    <dimen name="version_dialog_bottom_padding">20dp</dimen>
+    <dimen name="version_dialog_info_left_padding">14dp</dimen>
+    <dimen name="version_dialog_copyright_top_margin">20dp</dimen>
+
+    <dimen name="explode_animation_highlight_elevation">6dp</dimen>
+
+    <dimen name="sim_selector_text_size">14sp</dimen>
+    <dimen name="sim_selector_detail_text_size">14sp</dimen>
+    <dimen name="sim_selector_icon_size">42dp</dimen>
+
+    <dimen name="copy_contact_dialog_left_padding">25dp</dimen>
+    <dimen name="copy_contact_dialog_right_padding">10dp</dimen>
+    <dimen name="copy_contact_dialog_top_padding">5dp</dimen>
+
+    <dimen name="settings_list_text_size">16sp</dimen>
+    <dimen name="settings_list_detail_text_size">14sp</dimen>
+    <dimen name="settings_list_item_height">60dp</dimen>
+    <dimen name="group_mms_setting_text_size">14sp</dimen>
+
+    <!-- Camera focus indicator values -->
+    <dimen name="pie_radius_start">40dp</dimen>
+    <dimen name="pie_radius_increment">30dp</dimen>
+    <dimen name="pie_touch_offset">20dp</dimen>
+    <dimen name="focus_radius_offset">8dp</dimen>
+    <dimen name="focus_inner_offset">12dp</dimen>
+    <dimen name="focus_outer_stroke">3dp</dimen>
+    <dimen name="focus_inner_stroke">2dp</dimen>
+
+    <dimen name="conversation_bubble_width_snap">20dp</dimen>
+
+    <!-- Widget -->
+    <dimen name="widget_margin">8dp</dimen>
+    <dimen name="widget_subtitle_margin">0dp</dimen>
+    <dimen name="widget_avatar_padding">2dp</dimen>
+    <dimen name="widget_header_height">48dp</dimen>
+    <dimen name="widget_header_new_conv_button_width">48dp</dimen>
+    <dimen name="widget_conversation_title_size">18sp</dimen>
+    <dimen name="widget_compose_top_padding">12dp</dimen>
+    <dimen name="widget_compose_top_padding_compressed">16dp</dimen>
+
+    <dimen name="attachment_grid_image_cell_size">110dp</dimen>
+    <dimen name="attachment_grid_checkbox_area_increase">15dp</dimen>
+
+    <!-- The default size of a pending attachment while its size is unknown -->
+    <dimen name="pending_attachment_size">120dp</dimen>
+
+    <!-- Conversation fast-scroller -->
+    <dimen name="fastscroll_touch_slop">8dp</dimen>
+    <dimen name="fastscroll_track_width">8dp</dimen>
+    <dimen name="fastscroll_thumb_height">48dp</dimen>
+    <dimen name="fastscroll_preview_min_width">88dp</dimen>
+    <dimen name="fastscroll_preview_height">88dp</dimen>
+    <dimen name="fastscroll_preview_corner_radius">44dp</dimen>
+    <dimen name="fastscroll_preview_padding">24dp</dimen>
+    <dimen name="fastscroll_preview_margin_top">8dp</dimen>
+    <dimen name="fastscroll_preview_margin_left_right">8dp</dimen>
+    <dimen name="fastscroll_preview_text_size">24sp</dimen>
+
+    <dimen name="directory_header_padding_start">16dp</dimen>
+    <dimen name="directory_header_padding_end">32dp</dimen>
+    <dimen name="directory_header_padding_top">18dp</dimen>
+    <dimen name="directory_header_padding_bottom">8dp</dimen>
+    <dimen name="directory_header_text_size">14sp</dimen>
+
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..e5c442d
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,985 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- The name of the application as it appears under the main Launcher icon and in various activity titles -->
+    <string name="app_name">Messaging</string>
+
+    <!-- The name of the application as it appears in external share intent dialogs -->
+    <string name="share_intent_label">Messaging</string>
+    <!-- The title when selecting a conversation to share to -->
+    <string name="share_intent_activity_label">Select conversation</string>
+
+    <string name="action_settings">Settings</string>
+    <string name="sendButtonContentDescription">Send Message</string>
+    <string name="attachMediaButtonContentDescription">Add an attachment</string>
+    <string name="help_and_feedback_activity_label">Help</string>
+
+    <string name="welcome">Welcome</string>
+    <string name="skip">Skip</string>
+    <string name="next_with_arrow">Next &gt;</string>
+    <string name="next">Next</string>
+    <string name="exit">Exit</string>
+    <string name="settings_with_arrow">Settings &gt;</string>
+    <string name="settings">Settings</string>
+    <!-- Inform user of the names of permissions that are required to use the app -->
+    <string name="required_permissions_promo">Messaging needs permission to SMS, Phone and Contacts.</string>
+    <string name="enable_permission_procedure">You can change permissions in Settings > Apps > Messaging > Permissions.</string>
+    <string name="enable_permission_procedure_description">You can change permissions in Settings, Apps, Messaging, Permissions.</string>
+
+    <!-- The tab header for the frequently used contacts list -->
+    <string name="contact_picker_frequents_tab_title">Frequents</string>
+
+    <!-- The tab header for all contacts list -->
+    <string name="contact_picker_all_contacts_tab_title">All contacts</string>
+
+    <!-- The text on the list item in the contact picker that allows a user to send an SMS directly
+         to a number that he/she typed. eg. "Send to 650-555-1234" -->
+    <string name="contact_list_send_to_text">Send to <xliff:g id="destination">%s</xliff:g></string>
+
+    <string name="mediapicker_cameraChooserDescription">Capture pictures or video</string>
+    <string name="mediapicker_galleryChooserDescription">Choose images from this device</string>
+    <string name="mediapicker_audioChooserDescription">Record audio</string>
+    <string name="mediapicker_contactChooserDescription">Choose a contact from this device</string>
+    <string name="mediapicker_gallery_title">Choose media</string>
+    <string name="mediapicker_gallery_item_selected_content_description">The media is selected.</string>
+    <string name="mediapicker_gallery_item_unselected_content_description">The media is unselected.</string>
+    <string name="mediapicker_gallery_title_selection"><xliff:g id="count">%d</xliff:g> selected</string>
+    <!-- example: "image January 17 2015 1 59 pm" -->
+    <string name="mediapicker_gallery_image_item_description">image <xliff:g id="date">%1$tB %1$te %1$tY %1$tl %1$tM %1$tp</xliff:g></string>
+    <string name="mediapicker_gallery_image_item_description_no_date">image</string>
+    <string name="mediapicker_audio_title">Record audio</string>
+    <string name="mediapicker_contact_title">Choose a contact</string>
+    <!-- Hint text on the contact picker -->
+    <string name="contact_picker_hint_text">Click to open contacts list on this device</string>
+
+    <string name="action_share">Share</string>
+
+    <string name="posted_just_now">"Just now"</string>
+    <string name="posted_now">"Now"</string>
+
+    <!-- Abbreviated message to express that something occurred some number of minutes in the past (e.g., 5 minutes ago). -->
+    <plurals name="num_minutes_ago">
+        <item quantity="one"><xliff:g id="count">%d</xliff:g> min</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> mins</item>
+    </plurals>
+
+    <!-- Abbreviated message to express that something occurred some number of hours in the past (e.g., 5 hours ago). -->
+    <plurals name="num_hours_ago">
+        <item quantity="one"><xliff:g id="count">%d</xliff:g> hour</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> hours</item>
+    </plurals>
+
+    <!-- Abbreviated message to express that something occurred some number of days in the past (e.g., 5 days ago). -->
+    <plurals name="num_days_ago">
+        <item quantity="one"><xliff:g id="count">%d</xliff:g> day</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> days</item>
+    </plurals>
+
+    <!--
+        Plurals used for the duration in free sms storage action and confirm strings above
+        Example: "Delete messages older than a week"
+    -->
+    <plurals name="week_count">
+        <!-- Singular case -->
+        <item quantity="one">a week</item>
+        <!-- Plural case -->
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> weeks</item>
+    </plurals>
+    <plurals name="month_count">
+        <!-- Singular case -->
+        <item quantity="one">a month</item>
+        <!-- Plural case -->
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> months</item>
+    </plurals>
+    <plurals name="year_count">
+        <!-- Singular case -->
+        <item quantity="one">a year</item>
+        <!-- Plural case -->
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> years</item>
+    </plurals>
+
+    <!-- Title of the class-0 message activity. -->
+    <string name="class_0_message_activity">Class 0 message</string>
+    <string name="save">Save</string>
+
+    <!-- Text for SMS storage low text, when auto delete is enabled -->
+    <string name="sms_storage_low_auto_delete_enabled_dialog_text">Device is low on space. Messaging will automatically delete older messages to free up space.</string>
+    <!-- Title for SMS storage low notification and dialog. Must match the framework's notification title, i.e. //frameworks/base/core/res/res/values/strings.xml#low_internal_storage_view_title -->
+    <string name="sms_storage_low_title">Storage space running out</string>
+    <!-- Text for SMS storage low notification and dialog -->
+    <string name="sms_storage_low_text">Messaging might not send or receive messages until more space is available on your device.</string>
+    <!-- Ticker for SMS storage low notification -->
+    <string name="sms_storage_low_notification_ticker">Low SMS storage. You may need to delete messages.</string>
+
+    <!-- Title for asking the user to enter their phone number -->
+    <string name="enter_phone_number_title">Confirm your phone number</string>
+    <!-- Text for asking the user to enter their phone number -->
+    <string name="enter_phone_number_text">This one-time step will ensure Messaging will deliver your group messages properly.</string>
+    <!-- EditText hint for asking the user to enter their phone number -->
+    <string name="enter_phone_number_hint">Phone number</string>
+
+    <!-- Free SMS storage actions -->
+    <string name="delete_all_media">Delete all messages with media</string>
+    <string name="delete_oldest_messages">Delete messages older than <xliff:g id="duration">%s</xliff:g></string>
+    <string name="auto_delete_oldest_messages">Auto-delete messages older than <xliff:g id="duration">%s</xliff:g></string>
+    <string name="ignore">Ignore</string>
+
+    <!-- Free SMS storage action confirm dialog message -->
+    <string name="delete_all_media_confirmation">Delete all messages with media?</string>
+    <string name="delete_oldest_messages_confirmation">Delete messages older than <xliff:g id="duration">%s</xliff:g>?</string>
+    <string name="auto_delete_oldest_messages_confirmation">Delete messages older than <xliff:g id="duration">%s</xliff:g> and turn on auto-delete?</string>
+
+    <!-- ####### Strings to support the mms/sms service ####### -->
+
+    <!-- Prefix for accessibility to indicate who the sender of a plain text message is. -->
+    <string name="incoming_text_sender_content_description"><xliff:g id="sender">%s</xliff:g> said</string>
+    <string name="outgoing_text_sender_content_description">You said</string>
+
+    <!-- Prefix for accessibility to indicate who the sender of text with hyperlinks, an attachment, or yet-to-be-downloaded message is. -->
+    <string name="incoming_sender_content_description">Message from <xliff:g id="sender">%s</xliff:g></string>
+    <string name="outgoing_sender_content_description">You sent a message</string>
+
+    <!-- While sending a message display this message. -->
+    <string name="message_status_sending">Sending&#8230;</string>
+    <!-- When sending a message failed display this message. -->
+    <string name="message_status_send_failed">Not sent. Tap to try again.</string>
+    <!-- When retrying sending for a message. -->
+    <string name="message_status_send_retrying">Not sent. Trying again&#8230;</string>
+    <!-- When showing resend action display this message. -->
+    <string name="message_status_resend">Resend or delete</string>
+
+    <!-- When sending a message to an emergency number failed display this message in the conversation. -->
+    <string name="message_status_send_failed_emergency_number">Please make a voice call to emergency services. Your text message could not be delivered at this time.</string>
+
+    <!-- When showing resend action, display this message. -->
+    <string name="message_status_failed">Failed</string>
+
+    <!-- Title line for an MMS requiring manual download. -->
+    <string name="message_title_manual_download">New MMS message to download</string>
+    <!-- Title line for an MMS auto-downloading. -->
+    <string name="message_title_downloading">New MMS message</string>
+    <!-- Title line for MMS which failed to download. -->
+    <string name="message_title_download_failed">Couldn\'t download</string>
+    <!-- Timestamp line for MMS which failed to download. -->
+    <string name="message_status_download_failed">Tap to try again</string>
+    <!-- Timestamp line for MMS which failed to download. -->
+    <string name="message_status_download">Tap to download</string>
+    <!-- Timestamp line for MMS which is selected. -->
+    <string name="message_status_download_action">Download or delete</string>
+    <!-- Timestamp line to display while downloading a message. -->
+    <string name="message_status_downloading">Downloading&#8230;</string>
+    <!-- Timestamp line for MMS for expired or invalid message. -->
+    <string name="message_status_download_error">Message expired or not available</string>
+    <!-- Display this info line with an MMS notification -->
+    <string name="mms_info">size: <xliff:g id="messageSize">%1$s</xliff:g>, expiration: <xliff:g id="messageExpire">%2$s</xliff:g></string>
+    <!-- While sending a message, if it has invalid recipient, display this message. -->
+    <string name="invalid_destination">Can\'t send. Recipient not valid.</string>
+    <!-- While sending a message, this error is expected to be generated when user does not have
+         MMS enabled on his account. [CHAR LIMIT=NONE] -->
+    <string name="service_not_activated">Service not activated on network</string>
+    <!-- If a message can't be sent because of a MMSC network problem, show this toast. [CHAR LIMIT=NONE] -->
+    <string name="service_network_problem">Couldn\'t send due to network problem</string>
+    <!-- If a message has expired and is no longer available on MMSC, show this toast. [CHAR LIMIT=NONE] -->
+    <string name="service_message_not_found">Message expired or not available</string>
+    <!-- Download Manager -->
+    <!-- When an error occurs downloading a new message and a subject isn't available, substitute
+         this default subject. -->
+    <string name="no_subject">(No subject)</string>
+    <!-- When an error occurs downloading a new message and the sender is unknown, substitute
+         this default text. -->
+    <string name="unknown_sender">Unknown sender</string>
+    <string name="delivered_status_content_description">Delivered</string>
+    <!-- When an error occurs downloading a new message, display this message.
+         An example: Download of message Wanna get pizza from dorkman was unsuccessful. -->
+    <string name="dl_failure_notification">Couldn\'t download message <xliff:g id="subject">%1$s</xliff:g> from <xliff:g id="from">%2$s</xliff:g>.</string>
+    <!-- When a database error occurs due to low memory this toast is shown. -->
+    <string name="low_memory">Couldn\'t complete database operation due to low memory</string>
+    <!-- notification line 1 for "there are some failed messages" -->
+    <string name="notification_send_failures_line1_singular">Message not sent</string>
+    <!-- notification line 1 for "there are some failed messages" -->
+    <string name="notification_send_failures_line1_plural">Some messages not sent in Messaging</string>
+    <plurals name="notification_send_failures">
+        <item quantity="one"><xliff:g id="messages">%d</xliff:g> messages in one conversation</item>
+        <item quantity="other"><xliff:g id="messages">%d</xliff:g> messages in <xliff:g id="conversations">%d</xliff:g> conversations</item>
+    </plurals>
+    <!-- notification line 1 for download failed -->
+    <string name="notification_download_failures_line1_singular">Message not downloaded</string>
+    <!-- notification line 1 for multiple downloads failed -->
+    <string name="notification_download_failures_line1_plural">Some messages not downloaded in Messaging</string>
+    <plurals name="notification_download_failures">
+        <item quantity="one"><xliff:g id="messages">%d</xliff:g> messages in one conversation</item>
+        <item quantity="other"><xliff:g id="messages">%d</xliff:g> messages in <xliff:g id="conversations">%d</xliff:g> conversations</item>
+    </plurals>
+    <!-- Notification title when emergency SMS (e.g. to 911) fails to send -->
+    <string name="notification_emergency_send_failure_line1">Message to <xliff:g id="number">%1$s</xliff:g> not sent</string>
+    <!-- Notification content when emergency SMS fails to send -->
+    <string name="notification_emergency_send_failure_line2">
+        Please make a voice call to emergency services. Your text message to
+        <xliff:g id="number">%1$s</xliff:g> could not be delivered at this time.
+    </string>
+    <!-- notification line 1 for new message notification on the lock screen -->
+    <plurals name="notification_new_messages">
+        <item quantity="one">New message</item>
+        <item quantity="other"><xliff:g id="messages">%d</xliff:g> new messages</item>
+    </plurals>
+
+    <!-- Text for starting a new conversation button in the compose UI -->
+    <string name="start_conversation">Start</string>
+
+    <string name="camera_error_opening">Camera not available</string>
+    <string name="camera_error_unknown">Camera not available</string>
+    <string name="camera_error_video_init_fail">Video capture not available</string>
+    <!-- Error message when we are unable to write a picture or video file because of an error writing to storage (usually because insufficient space) -->
+    <string name="camera_error_storage_fail">Can\'t save media</string>
+    <string name="camera_error_failure_taking_picture">Can\'t take picture</string>
+
+    <!-- Content description text for Back button on the action bar -->
+    <string name="back">Back</string>
+    <!-- Action menu title for showing archived conversations -->
+    <string name="action_menu_show_archived">Archived</string>
+    <!-- Action menu title for deleting selected conversations in conversation list -->
+    <string name="action_delete">Delete</string>
+    <!-- Action menu title for archiving selected conversations in conversation list -->
+    <string name="action_archive">Archive</string>
+    <!-- Action menu title for unarchiving selected conversations in conversation list -->
+    <string name="action_unarchive">Unarchive</string>
+    <!-- Action menu title for turning off notification for the selected conversations in conversation list -->
+    <string name="action_notification_off">Turn off notifications</string>
+    <!-- Action menu title for turning on notification for the selected conversations in conversation list -->
+    <string name="action_notification_on">Turn on notifications</string>
+    <!-- Action menu title for adding the contacts for the selected conversations in conversation list -->
+    <string name="action_add_contact">Add contact</string>
+    <!-- Action menu title for downloading failed message selected in conversation -->
+    <string name="action_download">Download</string>
+    <!-- Action menu title for sending failed message selected in conversation -->
+    <string name="action_send">Send</string>
+    <!-- Action menu title for deleting failed message selected in conversation -->
+    <string name="action_delete_message">Delete</string>
+
+    <string name="delete_message_confirmation_dialog_title">Delete this message?</string>
+    <string name="delete_message_confirmation_dialog_text">This action cannot be undone.</string>
+    <string name="delete_message_confirmation_button">Delete</string>
+
+    <!-- Alert dialog title to accept or decline deleting conversation(s). -->
+    <plurals name="delete_conversations_confirmation_dialog_title">
+        <item quantity="one">Delete this conversation?</item>
+        <item quantity="other">Delete these conversations?</item>
+    </plurals>
+
+    <!-- Alert dialog accept deleting this conversation button. -->
+    <string name="delete_conversation_confirmation_button">Delete</string>
+    <!-- Alert dialog decline deleting this conversation button. -->
+    <string name="delete_conversation_decline_button">Cancel</string>
+
+    <!-- Hint text for the recipient chips text box when it's empty -->
+    <string name="recipient_hint">To</string>
+    <!-- Action menu title for multiple selection in gallery image picker -->
+    <string name="action_multiselect">Select multiple images</string>
+    <!-- Action menu title for confirming multiple selection in gallery image picker -->
+    <string name="action_confirm_multiselect">Confirm selection</string>
+    <!-- Text for showing there are more items in the attachments than is shown (e.g. "+2") -->
+    <string name="attachment_more_items">+<xliff:g id="count">%d</xliff:g></string>
+    <!-- Failed to start recording audio -->
+    <string name="audio_recording_start_failed">Can\'t record audio. Try again.</string>
+    <!-- Failed to replay recorded audio -->
+    <string name="audio_recording_replay_failed">Can\'t play audio. Try again.</string>
+    <!-- Error occurred while recording audio -->
+    <string name="audio_recording_error"> Couldn\'t save audio. Try again.</string>
+    <!-- Hint text on the audio recorder that instructs user how to start recording -->
+    <string name="audio_picker_hint_text">Tap &amp; hold</string>
+
+    <!-- An enumeration comma for separating multiple names in notifications. [CHAR LIMIT=2] -->
+    <string name="enumeration_comma">,\u0020</string>
+    <!-- Separator between parts of a notification in each line of an inboxStyle notification. [CHAR LIMIT=2] -->
+    <string name="notification_separator">\u0020\u0020</string>
+    <!-- Separator between title and content in notification ticker -->
+    <string name="notification_ticker_separator">:\u0020</string>
+    <!-- Separator between title and content in notifications -->
+    <string name="notification_space_separator">\u0020\u0020</string>
+    <!-- Shown in notifications when there's a picture. [CHAR LIMIT=25] -->
+    <string name="notification_picture">Picture</string>
+    <!-- Shown in notifications when there's an audio clip. [CHAR LIMIT=25] -->
+    <string name="notification_audio">Audio clip</string>
+    <!-- Shown in notifications when there's a video. [CHAR LIMIT=25] -->
+    <string name="notification_video">Video</string>
+    <!-- Shown in notifications when there's a vcard. [CHAR LIMIT=25] -->
+    <string name="notification_vcard">Contact card</string>
+    <!-- Notification action label for download MMS when set to manual downloads. [CHAR LIMIT=15] -->
+    <string name="notification_download_mms">Download</string>
+    <!-- Notification action label for SMS reply (visible on wearable device only). [CHAR LIMIT=15] -->
+    <string name="notification_reply_via_sms">Reply via SMS</string>
+    <!-- Notification action label for MMS reply (visible on wearable device only). [CHAR LIMIT=15] -->
+    <string name="notification_reply_via_mms">Reply via MMS</string>
+    <!-- Notification voice reply prompt (visible on wearable device only). [CHAR LIMIT=15] -->
+    <string name="notification_reply_prompt">Reply</string>
+    <string name="ellipsis" translatable="false">...</string>
+    <!-- The bottom line on a wearable notification that shows how many participants in the conversation -->
+    <plurals name="wearable_participant_count">
+        <item quantity="one"><xliff:g id="count">%d</xliff:g> participant</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> participants</item>
+    </plurals>
+    <!-- Shown in the Android Wear conversation log as the sender for outgoing messages,
+         when we don't know the user's real name (e.g. no "Me" contact on the phone). -->
+    <string name="unknown_self_participant">Me</string>
+
+    <!-- The text of the toast/snack message shown when a contact is blocked -->
+    <string name="blocked_toast_message">Contact blocked &amp; archived</string>
+    <!-- The text of the toast/snack message shown when a contact is unblocked -->
+    <string name="unblocked_toast_message">Contact unblocked &amp; unarchived</string>
+    <!-- The text of the toast/snack message shown when the selected conversation(s) are archived.
+         Displays the number of converstions archived -->
+    <string name="archived_toast_message"><xliff:g id="count">%d</xliff:g> archived</string>
+    <!-- The text of the toast/snack message shown when the selected conversation(s) are unarchived.
+         Displays the number of conversations unarchived -->
+    <string name="unarchived_toast_message"><xliff:g id="count">%d</xliff:g> unarchived</string>
+    <!-- The text of the toast/snack message shown when a notifications turned off for selected conversations -->
+    <string name="notification_off_toast_message">Notifications turned off</string>
+    <!-- The text of the toast/snack message shown when a notifications turned on for selected conversations -->
+    <string name="notification_on_toast_message">Notifications turned on</string>
+
+    <!-- Toast shown when the user tries to send a message, and then sets Bugle as the default SMS app. -->
+    <string name="toast_after_setting_default_sms_app_for_message_send">All set. Tap Send again.</string>
+    <!-- Toast shown when the user successfully sets Bugle as the default SMS app. -->
+    <string name="toast_after_setting_default_sms_app">Messaging successfully set as the default SMS app.</string>
+
+    <!-- Accessibility : Content descriptinon for ImageButtons and ImageViews -->
+    <plurals name="attachment_preview_close_content_description">
+        <item quantity="one">Discard attachment</item>
+        <item quantity="other">Discard attachments</item>
+    </plurals>
+    <string name="audio_attachment_content_description">Audio attachment</string>
+    <string name="audio_play_content_description">Play audio attachment</string>
+    <string name="audio_pause_content_description">Pause</string>
+
+    <!-- Accessibility announcement for an incoming message -->
+    <string name="incoming_message_announcement">Message from <xliff:g id="sender">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>.</string>
+    <!-- Accessibility description for conversation list for 1:1 conversations -->
+    <string name="one_on_one_incoming_failed_message_prefix">Failed message from <xliff:g id="sender">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="one_on_one_incoming_successful_message_prefix">Message from <xliff:g id="sender">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="one_on_one_outgoing_draft_message_prefix">Unsent message to <xliff:g id="contact">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="one_on_one_outgoing_sending_message_prefix">Sending message to <xliff:g id="contact">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="one_on_one_outgoing_failed_message_prefix">Failed message to <xliff:g id="contact">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="one_on_one_outgoing_successful_message_prefix">Message to <xliff:g id="contact">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <!-- Accessibility description for conversation list for group conversations -->
+    <string name="group_incoming_failed_message_prefix">Failed message from <xliff:g id="sender">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>. <xliff:g id="groupInfo">%4$s</xliff:g>.</string>
+    <string name="group_incoming_successful_message_prefix">Message from <xliff:g id="sender">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>. <xliff:g id="groupInfo">%4$s</xliff:g>.</string>
+    <string name="group_outgoing_draft_message_prefix">Unsent message to <xliff:g id="group">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="group_outgoing_sending_message_prefix">Sending message to <xliff:g id="group">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="group_outgoing_failed_message_prefix">Failed message to <xliff:g id="group">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <string name="group_outgoing_successful_message_prefix">Message to <xliff:g id="group">%1$s</xliff:g>: <xliff:g id="message">%2$s</xliff:g>. Time: <xliff:g id="time">%3$s</xliff:g>.</string>
+    <!-- Accessibility description for conversation list for failed messages -->
+    <string name="failed_message_content_description">Failed message. Tap to retry.</string>
+
+    <!-- Accessibility name for a group conversation -->
+    <string name="group_conversation_description">Conversation with <xliff:g id="participants">%s</xliff:g></string>
+
+    <!-- Accessibility : text read on the small X icon on the subject editor -->
+    <string name="delete_subject_content_description">Delete subject</string>
+
+    <string name="camera_switch_to_video_mode">Capture video</string>
+    <string name="camera_switch_to_still_mode">Capture a still image</string>
+    <string name="camera_take_picture">Take picture</string>
+    <string name="camera_start_recording">Start recording video</string>
+    <string name="camera_switch_full_screen">Switch to full screen camera</string>
+    <string name="camera_switch_camera_facing">Switch between front and back camera</string>
+    <string name="camera_stop_recording">Stop recording and attach video</string>
+    <string name="camera_cancel_recording">Stop recording video</string>
+
+    <string name="photo_view_activity_title">Messaging photos</string>
+    <plurals name="photos_saved_to_album">
+        <item quantity="one"><xliff:g id="quantity">%d</xliff:g> photo saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+        <item quantity="other"><xliff:g id="quantity">%d</xliff:g> photos saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="videos_saved_to_album">
+        <item quantity="one"><xliff:g id="quantity">%d</xliff:g> video saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+        <item quantity="other"><xliff:g id="quantity">%d</xliff:g> videos saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_album">
+        <item quantity="one"><xliff:g id="quantity">%d</xliff:g> attachment saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+        <item quantity="other"><xliff:g id="quantity">%d</xliff:g> attachments saved to \"<xliff:g id="albumName">%s</xliff:g>\" album</item>
+    </plurals>
+    <plurals name="attachments_saved_to_downloads">
+        <item quantity="one"><xliff:g id="quantity">%d</xliff:g> attachment saved to \"Downloads\"</item>
+        <item quantity="other"><xliff:g id="quantity">%d</xliff:g> attachments saved to \"Downloads\"</item>
+    </plurals>
+    <plurals name="attachments_saved">
+        <item quantity="one"><xliff:g id="quantity">%d</xliff:g> attachment saved</item>
+        <item quantity="other"><xliff:g id="quantity">%d</xliff:g> attachments saved</item>
+    </plurals>
+    <plurals name="attachment_save_error">
+        <item quantity="one">Couldn\'t save <xliff:g id="quantity">%d</xliff:g> attachment</item>
+        <item quantity="other">Couldn\'t save <xliff:g id="quantity">%d</xliff:g> attachments</item>
+    </plurals>
+    <!-- Description shown in the download manager for an attachment that the user manually saved -->
+    <string name="attachment_file_description">Saved MMS attachment</string>
+
+    <!-- Title for the preferences/settings activity -->
+    <string name="settings_activity_title">Settings</string>
+    <!-- Title for the archived conversations activity -->
+    <string name="archived_activity_title">Archived</string>
+    <!-- Action title: Close -->
+    <string name="action_close">Close</string>
+    <!-- Preference category: MMS messaging -->
+    <string name="mms_messaging_category_pref_title">MMS</string>
+    <!-- Preference category: Advanced -->
+    <string name="advanced_category_pref_title">Advanced</string>
+    <!-- Preference category: Debug -->
+    <string name="debug_category_pref_title">Debug</string>
+    <!-- Title for the preference for whether or to notify the user of new messages -->
+    <string name="notifications_enabled_pref_title">Notifications</string>
+    <!-- Title for the notification sound preference -->
+    <string name="notification_sound_pref_title">Sound</string>
+    <!-- What to display in the settings screen for Ringtone when the user chooses "silent" [CHAR LIMIT=100]-->
+    <string name="silent_ringtone">Silent</string>
+    <!-- Title for the preference for whether or not to vibrate with notifications -->
+    <string name="notification_vibrate_pref_title">Vibrate</string>
+    <string name="blocked_pref_title">Blocked</string>
+    <!-- Title for the preference for whether or not to request/show delivery reports for SMS -->
+    <string name="delivery_reports_pref_title">SMS delivery reports</string>
+    <string name="delivery_reports_pref_summary">Request a delivery report for each SMS you send</string>
+    <string name="auto_retrieve_mms_pref_title">Auto-retrieve</string>
+    <string name="auto_retrieve_mms_pref_summary">Automatically retrieve MMS messages</string>
+    <!-- Title for the preference for whether or not to auto-retrieve MMS when roaming -->
+    <string name="auto_retrieve_mms_when_roaming_pref_title">Roaming auto-retrieve</string>
+    <string name="auto_retrieve_mms_when_roaming_pref_summary">Automatically retrieve MMS when roaming</string>
+    <string name="group_mms_pref_title">Group messaging</string>
+    <string name="group_mms_pref_summary">Use MMS to send a single message when there are multiple recipients</string>
+    <!-- Preference title: SMS disabled (Messaging is not default SMS app) -->
+    <string name="sms_disabled_pref_title">Default SMS app</string>
+    <!-- Preference title: SMS enabled (Messaging is the default SMS app) -->
+    <string name="sms_enabled_pref_title">Default SMS app</string>
+    <!-- Preference summary: Current default SMS app -->
+    <string name="default_sms_app"><xliff:g id="app_name">%s</xliff:g></string>
+    <!-- Preference title: MMS phone number -->
+    <string name="mms_phone_number_pref_title">Your phone number</string>
+    <!-- Display text for phone number preference when the number is unknown -->
+    <string name="unknown_phone_number_pref_display_value">Unknown</string>
+    <!-- Title for the preference for playing a message send sound -->
+    <string name="send_sound_pref_title">Outgoing message sounds</string>
+
+    <string name="dump_sms_pref_title">Dump SMS</string>
+    <string name="dump_sms_pref_summary">Dump received SMS raw data into external storage file</string>
+    <string name="dump_mms_pref_title">Dump MMS</string>
+    <string name="dump_mms_pref_summary">Dump received MMS raw data into external storage file</string>
+    <!-- Strings for dump sms/mms dialog -->
+    <string name="email_sms_mms_dump_file_subject" translatable="false">SMS dump file</string>
+    <string name="email_sms_mms_dump_file_chooser_title" translatable="false">Email SMS dump</string>
+    <string name="load_sms_mms_from_dump_file_dialog_title" translatable="false">Load dump file</string>
+    <string name="email_sms_mms_from_dump_file_dialog_title" translatable="false">Email dump file</string>
+    <string name="wireless_alerts_title">Wireless alerts</string>
+
+    <!-- Title of long press menu on an individual message. -->
+    <string name="message_context_menu_title">Message options</string>
+    <!-- Menu item to copy message text -->
+    <string name="message_context_menu_copy_text">Copy text</string>
+    <!-- Title of long press menu for details about an individual message. -->
+    <string name="message_context_menu_view_details">View details</string>
+    <!-- Title of long press menu for deleting an individual message. -->
+    <string name="message_context_menu_delete_message">Delete</string>
+    <!-- Title of long press menu for forwarding an individual message. -->
+    <string name="message_context_menu_forward_message">Forward</string>
+    <!-- Title of "Message details" dialog -->
+    <string name="message_details_title">Message details</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="message_type_label">Type:\u0020</string>
+    <!-- "Type" value in "Message details" dialog -->
+    <string name="text_message">Text message</string>
+    <!-- "Type" value in "Message details" dialog -->
+    <string name="multimedia_message">Multimedia message</string>
+    <!-- Label in "Message details" dialog showing who sent the message. -->
+    <string name="from_label">From:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="to_address_label">To:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="sent_label">Sent:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="received_label">Received:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="subject_label">Subject:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="message_size_label">Size:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="priority_label">Priority:\u0020</string>
+    <!-- Label in "Message details" dialog -->
+    <string name="sim_label">SIM:\u0020</string>
+    <!-- "Priority" value in "Message details" dialog -->
+    <string name="priority_high">High</string>
+    <!-- "Priority" value in "Message details" dialog -->
+    <string name="priority_normal">Normal</string>
+    <!-- "Priority" value in "Message details" dialog -->
+    <string name="priority_low">Low</string>
+    <!-- SIM identified using the slot number. e.g. SIM 1 -->
+    <string name="sim_slot_identifier">SIM <xliff:g id="sim_slot_number">%s</xliff:g></string>
+    <!-- Sender to be used if the sender address has been hidden -->
+    <string name="hidden_sender_address">Hidden sender address</string>
+    <!-- Shows when the user attempts to send message while some attachment(s) haven't finished loading -->
+    <string name="cant_send_message_while_loading_attachments">Can\'t send message while loading attachments.</string>
+    <!-- Notifies the user when an attachment fails to load -->
+    <string name="fail_to_load_attachment">Can\'t load attachment. Try again.</string>
+    <!-- Shows when the user attempts to send message when there is no active subscription -->
+    <string name="cant_send_message_without_active_subscription">Network is not ready. Try again.</string>
+
+    <string name="chips_text_delete_button_content_description">Delete text</string>
+    <string name="numeric_text_keyboard_toggle_button_content_description">Switch between entering text and numbers</string>
+    <string name="add_more_participants_button_content_description">Add more participants</string>
+    <string name="confrim_participants_button_content_description">Confirm participants</string>
+    <string name="start_new_conversation">Start new conversation</string>
+    <!-- Content description for the checkbox when selecting an item in the gallery -->
+    <string name="gallery_checkbox_content_description">Select this item</string>
+    <string name="video_thumbnail_view_play_button_content_description">Play video</string>
+    <!-- Option menu item in the conversation view that lets user view list of conversation participants and change options -->
+    <string name="action_people_and_options">People &amp; options</string>
+    <!-- Option menu item in the conversation list view and conversation view that shows debug menu -->
+    <string name="action_debug_options">Debug</string>
+    <!-- Title for the "People and Options" activity -->
+    <string name="people_and_options_activity_title">People &amp; options</string>
+    <!-- Title for the general settings section in the "People and options" activity -->
+    <string name="general_settings_title">General</string>
+    <!-- Title for the list of participants in the "People and options" activity -->
+    <string name="participant_list_title">People in this conversation</string>
+    <!-- Title for the phone call button in the action bar that lets the user call a participant in an SMS conversation -->
+    <string name="action_call">Make a call</string>
+    <!-- The hint text shown in the message compose input box prompting the user to send a message -->
+    <string name="compose_message_view_hint_text">Send message</string>
+    <!-- The hint text shown in the message compose input box prompting the user to send a message when there are multiple SIMs. -->
+    <string name="compose_message_view_hint_text_multi_sim">Send message&lt;br/&gt;&lt;small&gt;from <xliff:g id="sim_name">%s</xliff:g>&lt;/small&gt;</string>
+    <!-- The hint text shown in the message compose input box when photo(s) is attached -->
+    <plurals name="compose_message_view_hint_text_photo">
+        <item quantity="one">Send photo</item>
+        <item quantity="other">Send photos</item>
+    </plurals>
+    <!-- The hint text shown in the message compose input box when audio recording(s) is attached -->
+    <plurals name="compose_message_view_hint_text_audio">
+        <item quantity="one">Send audio</item>
+        <item quantity="other">Send audios</item>
+    </plurals>
+    <!-- The hint text shown in the message compose input box when video(s) is attached -->
+    <plurals name="compose_message_view_hint_text_video">
+        <item quantity="one">Send video</item>
+        <item quantity="other">Send videos</item>
+    </plurals>
+    <!-- The hint text shown in the message compose input box when vcard(s) is attached -->
+    <plurals name="compose_message_view_hint_text_vcard">
+        <item quantity="one">Send contact card</item>
+        <item quantity="other">Send contact cards</item>
+    </plurals>
+    <!-- The hint text shown in the message compose input box when a single unknown attachment, or multiple different attachments are attached -->
+    <plurals name="compose_message_view_hint_text_attachments">
+        <item quantity="one">Send attachment</item>
+        <item quantity="other">Send attachments</item>
+    </plurals>
+    <!-- Announcement after the user adds or removes an attachment -->
+    <plurals name="attachment_changed_accessibility_announcement">
+        <item quantity="zero">No attachments selected</item>
+        <item quantity="one">One attachment ready to send</item>
+        <item quantity="other"><xliff:g id="attachment_count">%d</xliff:g> attachments ready to send</item>
+    </plurals>
+    <!-- Action menu title in the HelpAndFeedbackFragment to let users send feedback -->
+    <string name="menu_send_feedback">Send feedback</string>
+    <!-- Action menu title in the HelpAndFeedbackFragment to let users view the app in the Google Play Store -->
+    <string name="menu_view_in_store">View in Google Play Store</string>
+    <!-- Action menu title in the HelpAndFeedbackFragment to let users view the version of Bugle -->
+    <string name="menu_version_info">Version info</string>
+    <!-- The format of the subtitle of the help activity. -->
+    <string name="subtitle_format_for_version_number">Version %1$s</string>
+
+    <!--  Action menu title to let users view open source license -->
+    <string name="menu_license">Open source licenses</string>
+    <!-- Title for the per-conversation preference for whether or to notify the user of new messages -->
+    <string name="notifications_enabled_conversation_pref_title">Notifications</string>
+    <!-- Reached MMS message attachment limit -->
+    <string name="mms_attachment_limit_reached">Attachment limit reached</string>
+    <!-- Message attachment load failed -->
+    <string name="mms_attachment_load_failed">Failed to load attachment.</string>
+    <!-- Alert dialog title to accept or decline adding the given phone number to your contacts. -->
+    <string name="add_contact_confirmation_dialog_title">Add to Contacts?</string>
+    <!-- Alert dialog accept adding the given phone number to your contacts button. -->
+    <string name="add_contact_confirmation">Add Contact</string>
+    <!-- The text shown as a label before the message subject input box -->
+    <string name="compose_message_view_subject_hint_text">Subject</string>
+    <!-- The text shown as a label before the message subject input box -->
+    <string name="conversation_message_view_subject_text">Subject:\u0020</string>
+    <!-- When there's a subject in an mms, the subject + message are shown in a notification -->
+    <string name="notification_subject"><xliff:g id="subject_label">%1$s</xliff:g><xliff:g id="messageText">%2$s</xliff:g></string>
+
+    <!-- Text shown on contact VCard when it's being loaded -->
+    <string name="loading_vcard">Loading contact card</string>
+    <!-- Text shown on contact VCard when it failed to load -->
+    <string name="failed_loading_vcard">Couldn\'t load contact card</string>
+    <!-- Text shown on contact VCard promping the user to tap to view the contact -->
+    <string name="vcard_tap_hint">View contact card</string>
+    <!-- VCard display name for when there's more than one contact, e.g. "2 contact cards" -->
+    <plurals name="vcard_multiple_display_name">
+        <!-- quantity="one" is not needed by the app, but it keeps the translation pipeline happy. -->
+        <item quantity="one"><xliff:g id="count">%d</xliff:g> contact</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> contacts</item>
+    </plurals>
+    <!-- Title for the activity that shows details of VCards -->
+    <string name="vcard_detail_activity_title">Contact cards</string>
+    <!-- VCard label for displaying birthdays -->
+    <string name="vcard_detail_birthday_label">Birthday</string>
+    <!-- VCard label for describing the Notes field of a contact. -->
+    <string name="vcard_detail_notes_label">Notes</string>
+    <!-- Title for the message forwarding dialog -->
+    <string name="forward_message_activity_title">Forward message</string>
+    <!-- Title for the message reply dialog -->
+    <string name="reply_activity_title">Reply</string>
+
+    <!-- String to show when eliding the number of participants in a conversation due to length (used when there is one extra) -->
+    <string name="plus_one">+1</string>
+
+    <!-- String to show when eliding the number of participants in a conversation due to length (used when there is more than one extra) -->
+    <string name="plus_n">+%d</string>
+
+    <!-- Toast error shown when SMS functionality is disabled -->
+    <string name="sms_disabled">SMS disabled</string>
+
+    <!-- Snackbar message that indicates users must set Messaging as their
+         default SMS application in order to send messages -->
+    <string name="requires_default_sms_app_to_send">To send, set Messaging as the default SMS app</string>
+
+    <!-- Snackbar message that indicates users must set Messaging as their default SMS application in order to perform the requested action. -->
+    <string name="requires_default_sms_app">Set Messaging as the default SMS app</string>
+
+    <!-- Snackbar button text to switch default SMS apps shown in snackbar. -->
+    <string name="requires_default_sms_change_button">Change</string>
+
+    <!-- Toast message that indicates uses must set Messaging as their
+         default SMS application in order to receive replies in the app. -->
+    <string name="recommend_set_default_sms_app">To receive messages, set Messaging as the default SMS app</string>
+
+    <!-- Toast message that indicates no preferred SIM was selected for sending the message -->
+    <string name="no_preferred_sim_selected">No preferred SIM selected for sending SMS messages</string>
+
+    <!-- Dialog message that indicates user must be granted permissions from the phone owner to
+         send SMS messages. -->
+    <string name="requires_sms_permissions_message">This app isn\'t allowed by the device owner.</string>
+    <!-- Dialog button text that closes the application. -->
+    <string name="requires_sms_permissions_close_button">OK</string>
+
+    <!-- Toast text when creating a conversation with more participants than MMS/SMS config permits -->
+    <string name="too_many_participants">Too many participants in a conversation</string>
+    <!-- Toast text when creating a conversation with an invalid participant -->
+    <plurals name="add_invalid_contact_error">
+        <item quantity="one">Invalid contact</item>
+        <item quantity="other">Invalid contacts</item>
+    </plurals>
+    <!-- Error toast message shown when a camera image failed to attach to the message -->
+    <string name="camera_media_failure">Couldn\'t load camera image</string>
+
+    <!-- A message prefix to indicate the message was sent by the user. -->
+    <string name="conversation_list_item_view_sent_from_you_prefix">You:\u0020</string>
+
+    <!-- A message prefix to indicate the message was sent by another user in a group conversation. -->
+    <string name="conversation_list_item_view_sent_from_other_prefix"><xliff:g id="firstNameOfSender">%s</xliff:g>:\u0020</string>
+
+    <!-- A message in conversation list view to indicate that the snipit text and preview is from an unsent draft. -->
+    <string name="conversation_list_item_view_draft_message">Draft</string>
+
+    <!-- String to show in the conversation list view when there are no messages. -->
+    <string name="conversation_list_empty_text">Once you start a new conversation, you’ll see it listed here</string>
+    <!-- String to show in the archived conversation list view when there are no messages. -->
+    <string name="archived_conversation_list_empty_text">Archived conversations appear here</string>
+    <!-- String to show in the conversation list view when we haven't synchronized the SMS database yet -->
+    <string name="conversation_list_first_sync_text">Loading conversations&#8230;</string>
+
+    <!-- Shown in conversation as the snippet when there is no text and an attached picture. [CHAR LIMIT=25] -->
+    <string name="conversation_list_snippet_picture">Picture</string>
+    <!-- Shown in conversation as the snippet when there is no text and an attached audio clip. [CHAR LIMIT=25] -->
+    <string name="conversation_list_snippet_audio_clip">Audio clip</string>
+    <!-- Shown in conversation as the snippet when there is no text and an attached video. [CHAR LIMIT=25] -->
+    <string name="conversation_list_snippet_video">Video</string>
+    <!-- Shown in conversation as the snippet when there is no text and an attached vcard. [CHAR LIMIT=25] -->
+    <string name="conversation_list_snippet_vcard">Contact card</string>
+
+    <!-- Indicates that the current message will be sent via MMS -->
+    <string name="mms_text">MMS</string>
+
+    <!-- The string we display with the snack bar notification (very similar to toast) to undo the action that the notification is about. -->
+    <string name="snack_bar_undo">Undo</string>
+    <string name="snack_bar_retry">Retry</string>
+
+    <!-- Hint text shown on the contact list when there's no contacts -->
+    <string name="contact_list_empty_text">Enter a contact name or phone number to start a new message</string>
+
+    <!-- Action menu title for blocking and archiving selected conversations in conversation list -->
+    <string name="action_block">Block</string>
+
+    <!-- Label of block contact item in People & Options for 1:1 conversation -->
+    <string name="block_contact_title">Block <xliff:g id="destination">%s</xliff:g></string>
+
+    <!-- Label of unblock contact item in People & Options for 1:1 conversation -->
+    <string name="unblock_contact_title">Unblock <xliff:g id="destination">%s</xliff:g></string>
+
+    <!-- Title of block confirmation dialog -->
+    <string name="block_confirmation_title">Block <xliff:g id="destination">%s</xliff:g>?</string>
+
+    <!-- Text describing what happens when user is blocked via the block actionbar action -->
+    <string name="block_confirmation_message">You\'ll continue to receive messages from this number but won\'t be notified anymore. This conversation will be archived.</string>
+
+    <!-- The title of the list of blocked contacts -->
+    <string name="blocked_contacts_title">Blocked contacts</string>
+
+    <!-- The message in a blocked contact item which indicates tapping will unblock -->
+    <string name="tap_to_unblock_message">UNBLOCK</string>
+
+    <!-- Action menu title for viewing the list of blocked contacts -->
+    <string name="view_blocked_contacts_title">Blocked contacts</string>
+
+    <!-- Content description for the button in gallery media picker to pick an image from the document library -->
+    <string name="pick_image_from_document_library_content_description">Choose image from document library</string>
+    <!-- Accessibility toast shown when a message is sending. -->
+    <string name="sending_message">Sending message</string>
+    <!-- Accessibility toast shown when a message is sent. -->
+    <string name="send_message_success">Message sent</string>
+    <!-- Error toast shown when an MMS could not be sent because mobile data was disabled. -->
+    <string name="send_message_failure_no_data">Cellular data is turned off. Check your settings.</string>
+    <!-- Error toast shown when a message could not be sent because of airplane mode. -->
+    <string name="send_message_failure_airplane_mode">Can\'t send messages in Airplane mode</string>
+    <!-- Error toast shown when a message could not be sent because of unspecified error. -->
+    <string name="send_message_failure">Message could not be sent</string>
+
+    <!-- Accessibility toast shown when an MMS is downloaded. -->
+    <string name="download_message_success">Message downloaded</string>
+    <!-- Error toast shown when an MMS could not be downloaded because mobile data was disabled. -->
+    <string name="download_message_failure_no_data">Cellular data is turned off. Check your settings.</string>
+    <!-- Error toast shown when a message could not be downloaded because of airplane mode. -->
+    <string name="download_message_failure_airplane_mode">Can\'t download messages in Airplane mode</string>
+    <!-- Error toast shown when a message could not be downloaded because of unspecified error. -->
+    <string name="download_message_failure">Message could not be downloaded</string>
+
+    <!-- Accessibility : content description for numbers -->
+    <string name="content_description_for_number_zero">Zero</string>
+    <string name="content_description_for_number_one">One</string>
+    <string name="content_description_for_number_two">Two</string>
+    <string name="content_description_for_number_three">Three</string>
+    <string name="content_description_for_number_four">Four</string>
+    <string name="content_description_for_number_five">Five</string>
+    <string name="content_description_for_number_six">Six</string>
+    <string name="content_description_for_number_seven">Seven</string>
+    <string name="content_description_for_number_eight">Eight</string>
+    <string name="content_description_for_number_nine">Nine</string>
+
+    <!-- Error message which shows the user a carrier specific error code such as "Unable to send message: xxxxx error 97" -->
+    <string name="carrier_send_error">Can\'t send message with <xliff:g id="carrierName">%1$s</xliff:g>, error <xliff:g id="errorCode">%2$d</xliff:g></string>
+    <string name="carrier_send_error_unknown_carrier">Can\'t send message with unknown carrier, error <xliff:g id="errorCode">%1$d</xliff:g></string>
+
+    <!-- Text prepended to the subject of a forwarded message -->
+    <string name="message_fwd">Fwd: <xliff:g id="subject">%s</xliff:g></string>
+
+    <!-- Detailed MMS failure strings, may need to be adjusted per carrier for TA -->
+    <string name="mms_failure_outgoing_service">Message not sent: service not activated on network</string>
+    <string name="mms_failure_outgoing_address">Message not sent: invalid destination address</string>
+    <string name="mms_failure_outgoing_corrupt">Message not sent: invalid message</string>
+    <string name="mms_failure_outgoing_content">Message not sent: unsupported content</string>
+    <string name="mms_failure_outgoing_unsupported">Message not sent: unsupported message</string>
+    <string name="mms_failure_outgoing_too_large">Message not sent: too large</string>
+
+    <!-- The notification toast text and action button label shown at bottom of screen, for when a new message comes in while the user
+         is in that conversation, but the message list is not scrolled to the bottom -->
+    <string name="in_conversation_notify_new_message_text">New message</string>
+    <string name="in_conversation_notify_new_message_action">View</string>
+
+    <!-- Content description for the message images in a conversation or for the image preview in the conversation list if the lastest message in that conversation contains an image-->
+    <string name="message_image_content_description">Image</string>
+
+    <!-- Text for a toast message notifying the user that we can't find an appropriate application to handle their request -->
+    <string name="activity_not_found_message">Could not find an appropriate application</string>
+
+    <string name="debug_sub_id_spinner_text" translatable="false">SUB Id</string>
+
+    <!-- Accessibility : Content description for deleting a recipient chip. -->
+    <string name="chips_delete_content_description">Remove recipient</string>
+
+    <!-- Label for new message button in share intent dialog -->
+    <string name="share_new_message">New message</string>
+
+    <!-- Label for new message button in share intent dialog -->
+    <string name="share_cancel">Cancel</string>
+
+    <!-- Screen title after user selects APNs setting option -->
+    <string name="apn_edit">Edit access point</string>
+    <!-- Edit access point label summary text when no value has been set -->
+    <string name="apn_not_set">Not set</string>
+    <!-- Edit access point labels: A label the user can give to the APN to allow him to differentiate it from the others -->
+    <string name="apn_name">Name</string>
+    <!-- Edit access point labels: The actual access point name-->
+    <string name="apn_apn">APN</string>
+    <!-- Edit access point labels: -->
+    <string name="apn_mmsc">MMSC</string>
+    <!-- Edit access point labels: The proxy to use for MMS (multimedia messages)-->
+    <string name="apn_mms_proxy">MMS proxy</string>
+    <!-- Edit access point labels: The port on the proxy used for MMS-->
+    <string name="apn_mms_port">MMS port</string>
+    <!-- Edit access point labels: -->
+    <string name="apn_mcc">MCC</string>
+    <!-- Edit access point labels: -->
+    <string name="apn_mnc">MNC</string>
+    <!-- Edit access point labels: The type of APN -->
+    <string name="apn_type">APN type</string>
+    <!-- Edit access point screen menu option to delete this APN -->
+    <string name="menu_delete_apn">Delete APN</string>
+    <!-- APNs screen menu option to create a brand spanking new APN -->
+    <string name="menu_new_apn">New APN</string>
+    <!-- Edit access point screen menu option to save the user's changes for this APN to the persistent storage -->
+    <string name="menu_save_apn">Save</string>
+    <!-- Edit access point screen menu option to discard the user's changes for this APN -->
+    <string name="menu_discard_apn_change">Discard</string>
+    <!-- APN error dialog messages: -->
+    <string name="error_apn_name_empty">The Name field can\'t be empty.</string>
+    <!-- APN error dialog messages: -->
+    <string name="error_apn_empty">The APN can\'t be empty.</string>
+    <!-- APN error dialog messages: -->
+    <string name="error_mcc_not3">MCC field must be 3 digits.</string>
+    <!-- APN error dialog messages: -->
+    <string name="error_mnc_not23">MNC field must be 2 or 3 digits.</string>
+    <!-- The message of dialog indicated restoring default APN settings in progress -->
+    <string name="restore_default_apn">Restoring default APN settings.</string>
+    <!-- APNs screen menu option to reset default APN settings -->
+    <string name="menu_restore_default_apn">Reset to default</string>
+    <!-- APNs screen toast message to inform reset default APN settings is completed -->
+    <string name="restore_default_apn_completed">Reset default APN settings completed.</string>
+    <!-- Name to assign to a Network Access Point that was saved without a name -->
+    <string name="untitled_apn">Untitled</string>
+    <!-- Title for Access Point Names settings -->
+    <string name="sms_apns_title">Access Point Names</string>
+    <!-- Title for Access Point Names settings activity -->
+    <string name="apn_settings">APNs</string>
+    <!-- APNs screen menu option to create a brand spanking new APN -->
+    <string name="menu_new">New APN</string>
+    <!-- Error message for users that aren't allowed to modify Access Point Names settings [CHAR LIMIT=none] -->
+    <string name="apn_settings_not_available">Access Point Name settings are not available for this user</string>
+    <!-- Alert dialog title to copy information displayed in dialog to system clipboard. -->
+    <string name="copy_to_clipboard_dialog_title">Copy to clipboard?</string>
+    <!-- Alert dialog accept to copy information displayed in dialog to system clipboard. -->
+    <string name="copy_to_clipboard">Copy</string>
+    <!-- SIM name incoming message bubbles indicating which SIM the message was delivered to -->
+    <string name="incoming_sim_name_text">to <xliff:g id="sim_name">%s</xliff:g></string>
+
+    <!-- The title for general settings section in the settings activity  -->
+    <string name="general_settings">General</string>
+
+    <!-- The title for advanced settings section in the settings activity  -->
+    <string name="advanced_settings">Advanced</string>
+
+    <!-- The title for general settings activity  -->
+    <string name="general_settings_activity_title">General settings</string>
+
+    <!-- The title for advanced settings activity  -->
+    <string name="advanced_settings_activity_title">Advanced settings</string>
+
+    <!-- The title for sim_specific settings  -->
+    <string name="sim_specific_settings">\"<xliff:g id="sim_name">%s</xliff:g>\" SIM</string>
+
+    <!-- The group MMS choices in settings -->
+    <string name="disable_group_mms">Send individual SMS messages to all recipients. Only you will get any replies</string>
+    <string name="enable_group_mms">Send a single MMS to all recipients</string>
+
+    <!-- SIM number shown in the settings when the number is not known -->
+    <string name="sim_settings_unknown_number">Unknown number</string>
+
+    <!-- Notification title for incoming sms/mms message for secondary user -->
+    <string name="secondary_user_new_message_title">New message</string>
+    <!-- Ticker for notification  for incoming sms/mms message for secondary user -->
+    <string name="secondary_user_new_message_ticker">New message.</string>
+
+    <!-- Content description for the SIM selector button in the conversation -->
+    <string name="sim_selector_button_content_description">SIM selector</string>
+    <!-- Content description for the SIM selector button with selected sim name -->
+    <string name="sim_selector_button_content_description_with_selection"><xliff:g id="sim">%1$s</xliff:g> selected, SIM selector</string>
+
+    <!-- Custom TalkBack description for send button long click event when there's no SIM selector, i.e. edit subject -->
+    <string name="send_button_long_click_description_no_sim_selector">Edit subject</string>
+
+    <!-- Custom TalkBack description for send button long click event when there is SIM selector -->
+    <string name="send_button_long_click_description_with_sim_selector">Select SIM or edit subject</string>
+
+    <!-- Content description for the audio record view -->
+    <string name="audio_record_view_content_description">Tap &amp; hold to record audio</string>
+
+    <!-- Content description for new conversation button in desktop widget -->
+    <string name="widget_new_conversation_content_description">Start new conversation</string>
+    <!-- Content description for widget title -->
+    <string name="widget_title_content_description">Messaging</string>
+    <!-- Displayed name of the desktop widget that shows the list of conversations-->
+    <string name="widget_conversation_list_name">Messaging List</string>
+    <!-- Displayed name of the desktop widget that shows a single conversation-->
+    <string name="widget_conversation_name">Messaging</string>
+    <!-- Content description for new message button in desktop widget -->
+    <string name="widget_new_message_content_description">New message</string>
+    <!-- Content description for conversation list button in desktop widget -->
+    <string name="widget_conversation_list_content_description">Conversation list</string>
+    <!-- Shown when loading conversations in the widget -->
+    <string name="loading_conversations">Loading conversations</string>
+    <!-- Shown when loading messages in the widget -->
+    <string name="loading_messages">Loading messages</string>
+    <!-- Displayed at the end of the conversation list in the widget. Tapping on this will open bugle home activity. [CHAR LIMIT=35] -->
+    <string name="view_more_conversations">View more conversations</string>
+    <!-- Displayed at the beginning of the message list in the widget. Tapping on this will open bugle home activity. [CHAR LIMIT=35] -->
+    <string name="view_more_messages">View more messages</string>
+    <!-- Toast message telling the user a conversation has been deleted -->
+    <string name="conversation_deleted">Conversation deleted</string>
+    <!-- Displayed when user adds a new conversation widget. Tapping on the widget in this
+          mode will bring user to the conversation selection screen -->
+    <string name="tap_to_configure">Conversation deleted. Tap to show a different Messaging conversation</string>
+
+    <!-- Toast message telling the user that someone was blocked -->
+    <string name="update_destination_blocked">Blocked</string>
+    <!-- Toast message telling the user that someone was unblocked -->
+    <string name="update_destination_unblocked">Unblocked</string>
+    <string name="db_full">Storage space is low. Some data may be lost.</string>
+
+    <!-- Title for attachment chooser activity -->
+    <string name="attachment_chooser_activity_title">Select attachments</string>
+
+    <!-- Action menu title for confirming attachment selection in the attachment chooser -->
+    <string name="action_confirm_selection">Confirm selection</string>
+
+    <!-- Shows the number of selected attachments in the attachment chooser activity -->
+    <string name="attachment_chooser_selection"><xliff:g id="count">%d</xliff:g> selected</string>
+
+    <!-- The dialog message content for when the message is over the attachment limit when composing the message -->
+    <string name="attachment_limit_reached_dialog_message_when_composing">Please remove one or more attachments and try again.</string>
+
+    <!-- The dialog message content for when the message is over the attachment limit when sending the message -->
+    <string name="attachment_limit_reached_dialog_message_when_sending">You can try sending your message, but it might not be delivered unless you remove one or more attachments.</string>
+
+    <!-- The dialog message content for when the message is over the attachment limit when sending the message -->
+    <string name="video_attachment_limit_exceeded_when_sending">You can only send one video per message.  Please remove additional videos and try again.</string>
+
+    <!-- The dialog message content for when the message load failed -->
+    <string name="attachment_load_failed_dialog_message">Messaging failed to load attachment.</string>
+
+    <!-- The option to send the message anyway when the user is presented with the warning that the attachment size might be over limit -->
+    <string name="attachment_limit_reached_send_anyway">Send anyway</string>
+
+    <!-- Toast message telling the user a conversation with a recipient could not be found or created -->
+    <string name="conversation_creation_failure">Could not start conversation</string>
+
+    <!-- When converting html to text link urls are inlined.  This specifies how the link should be
+    displayed.  For example, a link "click here" which navigates to "www.google.com" would have
+    text="click here" and url="www.google.com", using the below format to create "click here (www.google.com)" -->
+    <string name="link_display_format"><xliff:g id="text">%1$s</xliff:g> (<xliff:g id="url">%2$s</xliff:g>)</string>
+
+    <!-- The accessibility text read when the sim chooser pops up to read the current selected sim -->
+    <string name="selected_sim_content_message"><xliff:g id="selected_sim">%s</xliff:g> selected</string>
+
+    <string name="work_directory_display_name">Work Profile contacts</string>
+
+    <!-- When making a call to emergency numbers, show this toast -->
+    <string name="disallow_emergency_call">Can\'t make a voice call to emergency services here.</string>
+</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..6f9be47
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,650 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by BugleBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="BugleBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+
+    <!-- Application theme. -->
+    <style name="BugleTheme" parent="BugleBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+         <item name="android:dropDownListViewStyle">@style/DropDownListViewStyle</item>
+         <item name="colorPrimary">@color/action_bar_background_color</item>
+         <item name="colorPrimaryDark">@color/action_bar_background_color_dark</item>
+         <item name="colorAccent">@color/action_bar_background_color</item>
+         <item name="android:textColorHighlight">@color/text_highlight_color</item>
+         <item name="actionBarStyle">@style/BugleActionBar</item>
+         <item name="apnPreferenceStyle">@style/ApnPreference</item>
+    </style>
+
+    <style name="BugleTheme.ConversationActivity"
+        parent="@style/BugleTheme.ConversationActivityBase">
+    </style>
+
+    <style name="BugleTheme.ConversationActivityBase" parent="BugleTheme">
+        <item name="android:windowBackground">@color/conversation_background</item>
+        <item name="windowActionBarOverlay">true</item>
+        <item name="android:fastScrollPreviewBackgroundLeft">@drawable/contacts_fastscroll_label_left</item>
+        <item name="android:fastScrollPreviewBackgroundRight">@drawable/contacts_fastscroll_label_right</item>
+    </style>
+
+    <style name="BugleTheme.DialogActivity" parent="@style/Theme.AppCompat.Light.Dialog">
+    </style>
+
+    <style name="BugleTheme.ConversationListActivity" parent="BugleTheme">
+        <item name="android:windowBackground">@android:color/background_light</item>
+    </style>
+
+    <style name="BugleTheme.ArchivedConversationListActivity" parent="BugleTheme.ConversationListActivity">
+        <item name="colorPrimary">@color/archived_conversation_action_bar_background_color</item>
+        <item name="colorPrimaryDark">@color/archived_conversation_action_bar_background_color_dark</item>
+    </style>
+
+    <style name="BugleTheme.SettingsActivity" parent="BugleTheme">
+        <item name="android:textSize">@dimen/settings_list_text_size</item>
+    </style>
+
+    <style name="Invisible" parent="BugleBaseTheme">
+        <item name="android:windowBackground">@null</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+        <item name="android:windowDisablePreview">true</item>
+        <item name="android:windowNoDisplay">true</item>
+    </style>
+
+    <style name="Translucent" parent="BugleBaseTheme">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+        <item name="android:windowDisablePreview">true</item>
+    </style>
+
+    <style name="BugleActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid">
+        <item name="height">@dimen/action_bar_height</item>
+        <item name="displayOptions">showTitle</item>
+        <item name="titleTextStyle">@style/BugleActionBarTitleTextStyle</item>
+    </style>
+
+    <style name="BugleActionBarTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
+      <item name="android:textColor">@color/action_bar_title_text_color</item>
+      <item name="android:textSize">@dimen/action_bar_text_size</item>
+      <item name="android:lines">1</item>
+    </style>
+
+    <style name="ConversationActionBarTitleTextStyle" parent="BugleActionBarTitleTextStyle">
+      <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="BuglePhotoViewTheme" parent="PhotoViewTheme.Translucent">
+        <item name="actionModeShareDrawable">@drawable/ic_share_light</item>
+    </style>
+
+    <style name="ConversationMessageText">
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="ConversationMessage" parent="ConversationMessageText">
+        <item name="android:textSize">@dimen/conversation_message_text_size</item>
+        <item name="android:textColor">@color/message_text</item>
+    </style>
+
+    <style name="ConversationMessageStatus" parent="ConversationMessageText">
+        <item name="android:textSize">@dimen/conversation_status_text_size</item>
+    </style>
+
+    <style name="ConversationMessageTitle" parent="ConversationMessageText">
+        <item name="android:textSize">@dimen/conversation_title_text_size</item>
+        <item name="android:background">@null</item>
+        <item name="android:textColor">@color/message_title_text</item>
+    </style>
+
+    <style name="ConversationMessageInfo" parent="ConversationMessageText">
+        <item name="android:textSize">@dimen/conversation_info_text_size</item>
+        <item name="android:textColor">@color/message_info_text</item>
+    </style>
+
+    <style name="ConversationComposeSendText">
+        <item name="android:textColor">@color/compose_send_text_color</item>
+        <item name="android:singleLine">false</item>
+        <item name="android:textSize">@dimen/conversation_compose_send_text_size</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:paddingLeft">@dimen/compose_message_text_box_padding_side</item>
+        <item name="android:paddingRight">@dimen/compose_message_text_box_padding_side</item>
+        <item name="android:minHeight">@dimen/conversation_message_contact_icon_size</item>
+        <item name="android:maxLines">4</item>
+        <item name="android:background">@null</item>
+        <item name="android:scrollHorizontally">false</item>
+        <item name="android:textCursorDrawable">@null</item>
+        <item name="android:inputType">textShortMessage|textAutoCorrect|textCapSentences|textMultiLine</item>
+    </style>
+
+    <style name="ConversationComposeSubjectText" parent="ConversationComposeSendText">
+        <item name="android:paddingLeft">18dp</item>
+        <item name="android:layout_marginLeft">@dimen/compose_message_subject_cancel_left_margin</item>
+    </style>
+
+    <style name="ContactListItem">
+        <item name="android:textSize">@dimen/contact_list_text_size</item>
+        <item name="android:textColor">@color/contact_list_text_primary</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="ContactListItemDetail">
+        <item name="android:textSize">@dimen/contact_list_detail_text_size</item>
+        <item name="android:textColor">@color/contact_list_text_secondary</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="ContactListItemDetailType" parent="ContactListItemDetail">
+        <item name="android:paddingLeft">12dp</item>
+    </style>
+
+    <style name="ContactListItemDrawableIndicator">
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="RecipientEditTextView">
+        <item name="android:textSize">@dimen/recipient_edit_text_size</item>
+        <item name="android:textColor">@color/compose_contact_text</item>
+        <item name="android:textColorHint">@color/compose_contact_faint_text</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:paddingLeft">4dp</item>
+        <item name="android:paddingRight">4dp</item>
+    </style>
+
+    <style name="PagerTabHeader">
+        <item name="android:textColor">@color/tab_text_color</item>
+        <item name="android:textSize">@dimen/pager_tab_header_text_size</item>
+        <item name="android:background">@null</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+
+    <style name="ContactListAlphabetHeader">
+        <item name="android:textSize">@dimen/contact_list_alphabet_header_text_size</item>
+        <item name="android:textColor">@color/contact_list_alphabet_header</item>
+    </style>
+
+    <style name="AttachmentPreviewMoreItemsText">
+        <item name="android:textSize">@dimen/attachment_preview_more_items_text_size</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
+    <style name="AudioPickerHintText">
+        <item name="android:textSize">@dimen/audio_picker_text_size</item>
+        <item name="android:textColor">@color/audio_picker_hint_text_color</item>
+    </style>
+
+    <style name="AudioPickerTimerText">
+        <item name="android:textSize">@dimen/audio_picker_text_size</item>
+        <item name="android:textColor">@color/audio_picker_timer_text_color</item>
+    </style>
+
+    <style name="AudioAttachmentTimerText">
+        <item name="android:textSize">@dimen/audio_attachment_text_size</item>
+        <item name="android:textColor">@color/audio_attachment_timer_text_color</item>
+        <item name="android:layout_marginRight">16dp</item>
+    </style>
+
+    <style name="AudioAttachmentViewStyle">
+        <item name="android:paddingRight">16dp</item>
+        <item name="android:paddingLeft">16dp</item>
+    </style>
+
+    <style name="ContactPickerHintText">
+        <item name="android:textSize">@dimen/contact_picker_text_size</item>
+        <item name="android:textColor">@color/contact_picker_hint_text_color</item>
+    </style>
+
+    <style name="VcardAttachmentSingleStyle">
+        <item name="android:paddingRight">@dimen/message_text_left_right_padding</item>
+        <item name="android:paddingLeft">@dimen/message_text_left_right_padding</item>
+    </style>
+
+    <style name="MessageVcardAttachmentStyle">
+        <item name="android:paddingRight">@dimen/message_text_left_right_padding</item>
+        <item name="android:paddingLeft">@dimen/message_text_left_right_padding</item>
+    </style>
+
+    <style name="NotificationSenderText">
+        <item name="android:textColor">@color/notification_sender_text</item>
+    </style>
+
+    <style name="NotificationSecondaryText">
+        <item name="android:textColor">@color/notification_secondary_text</item>
+    </style>
+
+    <style name="NotificationTertiaryText">
+        <item name="android:textColor">@color/notification_tertiary_text</item>
+    </style>
+
+    <style name="NotificationSubjectText">
+        <item name="android:textColor">@color/notification_subject_color</item>
+    </style>
+
+    <!-- Styles to support RTL for pre API 17 -->
+    <style name="AttachmentPreviewCloseButtonStyle">
+        <item name="android:gravity">left</item>
+    </style>
+
+    <style name="CameraChooserFrameStyle">
+        <item name="android:paddingLeft">16dp</item>
+    </style>
+
+    <style name="ComposeMessageViewAttachMediaButtonStyle">
+        <item name="android:paddingLeft">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:paddingRight">@dimen/compose_message_attachment_padding_sides</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="ContactListItemViewStyle">
+        <item name="android:paddingLeft">16dp</item>
+    </style>
+
+    <style name="ContactListItemLinearLayoutStyle">
+        <item name="android:paddingLeft">12dp</item>
+        <item name="android:paddingRight">24dp</item>
+    </style>
+
+    <style name="ConversationListItemViewPaddingStyle">
+        <item name="android:paddingLeft">@dimen/conversation_list_item_view_padding</item>
+        <item name="android:paddingRight">@dimen/conversation_list_item_view_padding</item>
+    </style>
+
+    <style name="ConversationListItemViewTextStyle">
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:background">@null</item>
+        <item name="android:textColor">@color/conversation_list_details</item>
+    </style>
+
+    <style name="ConversationListItemViewConversationNameStyle" parent="ConversationListItemViewTextStyle">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/conversation_list_name</item>
+    </style>
+
+    <style name="ConversationListNotificationBellPaddingStyle">
+        <item name="android:paddingRight">@dimen/conversation_list_notification_bell_padding</item>
+    </style>
+
+    <style name="ComposeMessageViewFrameLayoutStyle">
+        <item name="android:paddingRight">@dimen/compose_message_send_button_padding_right</item>
+    </style>
+
+    <style name="ConversationListFragmentStartNewButtonStyle">
+        <item name="android:layout_marginRight">@dimen/fab_left_right_margin</item>
+    </style>
+
+    <style name="GalleryGridItemViewCheckBoxStyle">
+        <item name="android:paddingRight">22dp</item>
+    </style>
+
+    <style name="AttachmentPreviewAttachmentStyle">
+        <item name="android:layout_marginLeft">10dp</item>
+    </style>
+
+    <style name="AudioAttachmentViewPlayPauseButtonStyle">
+        <item name="android:layout_marginRight">16dp</item>
+    </style>
+
+    <style name="ComposeMessageViewDraftViewStyle">
+        <item name="android:layout_marginLeft">53dp</item>
+        <item name="android:layout_marginRight">63dp</item>
+    </style>
+
+    <style name="ConversationMessageViewStyle">
+        <item name="android:paddingLeft">12dp</item>
+        <item name="android:paddingRight">12dp</item>
+    </style>
+
+    <style name="SubjectViewStyle">
+        <item name="android:paddingLeft">@dimen/compose_message_subject_left_padding</item>
+        <item name="android:paddingRight">@dimen/compose_message_subject_right_padding</item>
+    </style>
+
+    <style name="ParticipantListItem">
+        <item name="android:textSize">@dimen/participant_list_text_size</item>
+        <item name="android:textColor">@color/participant_list_text_primary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">left|center_vertical</item>
+    </style>
+
+    <style name="AddContactConfirmationTextStyle" parent="ParticipantListItem">
+        <item name="android:paddingLeft">12dp</item>
+        <item name="android:paddingRight">24dp</item>
+    </style>
+
+    <style name="CopyContactDialogTextStyle" parent="ParticipantListItem">
+        <item name="android:paddingLeft">@dimen/copy_contact_dialog_left_padding</item>
+        <item name="android:paddingRight">@dimen/copy_contact_dialog_right_padding</item>
+    </style>
+
+    <style name="ParticipantListItemDetail">
+        <item name="android:textSize">@dimen/participant_list_detail_text_size</item>
+        <item name="android:textColor">@color/participant_list_text_secondary</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="PeopleListItemViewStyle">
+        <item name="android:paddingLeft">16dp</item>
+    </style>
+
+    <style name="PeopleAndOptionsItemStyle">
+        <item name="android:paddingRight">16dp</item>
+        <item name="android:paddingLeft">16dp</item>
+    </style>
+
+    <style name="PeopleAndOptionsSectionHeader">
+        <item name="android:textSize">@dimen/people_and_options_header_text_size</item>
+        <item name="android:textColor">@color/people_and_options_header_text</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="DropDownListViewStyle" parent="Widget.AppCompat.ListView.DropDown">
+      <item name="android:dividerHeight">0dp</item>
+    </style>
+
+    <style name="ComposeMessageViewMessageBodySizeStyle">
+        <item name="android:textColor">@color/message_body_size_text_color</item>
+        <item name="android:textSize">@dimen/message_body_size_text_size</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:layout_gravity">right|center_vertical</item>
+        <item name="android:paddingRight">@dimen/compose_message_text_box_padding_side</item>
+    </style>
+
+    <style name="MmsIndicatorStyle">
+        <item name="android:textColor">@color/mms_indicator_color</item>
+        <item name="android:textSize">@dimen/mms_indicator_size</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:background">@null</item>
+        <item name="android:paddingRight">@dimen/compose_message_send_button_padding_right</item>
+        <item name="android:paddingTop">@dimen/compose_message_mms_indicator_padding_top</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+    </style>
+
+    <style name="ListEmptyText">
+        <item name="android:textSize">@dimen/list_empty_text_size</item>
+        <item name="android:textColor">@color/list_empty_text</item>
+    </style>
+
+    <style name="LowStorageActionItemStyle">
+        <item name="android:textColor">@color/low_storage_action_item_color</item>
+        <item name="android:textSize">@dimen/low_storage_action_item_text_size</item>
+        <item name="android:singleLine">false</item>
+    </style>
+
+    <style name="SnackBarMessageWrapper">
+        <item name="android:layout_marginLeft">@dimen/snack_bar_left_right_margin</item>
+        <item name="android:layout_marginRight">0dp</item>
+    </style>
+
+    <style name="SnackBarText">
+        <item name="android:textColor">@android:color/white</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">sans-serif</item>
+    </style>
+
+    <style name="SmsDeliverdBadge">
+        <item name="android:layout_marginLeft">4dp</item>
+    </style>
+
+    <style name="appTitleStyle">
+        <item name="android:textColor">@android:color/black</item>
+        <item name="android:textSize">20sp</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="appVersionStyle">
+        <item name="android:textColor">@android:color/black</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="appCopyrightStyle">
+        <item name="android:textColor">@android:color/black</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="ChipDeleteIconStyle">
+        <item name="android:paddingLeft">8dp</item>
+    </style>
+
+    <style name="ChipIconStyle">
+        <item name="android:layout_marginRight">12dp</item>
+    </style>
+
+    <style name="SimSelectorItem">
+        <item name="android:textSize">@dimen/sim_selector_text_size</item>
+        <item name="android:textColor">@color/sim_selector_text_primary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">right</item>
+    </style>
+
+    <style name="SimSelectorItemDetail">
+        <item name="android:textSize">@dimen/sim_selector_detail_text_size</item>
+        <item name="android:textColor">@color/sim_selector_text_secondary</item>
+        <item name="android:background">@null</item>
+        <item name="android:layout_gravity">right</item>
+    </style>
+
+    <style name="SimSelectorItemLinearLayoutStyle">
+        <item name="android:paddingRight">12dp</item>
+    </style>
+
+    <style name="MessageSimIndicator">
+        <item name="android:textSize">@dimen/conversation_status_text_size</item>
+        <item name="android:layout_marginLeft">4dp</item>
+    </style>
+
+    <style name="ColorAccentBlueOverrideStyle">
+        <item name="colorAccent">@color/action_bar_background_color</item>
+    </style>
+
+    <style name="ColorAccentGrayOverrideStyle">
+        <item name="colorAccent">@color/search_view_text_cursor</item>
+    </style>
+
+    <style name="ApnPreference">
+        <item name="android:layout">@layout/apn_preference_layout</item>
+    </style>
+
+    <style name="ApnPreferenceLayoutStyle">
+        <item name="android:paddingLeft">?android:attr/listPreferredItemPaddingStart</item>
+        <item name="android:paddingRight">?android:attr/listPreferredItemPaddingEnd</item>
+    </style>
+
+    <style name="SettingsListItem">
+        <item name="android:textSize">@dimen/settings_list_text_size</item>
+        <item name="android:textColor">@color/settings_list_text_primary</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="SettingsListItemDetail">
+        <item name="android:textSize">@dimen/settings_list_detail_text_size</item>
+        <item name="android:textColor">@color/settings_list_text_secondary</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="GroupMmsSettingItem">
+        <item name="android:textSize">@dimen/group_mms_setting_text_size</item>
+        <item name="android:textColor">@color/group_mms_setting_text_color</item>
+        <item name="android:layout_marginLeft">20dp</item>
+        <item name="android:layout_marginRight">20dp</item>
+        <item name="android:layout_marginTop">16dp</item>
+        <item name="android:paddingLeft">10dp</item>
+        <item name="android:paddingRight">10dp</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="DebugMmsConfigItemStyle">
+        <item name="android:paddingLeft">16dp</item>
+        <item name="android:paddingRight">16dp</item>
+    </style>
+
+    <style name="WidgetTitle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
+        <item name="android:textColor">@color/action_bar_title_text_color</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:layout_marginEnd">8dp</item>
+    </style>
+
+    <style name="WidgetConversationTitle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
+        <item name="android:textColor">@color/widget_conversation_title_color</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:textSize">@dimen/widget_conversation_title_size</item>
+        <item name="android:shadowColor">#000000</item>
+        <item name="android:shadowDx">0</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="WidgetHeaderImage">
+        <item name="android:paddingStart">4dip</item>
+    </style>
+
+    <style name="WidgetConversationListItemAvatar">
+        <item name="android:layout_marginEnd">12dp</item>
+        <item name="android:layout_marginStart">8dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+
+    <style name="WidgetConversationItemAvatarIncoming">
+        <item name="android:layout_marginStart">8dp</item>
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+
+    <style name="WidgetConversationItemAvatarOutgoing">
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:layout_alignParentRight">true</item>
+    </style>
+
+    <style name="WidgetConversationItemBodyIncoming">
+        <item name="android:layout_toRightOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetConversationItemBodyOutgoing">
+        <item name="android:layout_toLeftOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetConversationItemIncoming">
+        <item name="android:layout_marginRight">5dp</item>
+        <item name="android:layout_alignParentLeft">true</item>
+        <item name="android:layout_toLeftOf">@id/date</item>
+    </style>
+
+    <style name="WidgetConversationItemIncomingAvatarShadow">
+        <item name="android:layout_marginLeft">4dp</item>
+    </style>
+
+    <style name="WidgetConversationItemOutgoingAvatarShadow">
+        <item name="android:layout_marginLeft">-4dp</item>
+    </style>
+
+    <style name="WidgetConversationAppIcon" parent="WidgetHeaderImage">
+        <item name="android:layout_marginLeft">-20dp</item>
+    </style>
+
+    <style name="WidgetConversationItemDate">
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:layout_marginLeft">5dp</item>
+        <item name="android:layout_alignParentLeft">true</item>
+    </style>
+
+    <style name="WidgetConversationItemFailed">
+        <item name="android:layout_gravity">bottom|right</item>
+    </style>
+
+    <style name="WidgetConversationItemAttachment">
+        <item name="android:layout_gravity">bottom|right</item>
+    </style>
+
+    <style name="WidgetConversationItemWidget">
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:layout_marginLeft">5dp</item>
+        <item name="android:layout_alignParentLeft">true</item>
+    </style>
+
+    <style name="WidgetConversationListItemBody">
+        <item name="android:layout_toRightOf">@id/avatarFrame</item>
+    </style>
+
+    <style name="WidgetConversationListItemFrom">
+        <item name="android:layout_marginRight">5dp</item>
+        <item name="android:layout_alignParentLeft">true</item>
+    </style>
+
+    <style name="WidgetConversationListItemDate">
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:layout_marginLeft">5dp</item>
+        <item name="android:layout_gravity">right</item>
+    </style>
+
+    <style name="WidgetLoading">
+        <item name="android:layout_marginLeft">16dp</item>
+    </style>
+
+    <style name="WidgetConversationListItemStyle">
+        <item name="android:layout_height">80dp</item>
+    </style>
+
+    <style name="AttachmentGridItemViewCheckBoxStyle">
+        <item name="android:paddingRight">4dp</item>
+    </style>
+
+    <style name="PromoScreenTextStyle">
+        <item name="android:paddingLeft">40dp</item>
+        <item name="android:paddingRight">40dp</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@android:color/white</item>
+        <item name="android:fontFamily">roboto-regular</item>
+    </style>
+    <style name="PromoScreenTextStyle.CenterAligned">
+        <item name="android:textAlignment">center</item>
+    </style>
+    <style name="PromoScreenButtonStyle">
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">roboto-medium</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:textColor">@android:color/white</item>
+        <item name="android:gravity">center</item>
+    </style>
+    <style name="DirectoryHeaderStyle">
+        <item name="android:paddingLeft">@dimen/directory_header_padding_start</item>
+        <item name="android:paddingStart">@dimen/directory_header_padding_start</item>
+        <item name="android:paddingRight">@dimen/directory_header_padding_end</item>
+        <item name="android:paddingEnd">@dimen/directory_header_padding_end</item>
+        <item name="android:paddingTop">@dimen/directory_header_padding_top</item>
+        <item name="android:paddingBottom">@dimen/directory_header_padding_bottom</item>
+        <item name="android:textSize">@dimen/directory_header_text_size</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+</resources>
diff --git a/res/values/versions.xml b/res/values/versions.xml
new file mode 100644
index 0000000..14c6b47
--- /dev/null
+++ b/res/values/versions.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources>
+    <!-- DB version -->
+    <string name="database_version" translatable="false">2</string>
+
+    <!-- Version for shared preferences. This is used for handling prefs migration when old pref
+         keys are moved or renamed. You don't need to bump up the version number if you are just
+         adding/removing preferences -->
+    <string name="pref_version" translatable="false">1</string>
+</resources>
diff --git a/res/xml-mcc204-mnc04/mms_config.xml b/res/xml-mcc204-mnc04/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc204-mnc04/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc208-mnc01/mms_config.xml b/res/xml-mcc208-mnc01/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc208-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc208-mnc10/mms_config.xml b/res/xml-mcc208-mnc10/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc208-mnc10/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc208-mnc15/mms_config.xml b/res/xml-mcc208-mnc15/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc208-mnc15/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc208-mnc20/mms_config.xml b/res/xml-mcc208-mnc20/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc208-mnc20/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc208-mnc26/mms_config.xml b/res/xml-mcc208-mnc26/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc208-mnc26/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc214-mnc01/mms_config.xml b/res/xml-mcc214-mnc01/mms_config.xml
new file mode 100644
index 0000000..d6fad05
--- /dev/null
+++ b/res/xml-mcc214-mnc01/mms_config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - enable force 7 bit encoding
+        version 3 - removing v2 changes and move to correct location
+-->
+
+<mms_config version="2">
+    <!-- Disable SMS to MMS conversion for multiple recipient SMS -->
+    <bool name="enableGroupMms">false</bool>
+</mms_config>
diff --git a/res/xml-mcc214-mnc03/mms_config.xml b/res/xml-mcc214-mnc03/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc214-mnc03/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc214-mnc07/mms_config.xml b/res/xml-mcc214-mnc07/mms_config.xml
new file mode 100644
index 0000000..a90a26d
--- /dev/null
+++ b/res/xml-mcc214-mnc07/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">512000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc218-mnc05/mms_config.xml b/res/xml-mcc218-mnc05/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc218-mnc05/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc222-mnc01/mms_config.xml b/res/xml-mcc222-mnc01/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc222-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc222-mnc08/mms_config.xml b/res/xml-mcc222-mnc08/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc222-mnc08/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc234-mnc10/mms_config.xml b/res/xml-mcc234-mnc10/mms_config.xml
new file mode 100755
index 0000000..9f89f96
--- /dev/null
+++ b/res/xml-mcc234-mnc10/mms_config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+-->
+
+<mms_config version="1">
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">10</int>
+</mms_config>
diff --git a/res/xml-mcc234-mnc11 b/res/xml-mcc234-mnc11
new file mode 120000
index 0000000..e29c9d3
--- /dev/null
+++ b/res/xml-mcc234-mnc11
@@ -0,0 +1 @@
+xml-mcc234-mnc10
\ No newline at end of file
diff --git a/res/xml-mcc234-mnc15/mms_config.xml b/res/xml-mcc234-mnc15/mms_config.xml
new file mode 100755
index 0000000..9f89f96
--- /dev/null
+++ b/res/xml-mcc234-mnc15/mms_config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+-->
+
+<mms_config version="1">
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">10</int>
+</mms_config>
diff --git a/res/xml-mcc238-mnc02/mms_config.xml b/res/xml-mcc238-mnc02/mms_config.xml
new file mode 100644
index 0000000..6a27809
--- /dev/null
+++ b/res/xml-mcc238-mnc02/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">2097152</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc240-mnc01/mms_config.xml b/res/xml-mcc240-mnc01/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc240-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc240-mnc04/mms_config.xml b/res/xml-mcc240-mnc04/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc240-mnc04/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc240-mnc08/mms_config.xml b/res/xml-mcc240-mnc08/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc240-mnc08/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc240-mnc24/mms_config.xml b/res/xml-mcc240-mnc24/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc240-mnc24/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc242-mnc01/mms_config.xml b/res/xml-mcc242-mnc01/mms_config.xml
new file mode 100644
index 0000000..6a27809
--- /dev/null
+++ b/res/xml-mcc242-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">2097152</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc242-mnc02/mms_config.xml b/res/xml-mcc242-mnc02/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc242-mnc02/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc262-mnc07/mms_config.xml b/res/xml-mcc262-mnc07/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc262-mnc07/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc274-mnc02/mms_config.xml b/res/xml-mcc274-mnc02/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc274-mnc02/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc274-mnc03/mms_config.xml b/res/xml-mcc274-mnc03/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc274-mnc03/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc286-mnc01/mms_config.xml b/res/xml-mcc286-mnc01/mms_config.xml
new file mode 100644
index 0000000..a90a26d
--- /dev/null
+++ b/res/xml-mcc286-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">512000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc286-mnc03/mms_config.xml b/res/xml-mcc286-mnc03/mms_config.xml
new file mode 100644
index 0000000..a90a26d
--- /dev/null
+++ b/res/xml-mcc286-mnc03/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">512000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc294-mnc01/mms_config.xml b/res/xml-mcc294-mnc01/mms_config.xml
new file mode 100644
index 0000000..03ff16c
--- /dev/null
+++ b/res/xml-mcc294-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">102400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc294-mnc02/mms_config.xml b/res/xml-mcc294-mnc02/mms_config.xml
new file mode 100644
index 0000000..51af512
--- /dev/null
+++ b/res/xml-mcc294-mnc02/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">131072</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc294-mnc03/mms_config.xml b/res/xml-mcc294-mnc03/mms_config.xml
new file mode 100644
index 0000000..208a5a2
--- /dev/null
+++ b/res/xml-mcc294-mnc03/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">256000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc220/mms_config.xml b/res/xml-mcc302-mnc220/mms_config.xml
new file mode 100644
index 0000000..4267322
--- /dev/null
+++ b/res/xml-mcc302-mnc220/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+    to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+    will be converted into a single mms message. For example, if the mms_config.xml file
+    specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+    message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">5</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc221/mms_config.xml b/res/xml-mcc302-mnc221/mms_config.xml
new file mode 100644
index 0000000..4267322
--- /dev/null
+++ b/res/xml-mcc302-mnc221/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+    to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+    will be converted into a single mms message. For example, if the mms_config.xml file
+    specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+    message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">5</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc270/mms_config.xml b/res/xml-mcc302-mnc270/mms_config.xml
new file mode 100644
index 0000000..7f92daa
--- /dev/null
+++ b/res/xml-mcc302-mnc270/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc290/mms_config.xml b/res/xml-mcc302-mnc290/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc302-mnc290/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc320/mms_config.xml b/res/xml-mcc302-mnc320/mms_config.xml
new file mode 100644
index 0000000..0dc7956
--- /dev/null
+++ b/res/xml-mcc302-mnc320/mms_config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="1">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc370/mms_config.xml b/res/xml-mcc302-mnc370/mms_config.xml
new file mode 100644
index 0000000..7f92daa
--- /dev/null
+++ b/res/xml-mcc302-mnc370/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc490/mms_config.xml b/res/xml-mcc302-mnc490/mms_config.xml
new file mode 100644
index 0000000..7f92daa
--- /dev/null
+++ b/res/xml-mcc302-mnc490/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc500/mms_config.xml b/res/xml-mcc302-mnc500/mms_config.xml
new file mode 100644
index 0000000..0216774
--- /dev/null
+++ b/res/xml-mcc302-mnc500/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">3072000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc510/mms_config.xml b/res/xml-mcc302-mnc510/mms_config.xml
new file mode 100644
index 0000000..0216774
--- /dev/null
+++ b/res/xml-mcc302-mnc510/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">3072000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc520/mms_config.xml b/res/xml-mcc302-mnc520/mms_config.xml
new file mode 100644
index 0000000..21b15bb
--- /dev/null
+++ b/res/xml-mcc302-mnc520/mms_config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="1">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">3072000</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc610/mms_config.xml b/res/xml-mcc302-mnc610/mms_config.xml
new file mode 100644
index 0000000..7c0183e
--- /dev/null
+++ b/res/xml-mcc302-mnc610/mms_config.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">8</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- Disable SMS to MMS conversion for multiple recipient SMS -->
+    <bool name="enableGroupMms">false</bool>
+
+</mms_config>
diff --git a/res/xml-mcc302-mnc660/mms_config.xml b/res/xml-mcc302-mnc660/mms_config.xml
new file mode 100644
index 0000000..7f92daa
--- /dev/null
+++ b/res/xml-mcc302-mnc660/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc720/mms_config.xml b/res/xml-mcc302-mnc720/mms_config.xml
new file mode 100644
index 0000000..7f92daa
--- /dev/null
+++ b/res/xml-mcc302-mnc720/mms_config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+</mms_config>
diff --git a/res/xml-mcc302-mnc780/mms_config.xml b/res/xml-mcc302-mnc780/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc302-mnc780/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc004/mms_config.xml b/res/xml-mcc310-mnc004/mms_config.xml
new file mode 100644
index 0000000..346218b
--- /dev/null
+++ b/res/xml-mcc310-mnc004/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1258291</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">Profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE##|X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- enable alias -->
+    <bool name="aliasEnabled">true</bool>
+
+    <!-- alias rule: min chars -->
+    <int name="aliasMinChars">2</int>
+
+    <!-- alias rule: max chars -->
+    <int name="aliasMaxChars">48</int>
+
+    <!-- disable the option to attach an audio attachment to an Mms message. Currently Verizon
+         doesn't support OGG files and the only audio picker in the system allowed for picking
+         ringtones. All of our ringtones are OGG files so it doesn't make sense to allow a user
+         to select an audio file that eventually can't be handled. Therefore, the ability
+         to select a ringtone to send is disabled. -->
+    <bool name="allowAttachAudio">false</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">7</int>
+</mms_config>
+
diff --git a/res/xml-mcc310-mnc005/mms_config.xml b/res/xml-mcc310-mnc005/mms_config.xml
new file mode 100644
index 0000000..346218b
--- /dev/null
+++ b/res/xml-mcc310-mnc005/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1258291</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">Profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE##|X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- enable alias -->
+    <bool name="aliasEnabled">true</bool>
+
+    <!-- alias rule: min chars -->
+    <int name="aliasMinChars">2</int>
+
+    <!-- alias rule: max chars -->
+    <int name="aliasMaxChars">48</int>
+
+    <!-- disable the option to attach an audio attachment to an Mms message. Currently Verizon
+         doesn't support OGG files and the only audio picker in the system allowed for picking
+         ringtones. All of our ringtones are OGG files so it doesn't make sense to allow a user
+         to select an audio file that eventually can't be handled. Therefore, the ability
+         to select a ringtone to send is disabled. -->
+    <bool name="allowAttachAudio">false</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">7</int>
+</mms_config>
+
diff --git a/res/xml-mcc310-mnc010/mms_config.xml b/res/xml-mcc310-mnc010/mms_config.xml
new file mode 100644
index 0000000..571bc07
--- /dev/null
+++ b/res/xml-mcc310-mnc010/mms_config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- If this is true, The text message over 160 characters will be sent in separate,
+         independent messages after split into 160 character parts -->
+    <bool name="sendMultipartSmsAsSeparateMessages">true</bool>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- If true, need to read content_disposition field of an MMS part -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
+
diff --git a/res/xml-mcc310-mnc026/mms_config.xml b/res/xml-mcc310-mnc026/mms_config.xml
new file mode 100644
index 0000000..91481f9
--- /dev/null
+++ b/res/xml-mcc310-mnc026/mms_config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- T-Mobile U.S. mcc=310, mnc=026 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc040/mms_config.xml b/res/xml-mcc310-mnc040/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc310-mnc040/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc070/mms_config.xml b/res/xml-mcc310-mnc070/mms_config.xml
new file mode 100755
index 0000000..e9404e8
--- /dev/null
+++ b/res/xml-mcc310-mnc070/mms_config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<!-- AT&T U.S. mcc=310, mnc=070 -->
+
+<mms_config version="1">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc090/mms_config.xml b/res/xml-mcc310-mnc090/mms_config.xml
new file mode 100755
index 0000000..0c8f8de
--- /dev/null
+++ b/res/xml-mcc310-mnc090/mms_config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- AT&T U.S. mcc=310, mnc=090 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc120/mms_config.xml b/res/xml-mcc310-mnc120/mms_config.xml
new file mode 100644
index 0000000..8c1ae11
--- /dev/null
+++ b/res/xml-mcc310-mnc120/mms_config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">40</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">X-MDN: ##LINE1##|Proxy-Authorization: Basic ##NAI##</string>
+
+    <!-- Suffix to the NAI header (encoded together with base64) -->
+    <string name="naiSuffix">:pcs</string>
+
+    <!-- If true, need to read content_disposition field of an MMS part -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
diff --git a/res/xml-mcc310-mnc130/mms_config.xml b/res/xml-mcc310-mnc130/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc310-mnc130/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc150/mms_config.xml b/res/xml-mcc310-mnc150/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc310-mnc150/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc170/mms_config.xml b/res/xml-mcc310-mnc170/mms_config.xml
new file mode 100644
index 0000000..6705cbc
--- /dev/null
+++ b/res/xml-mcc310-mnc170/mms_config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- T-Mobile U.S. mcc=310, mnc=170 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc260/mms_config.xml b/res/xml-mcc310-mnc260/mms_config.xml
new file mode 100644
index 0000000..9bf9d70
--- /dev/null
+++ b/res/xml-mcc310-mnc260/mms_config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- T-Mobile U.S. mcc=310, mnc=260 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc360/mms_config.xml b/res/xml-mcc310-mnc360/mms_config.xml
new file mode 100644
index 0000000..eb8da80
--- /dev/null
+++ b/res/xml-mcc310-mnc360/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1228800</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc380/mms_config.xml b/res/xml-mcc310-mnc380/mms_config.xml
new file mode 100755
index 0000000..0ea83d1
--- /dev/null
+++ b/res/xml-mcc310-mnc380/mms_config.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+-->
+<!-- AT&T U.S. mcc=310, mnc=380 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc410/mms_config.xml b/res/xml-mcc310-mnc410/mms_config.xml
new file mode 100755
index 0000000..4e42f3a
--- /dev/null
+++ b/res/xml-mcc310-mnc410/mms_config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- AT&T U.S. mcc=310, mnc=410 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc420/mms_config.xml b/res/xml-mcc310-mnc420/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc310-mnc420/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc450/mms_config.xml b/res/xml-mcc310-mnc450/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc310-mnc450/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc490/mms_config.xml b/res/xml-mcc310-mnc490/mms_config.xml
new file mode 100644
index 0000000..06da531
--- /dev/null
+++ b/res/xml-mcc310-mnc490/mms_config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- T-Mobile U.S. mcc=310, mnc=490 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc560/mms_config.xml b/res/xml-mcc310-mnc560/mms_config.xml
new file mode 100755
index 0000000..a12d640
--- /dev/null
+++ b/res/xml-mcc310-mnc560/mms_config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- AT&T U.S. mcc=310, mnc=560 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc580/mms_config.xml b/res/xml-mcc310-mnc580/mms_config.xml
new file mode 100644
index 0000000..eb8da80
--- /dev/null
+++ b/res/xml-mcc310-mnc580/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1228800</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc600/mms_config.xml b/res/xml-mcc310-mnc600/mms_config.xml
new file mode 100644
index 0000000..f76c945
--- /dev/null
+++ b/res/xml-mcc310-mnc600/mms_config.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+<!-- MCC:310 MNC:600 - New Cell Inc. dba Cellcom -->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">8388608</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Flag indicating whether MMS Delivery Reports UI option should be shown -->
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc680/mms_config.xml b/res/xml-mcc310-mnc680/mms_config.xml
new file mode 100755
index 0000000..b42fa02
--- /dev/null
+++ b/res/xml-mcc310-mnc680/mms_config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- AT&T U.S. mcc=310, mnc=680 -->
+
+<mms_config version="3">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc750/mms_config.xml b/res/xml-mcc310-mnc750/mms_config.xml
new file mode 100644
index 0000000..eb8da80
--- /dev/null
+++ b/res/xml-mcc310-mnc750/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1228800</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc770/mms_config.xml b/res/xml-mcc310-mnc770/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc310-mnc770/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc310-mnc920/mms_config.xml b/res/xml-mcc310-mnc920/mms_config.xml
new file mode 100644
index 0000000..4319cb0
--- /dev/null
+++ b/res/xml-mcc310-mnc920/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1258291</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc310-mnc980/mms_config.xml b/res/xml-mcc310-mnc980/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc310-mnc980/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc311-mnc012/mms_config.xml b/res/xml-mcc311-mnc012/mms_config.xml
new file mode 100644
index 0000000..346218b
--- /dev/null
+++ b/res/xml-mcc311-mnc012/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1258291</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">Profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE##|X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- enable alias -->
+    <bool name="aliasEnabled">true</bool>
+
+    <!-- alias rule: min chars -->
+    <int name="aliasMinChars">2</int>
+
+    <!-- alias rule: max chars -->
+    <int name="aliasMaxChars">48</int>
+
+    <!-- disable the option to attach an audio attachment to an Mms message. Currently Verizon
+         doesn't support OGG files and the only audio picker in the system allowed for picking
+         ringtones. All of our ringtones are OGG files so it doesn't make sense to allow a user
+         to select an audio file that eventually can't be handled. Therefore, the ability
+         to select a ringtone to send is disabled. -->
+    <bool name="allowAttachAudio">false</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">7</int>
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc070/mms_config.xml b/res/xml-mcc311-mnc070/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc311-mnc070/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc100/mms_config.xml b/res/xml-mcc311-mnc100/mms_config.xml
new file mode 100755
index 0000000..dd671f6
--- /dev/null
+++ b/res/xml-mcc311-mnc100/mms_config.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+<!--Nex-Tech Wireless configuration-->
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">-1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Flag indicating whether SMS Delivery Reports UI option should be shown -->
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <!-- Flag indicating whether MMS Delivery Reports UI option should be shown -->
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+            Parameters are seperated by '|'. Optional.  -->
+    <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc180/mms_config.xml b/res/xml-mcc311-mnc180/mms_config.xml
new file mode 100644
index 0000000..891618b
--- /dev/null
+++ b/res/xml-mcc311-mnc180/mms_config.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+     to indicate no limit. -->
+    <int name="recipientLimit">10</int>
+</mms_config>
diff --git a/res/xml-mcc311-mnc220/mms_config.xml b/res/xml-mcc311-mnc220/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc220/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc221/mms_config.xml b/res/xml-mcc311-mnc221/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc221/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc222/mms_config.xml b/res/xml-mcc311-mnc222/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc222/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc223/mms_config.xml b/res/xml-mcc311-mnc223/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc223/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc224/mms_config.xml b/res/xml-mcc311-mnc224/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc224/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc225/mms_config.xml b/res/xml-mcc311-mnc225/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc225/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc226/mms_config.xml b/res/xml-mcc311-mnc226/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc226/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc227/mms_config.xml b/res/xml-mcc311-mnc227/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc227/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc228/mms_config.xml b/res/xml-mcc311-mnc228/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc228/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc229/mms_config.xml b/res/xml-mcc311-mnc229/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc229/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc230/mms_config.xml b/res/xml-mcc311-mnc230/mms_config.xml
new file mode 100755
index 0000000..b82f1d6
--- /dev/null
+++ b/res/xml-mcc311-mnc230/mms_config.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+<!--C Spire configuration-->
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">-1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Flag indicating whether SMS Delivery Reports UI option should be shown -->
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <!-- Flag indicating whether MMS Delivery Reports UI option should be shown -->
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request. -->
+    <string name="httpParams">X-CS3G-MDN: 1##LINE1NOCOUNTRYCODE##</string>
+
+</mms_config>
diff --git a/res/xml-mcc311-mnc340/mms_config.xml b/res/xml-mcc311-mnc340/mms_config.xml
new file mode 100644
index 0000000..eb8da80
--- /dev/null
+++ b/res/xml-mcc311-mnc340/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1228800</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc370/mms_config.xml b/res/xml-mcc311-mnc370/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc311-mnc370/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc311-mnc410/mms_config.xml b/res/xml-mcc311-mnc410/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc311-mnc410/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc430/mms_config.xml b/res/xml-mcc311-mnc430/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc311-mnc430/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc440/mms_config.xml b/res/xml-mcc311-mnc440/mms_config.xml
new file mode 100644
index 0000000..0f26fab
--- /dev/null
+++ b/res/xml-mcc311-mnc440/mms_config.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1228800</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Flag indicating whether MMS Delivery Reports UI option should be shown -->
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc480/mms_config.xml b/res/xml-mcc311-mnc480/mms_config.xml
new file mode 100644
index 0000000..1929b6a
--- /dev/null
+++ b/res/xml-mcc311-mnc480/mms_config.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <!-- TODO: check if this is correct for Passion -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1258291</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">Profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE##|X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <!-- enable alias -->
+    <bool name="aliasEnabled">true</bool>
+
+    <!-- alias rule: min chars -->
+    <int name="aliasMinChars">2</int>
+
+    <!-- alias rule: max chars -->
+    <int name="aliasMaxChars">48</int>
+
+    <!-- disable the option to attach an audio attachment to an Mms message. Currently Verizon
+         doesn't support OGG files and the only audio picker in the system allowed for picking
+         ringtones. All of our ringtones are OGG files so it doesn't make sense to allow a user
+         to select an audio file that eventually can't be handled. Therefore, the ability
+         to select a ringtone to send is disabled. -->
+    <bool name="allowAttachAudio">false</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">7</int>
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc490/mms_config.xml b/res/xml-mcc311-mnc490/mms_config.xml
new file mode 100644
index 0000000..8c1ae11
--- /dev/null
+++ b/res/xml-mcc311-mnc490/mms_config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">40</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">X-MDN: ##LINE1##|Proxy-Authorization: Basic ##NAI##</string>
+
+    <!-- Suffix to the NAI header (encoded together with base64) -->
+    <string name="naiSuffix">:pcs</string>
+
+    <!-- If true, need to read content_disposition field of an MMS part -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
diff --git a/res/xml-mcc311-mnc580/mms_config.xml b/res/xml-mcc311-mnc580/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc580/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc581/mms_config.xml b/res/xml-mcc311-mnc581/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc581/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc582/mms_config.xml b/res/xml-mcc311-mnc582/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc582/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc583/mms_config.xml b/res/xml-mcc311-mnc583/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc583/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc584/mms_config.xml b/res/xml-mcc311-mnc584/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc584/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc585/mms_config.xml b/res/xml-mcc311-mnc585/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc585/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc586/mms_config.xml b/res/xml-mcc311-mnc586/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc586/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc587/mms_config.xml b/res/xml-mcc311-mnc587/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc587/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc588/mms_config.xml b/res/xml-mcc311-mnc588/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc588/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc589/mms_config.xml b/res/xml-mcc311-mnc589/mms_config.xml
new file mode 100644
index 0000000..196d4f7
--- /dev/null
+++ b/res/xml-mcc311-mnc589/mms_config.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="2">
+    <!-- In case of single segment M-Notification.ind, this indicates whether
+         TransactionID should be appended to URI or not. -->
+    <bool name="enabledTransID">true</bool>
+
+    <!-- Send M-Acknowledge.ind and M-NotifyResp.ind to the URL received by the
+         M-Notification.ind (WAP-PUSH). -->
+    <bool name="enabledNotifyWapMMSC">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- UAProf parameter tag name -->
+    <string name="uaProfTagName">x-wap-profile</string>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- Additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">x-vzw-mdn: 1##LINE1NOCOUNTRYCODE##</string>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message or separate, independent SMS messages,
+         dependent on sendMultipartSMSAsSeparateMessages value. -->
+    <bool name="enableMultipartSMS">false</bool>
+
+    <!-- Email Gateway Number -->
+    <!-- TODO: check if this is correct for Passion -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="allowAttachAudio">true</bool>
+
+    <!-- Hide the MMS read reports UI in settings -->
+    <bool name="enableMMSReadReports">false</bool>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+</mms_config>
+
diff --git a/res/xml-mcc311-mnc590/mms_config.xml b/res/xml-mcc311-mnc590/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc311-mnc590/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc311-mnc870/mms_config.xml b/res/xml-mcc311-mnc870/mms_config.xml
new file mode 100644
index 0000000..8c1ae11
--- /dev/null
+++ b/res/xml-mcc311-mnc870/mms_config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">40</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">X-MDN: ##LINE1##|Proxy-Authorization: Basic ##NAI##</string>
+
+    <!-- Suffix to the NAI header (encoded together with base64) -->
+    <string name="naiSuffix">:pcs</string>
+
+    <!-- If true, need to read content_disposition field of an MMS part -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
diff --git a/res/xml-mcc312-mnc160/mms_config.xml b/res/xml-mcc312-mnc160/mms_config.xml
new file mode 100644
index 0000000..9622857
--- /dev/null
+++ b/res/xml-mcc312-mnc160/mms_config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">2432</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">4320</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">500</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">50</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">20</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+     <!-- Reference for additional http parameters used in MMS http request.
+          Parameters are seperated by '|'. Optional.  -->
+     <string name="httpParams">X-MDN: ##LINE1##</string>
+</mms_config>
diff --git a/res/xml-mcc312-mnc530/mms_config.xml b/res/xml-mcc312-mnc530/mms_config.xml
new file mode 100755
index 0000000..7b1b093
--- /dev/null
+++ b/res/xml-mcc312-mnc530/mms_config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 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.
+-->
+
+<mms_config version="1">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">40</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">6</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">false</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Maximum length in chars of mms subject field -->
+    <int name="maxSubjectLength">80</int>
+
+    <!-- Email Gateway Number -->
+    <string name="emailGatewayNumber">6245</string>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional. -->
+    <string name="httpParams">X-MDN: ##LINE1##|Proxy-Authorization: Basic ##NAI##</string>
+
+    <!-- Suffix to the NAI header (encoded together with base64) -->
+    <string name="naiSuffix">:pcs</string>
+
+    <!-- If true, need to read content_disposition field of an MMS part -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
diff --git a/res/xml-mcc334-mnc020/mms_config.xml b/res/xml-mcc334-mnc020/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc334-mnc020/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc418-mnc05/mms_config.xml b/res/xml-mcc418-mnc05/mms_config.xml
new file mode 100644
index 0000000..03ff16c
--- /dev/null
+++ b/res/xml-mcc418-mnc05/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">102400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc418-mnc20/mms_config.xml b/res/xml-mcc418-mnc20/mms_config.xml
new file mode 100644
index 0000000..9ef0dd8
--- /dev/null
+++ b/res/xml-mcc418-mnc20/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">153600</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc418-mnc30/mms_config.xml b/res/xml-mcc418-mnc30/mms_config.xml
new file mode 100644
index 0000000..9ef0dd8
--- /dev/null
+++ b/res/xml-mcc418-mnc30/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">153600</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc420-mnc04/mms_config.xml b/res/xml-mcc420-mnc04/mms_config.xml
new file mode 100644
index 0000000..614ba8e
--- /dev/null
+++ b/res/xml-mcc420-mnc04/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">409600</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc440-mnc10/mms_config.xml b/res/xml-mcc440-mnc10/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc440-mnc10/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc440-mnc11/mms_config.xml b/res/xml-mcc440-mnc11/mms_config.xml
new file mode 100644
index 0000000..2464a13
--- /dev/null
+++ b/res/xml-mcc440-mnc11/mms_config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<!-- Rakuten Mobile J.P. mcc=440, mnc=11 -->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">2097152</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
\ No newline at end of file
diff --git a/res/xml-mcc440-mnc20/mms_config.xml b/res/xml-mcc440-mnc20/mms_config.xml
new file mode 100644
index 0000000..7f383c4
--- /dev/null
+++ b/res/xml-mcc440-mnc20/mms_config.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<!-- Softbank J.P. mcc=440, mnc=020 -->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">307200</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Maximum number of SMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultSMSMessagesPerThread">10000</int>
+
+    <!-- Maximum number of MMS message to save per thread before auto-delete kicks in.
+         This is the default value. -->
+    <int name="defaultMMSMessagesPerThread">1000</int>
+
+    <!-- Minimum value for the number of messages kept per conversation. The user can never
+         set the limit below this value. -->
+    <int name="minMessageCountPerThread">10</int>
+
+    <!-- Maximum value for the number of messages kept per conversation. The user can never
+         set the limit above this value. -->
+    <int name="maxMessageCountPerThread">5000</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">-1</int>
+
+    <!-- If true, The mms support slide duration.
+         If false, The mms does not support slide duration and we have to
+         set duration value. -->
+    <bool name="enableSlideDuration">true</bool>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- Set to true to add links to Cell Broadcast app from Settings and MMS app. -->
+    <bool name="config_cellBroadcastAppLinks">false</bool>
+</mms_config>
diff --git a/res/xml-mcc450-mnc00/mms_config.xml b/res/xml-mcc450-mnc00/mms_config.xml
new file mode 100644
index 0000000..96e5b9d
--- /dev/null
+++ b/res/xml-mcc450-mnc00/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc450-mnc02/mms_config.xml b/res/xml-mcc450-mnc02/mms_config.xml
new file mode 100644
index 0000000..2a7231c
--- /dev/null
+++ b/res/xml-mcc450-mnc02/mms_config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+</mms_config>
diff --git a/res/xml-mcc450-mnc05/mms_config.xml b/res/xml-mcc450-mnc05/mms_config.xml
new file mode 100644
index 0000000..2a7231c
--- /dev/null
+++ b/res/xml-mcc450-mnc05/mms_config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+</mms_config>
diff --git a/res/xml-mcc450-mnc06/mms_config.xml b/res/xml-mcc450-mnc06/mms_config.xml
new file mode 100644
index 0000000..5123984
--- /dev/null
+++ b/res/xml-mcc450-mnc06/mms_config.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- SMS text length threshold (in bytes) to turn into MMS -->
+    <int name="smsToMmsTextLengthThreshold">80</int>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+</mms_config>
diff --git a/res/xml-mcc450-mnc08/mms_config.xml b/res/xml-mcc450-mnc08/mms_config.xml
new file mode 100644
index 0000000..2a7231c
--- /dev/null
+++ b/res/xml-mcc450-mnc08/mms_config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">1048576</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <bool name="enableMMSReadReports">false</bool>
+
+    <bool name="enableSMSDeliveryReports">false</bool>
+
+    <bool name="enableMMSDeliveryReports">false</bool>
+</mms_config>
diff --git a/res/xml-mcc505-mnc01/mms_config.xml b/res/xml-mcc505-mnc01/mms_config.xml
new file mode 100644
index 0000000..6a27809
--- /dev/null
+++ b/res/xml-mcc505-mnc01/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">2097152</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc530-mnc05/mms_config.xml b/res/xml-mcc530-mnc05/mms_config.xml
new file mode 100644
index 0000000..fabcf3c
--- /dev/null
+++ b/res/xml-mcc530-mnc05/mms_config.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+
+    <!-- Content-Disposition header is not supported -->
+    <bool name="supportMmsContentDisposition">false</bool>
+</mms_config>
diff --git a/res/xml-mcc604-mnc00/mms_config.xml b/res/xml-mcc604-mnc00/mms_config.xml
new file mode 100644
index 0000000..03ff16c
--- /dev/null
+++ b/res/xml-mcc604-mnc00/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">102400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc604-mnc02/mms_config.xml b/res/xml-mcc604-mnc02/mms_config.xml
new file mode 100644
index 0000000..03ff16c
--- /dev/null
+++ b/res/xml-mcc604-mnc02/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">102400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-mcc647-mnc10/mms_config.xml b/res/xml-mcc647-mnc10/mms_config.xml
new file mode 100644
index 0000000..486c468
--- /dev/null
+++ b/res/xml-mcc647-mnc10/mms_config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">614400</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">1944</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">2592</int>
+</mms_config>
diff --git a/res/xml-v21/preferences_application.xml b/res/xml-v21/preferences_application.xml
new file mode 100644
index 0000000..5d8ee4c
--- /dev/null
+++ b/res/xml-v21/preferences_application.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- Preference screen definition for Bugle's application-wide settings -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--  KLP+ only -->
+    <PreferenceScreen
+        android:key="@string/sms_disabled_pref_key"
+        android:title="@string/sms_disabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.provider.Telephony.ACTION_CHANGE_DEFAULT">
+            <extra android:name="package" android:value="com.android.messaging" />
+        </intent>
+    </PreferenceScreen>
+    <PreferenceScreen
+        android:key="@string/sms_enabled_pref_key"
+        android:title="@string/sms_enabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.settings.WIRELESS_SETTINGS">
+        </intent>
+    </PreferenceScreen>
+
+    <SwitchPreference
+        android:key="@string/send_sound_pref_key"
+        android:title="@string/send_sound_pref_title"
+        android:defaultValue="@bool/send_sound_pref_default"
+        android:persistent="true" />
+
+    <SwitchPreference
+        android:key="@string/notifications_enabled_pref_key"
+        android:title="@string/notifications_enabled_pref_title"
+        android:defaultValue="@bool/notifications_enabled_pref_default"
+        android:persistent="true"
+        android:disableDependentsState="false" />
+
+    <RingtonePreference
+        android:key="@string/notification_sound_pref_key"
+        android:title="@string/notification_sound_pref_title"
+        android:ringtoneType="notification"
+        android:showSilent="true"
+        android:showDefault="true"
+        android:persistent="true"
+        android:defaultValue=""
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <SwitchPreference
+        android:key="@string/notification_vibration_pref_key"
+        android:title="@string/notification_vibrate_pref_title"
+        android:defaultValue="@bool/notification_vibration_pref_default"
+        android:persistent="true"
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <PreferenceScreen
+            android:key="@string/advanced_pref_key"
+            android:title="@string/advanced_settings" />
+
+    <PreferenceCategory
+        android:key="@string/debug_pref_key"
+        android:title="@string/debug_category_pref_title">
+
+        <SwitchPreference
+            android:key="@string/dump_sms_pref_key"
+            android:title="@string/dump_sms_pref_title"
+            android:summary="@string/dump_sms_pref_summary"
+            android:defaultValue="@bool/dump_sms_pref_default" />
+
+        <SwitchPreference
+            android:key="@string/dump_mms_pref_key"
+            android:title="@string/dump_mms_pref_title"
+            android:summary="@string/dump_mms_pref_summary"
+            android:defaultValue="@bool/dump_mms_pref_default" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml-v21/preferences_per_subscription.xml b/res/xml-v21/preferences_per_subscription.xml
new file mode 100644
index 0000000..d0ae3e6
--- /dev/null
+++ b/res/xml-v21/preferences_per_subscription.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- Preference screen definition for Bugle's subscription-specific settings -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <PreferenceCategory
+        android:key="@string/mms_messaging_category_pref_key"
+        android:title="@string/mms_messaging_category_pref_title">
+
+        <Preference
+            android:title="@string/group_mms_pref_title"
+            android:key="@string/group_mms_pref_key"/>
+
+        <com.android.messaging.ui.appsettings.PhoneNumberPreference
+            android:key="@string/mms_phone_number_pref_key"
+            android:title="@string/mms_phone_number_pref_title" />
+
+        <SwitchPreference
+            android:key="@string/auto_retrieve_mms_pref_key"
+            android:title="@string/auto_retrieve_mms_pref_title"
+            android:summary="@string/auto_retrieve_mms_pref_summary"
+            android:defaultValue="@bool/auto_retrieve_mms_pref_default" />
+
+        <SwitchPreference
+            android:key="@string/auto_retrieve_mms_when_roaming_pref_key"
+            android:dependency="@string/auto_retrieve_mms_pref_key"
+            android:title="@string/auto_retrieve_mms_when_roaming_pref_title"
+            android:summary="@string/auto_retrieve_mms_when_roaming_pref_summary"
+            android:defaultValue="@bool/auto_retrieve_mms_when_roaming_pref_default" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="@string/advanced_category_pref_key"
+        android:title="@string/advanced_category_pref_title">
+
+        <SwitchPreference
+            android:key="@string/delivery_reports_pref_key"
+            android:title="@string/delivery_reports_pref_title"
+            android:summary="@string/delivery_reports_pref_summary"
+            android:defaultValue="@bool/delivery_reports_pref_default" />
+
+        <Preference
+            android:key="@string/wireless_alerts_key"
+            android:title="@string/wireless_alerts_title"/>
+
+        <PreferenceScreen
+            android:key="@string/sms_apns_key"
+            android:title="@string/sms_apns_title" />
+
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml-v23/preferences_application.xml b/res/xml-v23/preferences_application.xml
new file mode 100644
index 0000000..8fbadc4
--- /dev/null
+++ b/res/xml-v23/preferences_application.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- Preference screen definition for Bugle's application-wide settings -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--  KLP+ only -->
+    <PreferenceScreen
+        android:key="@string/sms_disabled_pref_key"
+        android:title="@string/sms_disabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.provider.Telephony.ACTION_CHANGE_DEFAULT">
+            <extra android:name="package" android:value="com.android.messaging" />
+        </intent>
+    </PreferenceScreen>
+    <!--  MNC+ only -->
+    <PreferenceScreen
+        android:key="@string/sms_enabled_pref_key"
+        android:title="@string/sms_enabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.provider.Telephony.ACTION_CHANGE_DEFAULT">
+        </intent>
+    </PreferenceScreen>
+
+    <SwitchPreference
+        android:key="@string/send_sound_pref_key"
+        android:title="@string/send_sound_pref_title"
+        android:defaultValue="@bool/send_sound_pref_default"
+        android:persistent="true" />
+
+    <SwitchPreference
+        android:key="@string/notifications_enabled_pref_key"
+        android:title="@string/notifications_enabled_pref_title"
+        android:defaultValue="@bool/notifications_enabled_pref_default"
+        android:persistent="true"
+        android:disableDependentsState="false" />
+
+    <RingtonePreference
+        android:key="@string/notification_sound_pref_key"
+        android:title="@string/notification_sound_pref_title"
+        android:ringtoneType="notification"
+        android:showSilent="true"
+        android:showDefault="true"
+        android:persistent="true"
+        android:defaultValue=""
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <SwitchPreference
+        android:key="@string/notification_vibration_pref_key"
+        android:title="@string/notification_vibrate_pref_title"
+        android:defaultValue="@bool/notification_vibration_pref_default"
+        android:persistent="true"
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <PreferenceScreen
+            android:key="@string/advanced_pref_key"
+            android:title="@string/advanced_settings" />
+
+    <PreferenceCategory
+        android:key="@string/debug_pref_key"
+        android:title="@string/debug_category_pref_title">
+
+        <SwitchPreference
+            android:key="@string/dump_sms_pref_key"
+            android:title="@string/dump_sms_pref_title"
+            android:summary="@string/dump_sms_pref_summary"
+            android:defaultValue="@bool/dump_sms_pref_default" />
+
+        <SwitchPreference
+            android:key="@string/dump_mms_pref_key"
+            android:title="@string/dump_mms_pref_title"
+            android:summary="@string/dump_mms_pref_summary"
+            android:defaultValue="@bool/dump_mms_pref_default" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/apn_editor.xml b/res/xml/apn_editor.xml
new file mode 100644
index 0000000..5afaeb5
--- /dev/null
+++ b/res/xml/apn_editor.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/apn_edit">
+    <EditTextPreference
+        android:title="@string/apn_name"
+        android:dialogTitle="@string/apn_name"
+        android:key="apn_name"
+        android:singleLine="true"
+        android:inputType="text"
+        />
+    <EditTextPreference
+        android:title="@string/apn_mmsc"
+        android:dialogTitle="@string/apn_mmsc"
+        android:key="apn_mmsc"
+        android:singleLine="true"
+        android:inputType="textUri"
+        />
+    <EditTextPreference
+        android:title="@string/apn_mms_proxy"
+        android:dialogTitle="@string/apn_mms_proxy"
+        android:key="apn_mms_proxy"
+        android:singleLine="true"
+        android:inputType="textUri"
+        />
+    <EditTextPreference
+        android:title="@string/apn_mms_port"
+        android:dialogTitle="@string/apn_mms_port"
+        android:key="apn_mms_port"
+        android:singleLine="true"
+        android:inputType="number"
+        />
+    <EditTextPreference
+        android:title="@string/apn_mcc"
+        android:dialogTitle="@string/apn_mcc"
+        android:key="apn_mcc"
+        android:singleLine="true"
+        android:inputType="number"
+        />
+    <EditTextPreference
+        android:title="@string/apn_mnc"
+        android:dialogTitle="@string/apn_mnc"
+        android:key="apn_mnc"
+        android:singleLine="true"
+        android:inputType="number"
+        />
+</PreferenceScreen>
diff --git a/res/xml/apn_settings.xml b/res/xml/apn_settings.xml
new file mode 100644
index 0000000..61a8b5b
--- /dev/null
+++ b/res/xml/apn_settings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/apn_settings" android:key="@string/apn_list_pref_key">
+</PreferenceScreen>
diff --git a/res/xml/apns.xml b/res/xml/apns.xml
new file mode 100644
index 0000000..20de298
--- /dev/null
+++ b/res/xml/apns.xml
@@ -0,0 +1,3284 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+  <apns version="9">
+      <apn mcc="001" mnc="01" carrier="AT&amp;T PHONE TEST SIM" apn="phone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl,hipri,fota,dun"></apn>
+      <apn mcc="001" mnc="01" carrier="EHRPD - Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="01" carrier="LTE - Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="01" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="01" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="01" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="001" mnc="01" carrier="U.S.Cellular TEST SIM" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,hipri,dun,fota" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="010" carrier="EHRPD - VZW Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="010" carrier="LTE - VZW Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="010" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="010" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="001" mnc="010" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="1" mnc="1" carrier="AT&amp;T US MMS TEST SIM" apn="phone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="mms"></apn>
+      <apn mcc="1" mnc="1" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="1" mnc="1" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="1" mnc="1" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="1" mnc="10" carrier="VZW Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="1" mnc="10" carrier="VZW Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="1" mnc="10" carrier="VZW Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="202" mnc="01" carrier="Cosmote Mms" apn="mms" mmsc="http://mmsc.cosmote.gr:8002" mmsproxy="10.10.10.20" mmsport="8080" type="mms"></apn>
+      <apn mcc="202" mnc="1" carrier="Cosmote Internet MMS" apn="internet" mmsc="http://mmsc.cosmote.gr:8002" mmsproxy="10.10.10.20" mmsport="8080" type="default,mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="202" mnc="1" carrier="Cosmote Mms" apn="mms" mmsc="http://mmsc.cosmote.gr:8002" mmsproxy="10.10.10.20" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="202" mnc="05" carrier="Vf MMS" apn="mms.vodafone.net" mmsc="http://mms.vodafone.gr" mmsproxy="213.249.19.49" mmsport="5080" type="mms" user="user" password="pass" authtype="1"></apn>
+      <apn mcc="202" mnc="5" carrier="VF MMS" apn="mms.vodafone.net" mmsc="http://mms.vodafone.gr" mmsproxy="213.249.19.49" mmsport="5080" type="mms" user="user" password="pass" authtype="0"></apn>
+      <apn mcc="202" mnc="09" carrier="Q-Telecom MMS GPRS" apn="q-mms.myq.gr" mmsc="http://mms.myq.gr" mmsproxy="192.168.80.134" mmsport="8080" type="mms"></apn>
+      <apn mcc="202" mnc="10" carrier="WIND GR MMS" apn="mnet.b-online.gr" mmsc="http://192.168.200.95/servlets/mms" mmsproxy="192.168.200.11" mmsport="9401" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="202" mnc="10" carrier="Wind MMS" apn="mnet.b-online.gr" mmsc="http://192.168.200.95/servlets/mms" mmsproxy="192.168.200.11" mmsport="9401" type="mms"></apn>
+      <apn mcc="202" mnc="10" carrier="Wind MMS" apn="mnet.b-online.gr" mmsc="http://192.168.200.95/servlets/mms" mmsproxy="192.168.200.11" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="204" mnc="02" carrier="Tele2 GPRS" apn="internet.tele2.nl" mmsc="http://mmsc.tele2.nl" mmsproxy="193.12.40.64" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="204" mnc="2" carrier="Tele2 GPRS" apn="internet.tele2.nl" mmsc="http://mmsc.tele2.nl" mmsproxy="193.12.40.64" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="2" carrier="Tele2 MMS" apn="internet.tele2.nl" mmsc="http://mmsc.tele2.nl" mmsproxy="193.12.40.64" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="204" mnc="04" carrier="CSpire international" apn="admin.cs4glte.com" mmsc="http://pix.cspire.com" type="admin,fota,ota" mvno_match_data="C Spire" mvno_type="spn" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="204" mnc="04" carrier="CSpire international" apn="internet.cs4glte.com" mmsc="http://pix.cspire.com" type="default,internet,mms" user="Uniroam@inet.cs.com" password="cs3g" authtype="3" mvno_match_data="C Spire" mvno_type="spn" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="204" mnc="04" carrier="CSpire international" apn="tethering.cs4glte.com" mmsc="http://pix.cspire.com" type="dun,pam" mvno_match_data="C Spire" mvno_type="spn" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="204" mnc="04" carrier="EHRPD - VZW Roaming CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="204" mnc="04" carrier="EHRPD - VZW Roaming CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" mvno_match_data="BAE0000000000000" mvno_type="gid" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="204" mnc="04" carrier="LTE - VZW Roaming CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="204" mnc="04" carrier="LTE - VZW Roaming CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" mvno_match_data="BAE0000000000000" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="204" mnc="04" carrier="SaskTel" apn="pda.stm.sk.ca" mmsc="http://mms.sasktel.com/" mmsproxy="mig.sasktel.com" mmsport="80" type="default,mms,supl" mvno_match_data="5A" mvno_type="gid"></apn>
+      <apn mcc="204" mnc="04" carrier="SaskTel" apn="pda.stm.sk.ca" mmsc="http://mms.sasktel.com/" mmsproxy="mig.sasktel.com" mmsport="80" type="default,mms,supl,dun" mvno_match_data="5A" mvno_type="gid"></apn>
+      <apn mcc="204" mnc="04" carrier="Vodafone NL" apn="live.vodafone.com" mmsc="http://mmsc.mms.vodafone.nl" mmsproxy="192.168.251.150" mmsport="8799" type="default,supl,mms" user="vodafone" password="vodafone" authtype="1"></apn>
+      <apn mcc="204" mnc="4" carrier="Vodafone NL" apn="live.vodafone.com" mmsc="http://mmsc.mms.vodafone.nl" mmsproxy="192.168.251.150" mmsport="8799" type="default,mms" user="vodafone" password="vodafone" authtype="1" proxy="192.168.251.150" port="8799"></apn>
+      <apn mcc="204" mnc="08" carrier="KPN/Hi 4G LTE Mobiel internet" apn="KPN4G.nl" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.20" mmsport="5080" type="default,supl,mms"></apn>
+      <apn mcc="204" mnc="08" carrier="KPN/Hi Mobiel Internet" apn="portalmmm.nl" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.20" mmsport="5080" type="default,supl,mms"></apn>
+      <apn mcc="204" mnc="08" carrier="Rabo Mobiel MMS" apn="rabo" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.10" mmsport="5080" type="mms" mvno_match_data="Rabo Mobiel" mvno_type="spn"></apn>
+      <apn mcc="204" mnc="8" carrier="KPN" apn="portalmmm.nl" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.20" mmsport="5080" type="default,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="8" carrier="KPN/Hi 4G LTE Mobiel internet" apn="KPN4G.nl" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.20" mmsport="5080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="8" carrier="KPN/Hi Mobiel Internet" apn="portalmmm.nl" mmsc="http://mp.mobiel.kpn/mmsc" mmsproxy="10.10.100.20" mmsport="5080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="12" carrier="Telfort" apn="internet" mmsc="http://mms" mmsproxy="193.113.200.195" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="12" carrier="Telfort Internet" apn="internet" mmsc="http://mms" mmsproxy="193.113.200.195" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="204" mnc="12" carrier="Telfort Internet" apn="internet" mmsc="http://mms" mmsproxy="193.113.200.195" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="204" mnc="16" carrier="Ben MMS" apn="mms.ben" mmsc="http://benmms/" mmsproxy="10.10.10.11" mmsport="8080" type="mms" authtype="1" mvno_match_data="BEN NL" mvno_type="spn"></apn>
+      <apn mcc="204" mnc="16" carrier="T-Mobile MMS" apn="mms" mmsc="http://t-mobilemms" mmsproxy="10.10.10.11" mmsport="8080" type="mms" user="tmobilemms" password="tmobilemms" authtype="1"></apn>
+      <apn mcc="204" mnc="16" carrier="T-Mobile MMS" apn="mms" mmsc="http://t-mobilemms" mmsproxy="10.10.10.11" mmsport="8080" type="mms" user="tmobilemms" password="tmobilemms" authtype="1" protocol="IP"></apn>
+      <apn mcc="204" mnc="16" carrier="T-Mobile NL" apn="internet" mmsc="http://t-mobilemms" mmsproxy="010.010.010.011" mmsport="8080" type="default,supl"></apn>
+      <apn mcc="204" mnc="16" carrier="T-Mobile NL MMS" apn="mms" mmsc="http://t-mobilemms" mmsproxy="010.010.010.011" mmsport="8080" type="mms"></apn>
+      <apn mcc="204" mnc="20" carrier="Orange NL MMS" apn="mms" mmsc="http://mms.orange.nl:8002" mmsproxy="10.250.255.183" mmsport="5080" type="mms" authtype="0"></apn>
+      <apn mcc="204" mnc="20" carrier="T-Mobile MMS" apn="mms" mmsc="http://t-mobilemms" mmsproxy="10.10.10.11" mmsport="8080" type="mms" user="tmobilemms" password="tmobilemms" authtype="1"></apn>
+      <apn mcc="206" mnc="01" carrier="MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="0" mvno_match_data="IUSACELL" mvno_type="spn"></apn>
+      <apn mcc="206" mnc="01" carrier="MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="0" mvno_match_data="UNEFON" mvno_type="spn"></apn>
+      <apn mcc="206" mnc="01" carrier="MMS" apn="mms.mobi.eastlink.ca" mmsc="http://mmss.mobi.eastlink.ca" mmsproxy="10.232.12.49" mmsport="8080" type="mms" mvno_match_data="B6" mvno_type="gid"></apn>
+      <apn mcc="206" mnc="01" carrier="NRJMMS" apn="event.proximus.be" mmsc="http://mmsc.proximus.be/mms" mmsproxy="10.55.14.75" mmsport="8080" type="mms" user="mms" password="mms" authtype="0" mvno_match_data="NRJ Mobile" mvno_type="spn"></apn>
+      <apn mcc="206" mnc="01" carrier="Px MMS" apn="EVENT.PROXIMUS.BE" mmsc="http://mmsc.proximus.be/mms" mmsproxy="10.55.14.75" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="206" mnc="01" carrier="Telenet MMS" apn="mms.be" mmsc="http://mmsc.telenet.be" mmsproxy="195.130.149.100" mmsport="80" type="mms" mvno_match_data="2060188" mvno_type="imsi"></apn>
+      <apn mcc="206" mnc="01" carrier="VM MMS" apn="virgin-mobile.fr" mmsc="http://virginmms.fr" mmsproxy="10.6.10.1" mmsport="8080" type="mms" mvno_match_data="52" mvno_type="gid"></apn>
+      <apn mcc="206" mnc="1" carrier="Px MMS" apn="EVENT.PROXIMUS.BE" mmsc="http://mmsc.proximus.be/mms" mmsproxy="10.55.14.75" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="206" mnc="1" carrier="Px MMS" apn="event.proximus.be" mmsc="http://mmsc.proximus.be/mms" mmsproxy="10.55.14.75" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="206" mnc="1" carrier="Telenet MMS" apn="mms.be" mmsc="http://mmsc.telenet.be" mmsproxy="195.130.149.100" mmsport="80" type="mms" authtype="0" mvno_match_data="2060188" mvno_type="imsi"></apn>
+      <apn mcc="206" mnc="1" carrier="Telenet Roam MMS" apn="mms.be" mmsc="http://mmsc.telenet.be" mmsproxy="195.130.149.100" mmsport="80" type="mms" authtype="0" mvno_match_data="Telenet" mvno_type="spn"></apn>
+      <apn mcc="206" mnc="05" carrier="Telenet MMS" apn="mms.be" mmsc="http://mmsc.telenet.be" mmsproxy="195.130.149.100" mmsport="80" type="mms"></apn>
+      <apn mcc="206" mnc="10" carrier="Mobistar MMS" apn="mms.be" mmsc="http://mmsc.mobistar.be" mmsproxy="212.65.63.143" mmsport="8080" type="mms"></apn>
+      <apn mcc="206" mnc="10" carrier="Mobistar MMS" apn="mms.be" mmsc="http://mmsc.mobistar.be" mmsproxy="212.65.63.143" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="206" mnc="10" carrier="Mobistar MMS" apn="mms.be" mmsc="http://mmsc.mobistar.be" mmsproxy="212.65.63.143" mmsport="8080" type="mms" user="mobistar" password="mobistar" authtype="0"></apn>
+      <apn mcc="206" mnc="20" carrier="BASE MMS" apn="mms.base.be" mmsc="http://mmsc.base.be" mmsproxy="217.72.235.1" mmsport="8080" type="mms" user="base" password="base" authtype="1"></apn>
+      <apn mcc="206" mnc="20" carrier="Base MMS" apn="mms.base.be" mmsc="http://mmsc.base.be" mmsproxy="217.72.235.1" mmsport="8080" type="mms" user="base" password="base" authtype="0"></apn>
+      <apn mcc="208" mnc="01" carrier="Carrefour MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" mvno_match_data="33" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="01" carrier="NRJMMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" mvno_match_data="4E" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="01" carrier="Orange MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1"></apn>
+      <apn mcc="208" mnc="01" carrier="Tele2 MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange"></apn>
+      <apn mcc="208" mnc="01" carrier="VM MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" mvno_match_data="52" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="1" carrier="Carrefour MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" mvno_match_data="33" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="1" carrier="MMS Carrefour" apn="orange.acte" mmsc="http://mms.orange.fr/" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="0" mvno_match_data="Carrefour Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="1" carrier="NRJMMS" apn="orange.acte" mmsc="http://mms.orange.fr/" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="0" mvno_match_data="NRJ Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="1" carrier="Orange MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1"></apn>
+      <apn mcc="208" mnc="1" carrier="Orange MMS" apn="orange.acte" mmsc="http://mms.orange.fr/" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="0"></apn>
+      <apn mcc="208" mnc="1" carrier="Tele2 MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="3"></apn>
+      <apn mcc="208" mnc="1" carrier="VM MMS" apn="orange.acte" mmsc="http://mms.orange.fr" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" mvno_match_data="52" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="1" carrier="VM MMS FR" apn="orange.acte" mmsc="http://mms.orange.fr/" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange" authtype="0" mvno_match_data="Virgin Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="09" carrier="SFR webphone" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="default,mms,supl,agps,fota" protocol="IP"></apn>
+      <apn mcc="208" mnc="10" carrier="Auchan MMS" apn="mms65" mmsc="http://mms65" mmsproxy="10.143.156.8" mmsport="8080" type="mms" mvno_match_data="A MOBILE" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="Auchan MMS" apn="mms65" mmsc="http://mms65" mmsproxy="10.143.156.8" mmsport="8080" type="mms" authtype="0" mvno_match_data="A MOBILE" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="Coriolis MMS" apn="mmscoriolis" mmsc="http://mmscoriolis" mmsproxy="10.143.156.6" mmsport="8080" type="mms" mvno_match_data="12" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="Coriolis MMS" apn="mmscoriolis" mmsc="http://mmscoriolis" mmsproxy="10.143.156.6" mmsport="8080" type="mms" authtype="0" mvno_match_data="12" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="Coriolis MMS FR" apn="mmscoriolis" mmsc="http://mmscoriolis" mmsproxy="10.143.156.6" mmsport="8080" type="mms" authtype="0" mvno_match_data="Coriolis" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="DARTY MMS" apn="mms68" mmsc="http://mms68/" mmsproxy="10.143.156.11" mmsport="8080" type="mms" authtype="0" mvno_match_data="Darty" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="Darty MMS" apn="mms68" mmsc="http://mms68/" mmsproxy="10.143.156.11" mmsport="8080" type="mms" mvno_match_data="44" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="Darty MMS" apn="mms68" mmsc="http://mms68/" mmsproxy="10.143.156.11" mmsport="8080" type="mms" authtype="0" mvno_match_data="44" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="Internet Joe" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="default,mms,supl,agps,fota" authtype="0" mvno_match_data="53" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="Keyyo Mobile MMS" apn="mms68" mmsc="http://mms68" mmsproxy="10.143.156.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="208" mnc="10" carrier="Keyyo Mobile MMS" apn="mms68" mmsc="http://mms68" mmsproxy="10.143.156.11" mmsport="8080" type="mms" authtype="0" mvno_match_data="Keyyo Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS La Poste Mobile" apn="mmsdebitel" mmsc="http://mmsdebitel" mmsproxy="10.143.156.3" mmsport="8080" type="mms" mvno_match_data="4C" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS La Poste Mobile" apn="mmsdebitel" mmsc="http://mmsdebitel" mmsproxy="10.143.156.3" mmsport="8080" type="mms" authtype="0" mvno_match_data="4C" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS La Poste Mobile" apn="mmsdebitel" mmsc="http://mmsdebitel" mmsproxy="10.143.156.3" mmsport="8080" type="mms" authtype="0" mvno_match_data="La Poste Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS Leclerc mobile" apn="mms66" mmsc="http://mms66" mmsproxy="10.143.156.9" mmsport="8080" type="mms" authtype="0" mvno_match_data="Leclerc Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS LeclercMobile" apn="mms66" mmsc="http://mms66" mmsproxy="10.143.156.9" mmsport="8080" type="mms" mvno_match_data="LeclercMobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS LeclercMobile" apn="mms66" mmsc="http://mms66" mmsproxy="10.143.156.9" mmsport="8080" type="mms" authtype="0" mvno_match_data="LeclercMobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS RegloMobile" apn="mms66" mmsc="http://mms66" mmsproxy="10.143.156.9" mmsport="8080" type="mms" authtype="0" mvno_match_data="RegloMobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="MMS Simplicime" apn="mmsdebitel" mmsc="http://mmsdebitel" mmsproxy="10.143.156.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="208" mnc="10" carrier="NRJMMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" mvno_match_data="4E" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="NRJMMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" authtype="0" mvno_match_data="4E" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="10" carrier="NRJMMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" authtype="0" mvno_match_data="NRJ Mobile" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="SFR MMS" apn="mmssfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="208" mnc="10" carrier="SFR webphone" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="default,mms,supl"></apn>
+      <apn mcc="208" mnc="10" carrier="SFR webphone" apn="sl2sfr" mmsc="http://mms1" mmsproxy="10.151.0.1" mmsport="8080" type="default,mms,supl,agps,fota" authtype="0"></apn>
+      <apn mcc="208" mnc="10" carrier="WEB La Poste Mobile" apn="sl2sfr" mmsc="http://mmsdebitel" mmsproxy="10.143.156.3" mmsport="8080" type="default,mms,supl" mvno_match_data="4C" mvno_type="gid" proxy="192.168.21.3" port="8080"></apn>
+      <apn mcc="208" mnc="10" carrier="Zero forfait MMS" apn="mms68" mmsc="http://mms68" mmsproxy="10.143.156.11" mmsport="8080" type="mms" authtype="0" mvno_match_data="ZERO FORFAIT" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="10" carrier="mms65 Amobile" apn="mms65" mmsc="http://mms65" mmsproxy="10.143.156.8" mmsport="8080" type="mms" authtype="0" mvno_match_data="A MOBILE" mvno_type="spn"></apn>
+      <apn mcc="208" mnc="15" carrier="Free MMS" apn="mmsfree" mmsc="http://mms.free.fr" type="mms"></apn>
+      <apn mcc="208" mnc="15" carrier="Free MMS" apn="mmsfree" mmsc="http://mms.free.fr" type="mms" authtype="0"></apn>
+      <apn mcc="208" mnc="15" carrier="Free Telecom MMS" apn="mmsfree" mmsc="http://mms.free.fr" type="mms" authtype="0"></apn>
+      <apn mcc="208" mnc="20" carrier="Bouygues" apn="mmsbouygtel.com" mmsc="http://mms.bouyguestelecom.fr/mms/wapenc" mmsproxy="62.201.129.226" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="208" mnc="20" carrier="Bouygues Telecom" apn="mmsbouygtel.com" mmsc="http://mms.bouyguestelecom.fr/mms/wapenc" mmsproxy="62.201.129.226" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="208" mnc="20" carrier="Bouygues Telecom" apn="mmsbouygtel.com" mmsc="http://mms.bouyguestelecom.fr/mms/wapenc" mmsproxy="62.201.129.226" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="208" mnc="23" carrier="VM MMS" apn="virgin-mobile.fr" mmsc="http://virginmms.fr" mmsproxy="10.6.10.1" mmsport="8080" type="mms" mvno_match_data="52" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="23" carrier="VM MMS" apn="virgin-mobile.fr" mmsc="http://virginmms.fr" mmsproxy="10.6.10.1" mmsport="8080" type="mms" authtype="0" mvno_match_data="52" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="23" carrier="Virgin mobile" apn="virgin-mobile.fr" mmsc="http://mmc.omeatelecom.fr/servlets/mms" mmsproxy="10.6.10.1" mmsport="8080" type="default,mms" authtype="0" mvno_match_data="Virgin" mvno_type="spn" proxy="10.6.10.1" port="8080"></apn>
+      <apn mcc="208" mnc="26" carrier="NRJ MMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" mvno_match_data="4E" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="26" carrier="NRJ MMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" authtype="0" mvno_match_data="4E" mvno_type="gid"></apn>
+      <apn mcc="208" mnc="26" carrier="NRJMMS" apn="mmsnrj" mmsc="http://mmsnrj" mmsproxy="10.143.156.5" mmsport="8080" type="mms" authtype="0" mvno_match_data="NRJ Mobile" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="01" carrier="MMS VODAFONE" apn="mms.vodafone.net" mmsc="http://mmsc.vodafone.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125" authtype="1"></apn>
+      <apn mcc="214" mnc="03" carrier="Carrefour MMS" apn="CARREFOURMMS" mmsc="http://mms.orange.es" mmsproxy="172.022.188.025" mmsport="8080" type="mms" user="CARREFOUR" password="CARREFOUR" authtype="1" mvno_match_data="2140352xxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="03" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="1" mvno_match_data="2140359" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="03" carrier="Orange MMS" apn="orangemms" mmsc="http://mms.orange.es" mmsproxy="172.22.188.25" mmsport="8080" type="mms" user="orange" password="orange" authtype="1"></apn>
+      <apn mcc="214" mnc="3" carrier="Orange MMS" apn="orangemms" mmsc="http://mms.orange.es" mmsproxy="172.22.188.25" mmsport="8080" type="mms" user="orange" password="orange" authtype="0"></apn>
+      <apn mcc="214" mnc="04" carrier="Yoigo MMS" apn="mms" mmsc="http://mmss/" mmsproxy="193.209.134.141" mmsport="80" type="mms"></apn>
+      <apn mcc="214" mnc="4" carrier="Yoigo MMS" apn="mms" mmsc="http://mmss/" mmsproxy="193.209.134.141" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="214" mnc="4" carrier="Yoigo MMS" apn="mms" mmsc="http://mmss/" mmsproxy="193.209.134.141" mmsport="80" type="mms" authtype="1"></apn>
+      <apn mcc="214" mnc="05" carrier="Tuenti" apn="tuenti.com" mmsc="http://tuenti.com" mmsproxy="10.138.255.43" mmsport="8080" user="tuenti" password="tuenti" authtype="1"></apn>
+      <apn mcc="214" mnc="5" carrier="Tuenti" apn="tuenti.com" mmsc="http://tuenti.com" mmsproxy="10.138.255.43" mmsport="8080" user="tuenti" password="tuenti" authtype="1"></apn>
+      <apn mcc="214" mnc="06" carrier="Eroski Movil MMS" apn="mms.eroskimovil.es" mmsc="http://mms.eroskimovil.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125" authtype="1" mvno_match_data="2140606" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="06" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="1" mvno_match_data="0008" mvno_type="gid"></apn>
+      <apn mcc="214" mnc="06" carrier="MMS" apn="mms.pepephone.com" mmsc="http://mms.pepephone.com/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125" authtype="0" mvno_match_data="pepephone" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="06" carrier="MMS R" apn="mms.mundo-r.com" mmsc="http://mms.mundo-r.com" mmsproxy="10.0.157.169" mmsport="8080" type="mms" authtype="1" mvno_match_data="2140612" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="06" carrier="MMS Vodafone" apn="mms.vodafone.net" mmsc="http://mmsc.vodafone.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125"></apn>
+      <apn mcc="214" mnc="06" carrier="TeleCable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable" authtype="1" mvno_match_data="2140613" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="6" carrier="Eroski Movil MMS" apn="mms.eroskimovil.es" mmsc="http://mms.eroskimovil.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125" authtype="1" mvno_match_data="2140606" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="6" carrier="Eroski Movil MMS" apn="mms.eroskimovil.es" mmsc="http://mms.eroskimovil.es/servlets/mms" mmsproxy="212.73.32.10" mmsport="80" type="mms" user="wap@wap" password="wap125" authtype="1" mvno_match_data="Eroski Movil" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="6" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="0" mvno_match_data="EUSKALTEL" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="6" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="1" mvno_match_data="0008" mvno_type="gid"></apn>
+      <apn mcc="214" mnc="6" carrier="MMS R" apn="mms.mundo-r.com" mmsc="http://mms.mundo-r.com" mmsproxy="10.0.157.169" mmsport="8080" type="mms" authtype="1" mvno_match_data="2140612" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="6" carrier="R MMS" apn="mms.mundo-r.com" mmsc="http://mms.mundo-r.com" mmsproxy="10.0.157.169" mmsport="8080" type="mms" authtype="0" mvno_match_data="mobil R" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="6" carrier="TeleCable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable" authtype="1" mvno_match_data="2140613" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="6" carrier="telecable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable" authtype="1" mvno_match_data="telecable" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="07" carrier="Jazztel MMS" apn="jazzmms" mmsc="http://jazztelmms.com/servlets/mms" mmsproxy="37.132.0.10" mmsport="8080" type="mms" authtype="1" mvno_match_data="JAZZTEL" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="07" carrier="Jazztel MMS" apn="jazzmms" mmsc="http://jazztelmms.com/servlets/mms/" mmsproxy="37.132.0.10" mmsport="8080" type="mms" authtype="1" mvno_match_data="JAZZTEL" mvno_type="spn"></apn>
+      <apn mcc="214" mnc="07" carrier="Movistar" apn="telefonica.es" mmsc="http://mms.movistar.com" mmsproxy="10.138.255.5" mmsport="8080" type="default,supl,mms" user="telefonica" password="telefonica" authtype="1" proxy="10.138.255.133" port="8080"></apn>
+      <apn mcc="214" mnc="07" carrier="T-2" apn="internet.t-2.net" mmsc="http://www.mms.t-2.net:8002" mmsproxy="172.20.18.137" mmsport="8080" type="default,ims,mms,supl" mvno_match_data="2140759577xxxxx" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="07" carrier="T-2" apn="internet.t-2.net" mmsc="http://www.mms.t-2.net:8002" mmsproxy="172.20.18.137" mmsport="8080" type="default,ims,mms,supl" mvno_match_data="2140796692xxxxx" mvno_type="imsi"></apn>
+      <apn mcc="214" mnc="7" carrier="Movistar" apn="telefonica.es" mmsc="http://mms.movistar.com" mmsproxy="10.138.255.5" mmsport="8080" type="default,mms,supl,agps,fota" user="telefonica" password="telefonica" authtype="1" proxy="10.138.255.133" port="8080"></apn>
+      <apn mcc="214" mnc="7" carrier="Movistar" apn="telefonica.es" mmsc="http://mms.movistar.com" mmsproxy="10.138.255.5" mmsport="8080" type="default,supl,mms" user="telefonica" password="telefonica" authtype="1" proxy="10.138.255.133" port="8080"></apn>
+      <apn mcc="214" mnc="08" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="1"></apn>
+      <apn mcc="214" mnc="8" carrier="Euskaltel MMS" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="1"></apn>
+      <apn mcc="214" mnc="8" carrier="MMS Euskaltel" apn="euskaltelmms.euskaltel.mobi" mmsc="http://mms.euskaltel.mobi" mmsproxy="172.16.18.74" mmsport="8080" type="mms" user="MMS" password="EUSKALTEL" authtype="0"></apn>
+      <apn mcc="214" mnc="16" carrier="TeleCable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable"></apn>
+      <apn mcc="214" mnc="16" carrier="TeleCable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable" authtype="3"></apn>
+      <apn mcc="214" mnc="16" carrier="Telecable MMS" apn="mms.telecable.es" mmsc="http://mms.telecable.es/mms/" mmsproxy="212.89.0.84" mmsport="8080" type="mms" user="telecable" password="telecable" authtype="0"></apn>
+      <apn mcc="214" mnc="18" carrier="ONO MMS" apn="mms.ono.com" mmsc="http://mms.ono.com" mmsproxy="10.126.0.50" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="214" mnc="18" carrier="ONO MMS" apn="mms.ono.com" mmsc="http://mms.ono.com/" mmsproxy="10.126.0.50" mmsport="8080" type="mms"></apn>
+      <apn mcc="214" mnc="18" carrier="ONO MMS" apn="mms.ono.com" mmsc="http://mms.ono.com/" mmsproxy="10.126.0.50" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="214" mnc="19" carrier="KPN" apn="gprs-service.com" mmsc="http://217.18.32.180:8080" mmsproxy="217.18.32.181" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="214" mnc="19" carrier="Simyo Internet" apn="gprs-service.com" mmsc="http://217.18.32.180:8080" mmsproxy="217.18.32.181" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="214" mnc="19" carrier="Simyo Internet" apn="gprs-service.com" mmsc="http://217.18.32.180:8080" mmsproxy="217.18.32.181" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="214" mnc="21" carrier="Jazztel MMS" apn="jazzmms" mmsc="http://jazztelmms.com/servlets/mms" mmsproxy="37.132.0.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="214" mnc="21" carrier="Jazztel MMS" apn="jazzmms" mmsc="http://jazztelmms.com/servlets/mms/" mmsproxy="37.132.0.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="214" mnc="21" carrier="MMS" apn="jazzmms" mmsc="http://jazztelmms.com:8081" mmsproxy="217.18.32.183" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="216" mnc="01" carrier="Djuice MMS" apn="mms" mmsc="http://mmsc.pgsm.hu/" mmsproxy="84.225.255.1" mmsport="8080" type="mms" authtype="0" mvno_match_data="Djuice" mvno_type="spn"></apn>
+      <apn mcc="216" mnc="01" carrier="Telenor MMS" apn="mms" mmsc="http://mmsc.telenor.hu/" mmsproxy="84.225.255.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="216" mnc="1" carrier="Telenor HU MMS" apn="mms" mmsc="http://mmsc.telenor.hu" mmsproxy="84.225.255.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="216" mnc="1" carrier="Telenor MMS" apn="mms" mmsc="http://mmsc.telenor.hu/" mmsproxy="84.225.255.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="216" mnc="30" carrier="T-Mobile H" apn="internet.telekom" mmsc="http://mms.t-mobile.hu/servlets/mms" mmsproxy="212.51.126.10" mmsport="8080" type="default,mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="216" mnc="30" carrier="T-Mobile H MMS" apn="internet.telekom" mmsc="http://mms.t-mobile.hu/servlets/mms" mmsproxy="212.51.126.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="216" mnc="30" carrier="T-Mobile MMS" apn="mms" mmsc="http://mms.t-mobile.hu/servlets/mms" mmsproxy="212.51.126.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="216" mnc="70" carrier="Vodafone MMS" apn="mms.vodafone.net" mmsc="http://mms.vodafone.hu/servlets/mms" mmsproxy="80.244.97.2" mmsport="8080" type="mms" mvno_match_data="21670xx1xxx" mvno_type="imsi"></apn>
+      <apn mcc="216" mnc="70" carrier="Vodafone MMS" apn="mms.vodafone.net" mmsc="http://mms.vodafone.hu/servlets/mms" mmsproxy="80.244.97.2" mmsport="8080" type="mms" authtype="0" mvno_match_data="21670xx2xxx" mvno_type="imsi"></apn>
+      <apn mcc="218" mnc="03" carrier="Ht Eronet MMS" apn="mms.eronet.ba" mmsc="http://mms.gprs.eronet.ba/mms/wapenc" mmsproxy="10.12.3.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="218" mnc="3" carrier="Eronet BH MMS" apn="mms.eronet.ba" mmsc="http://mms.gprs.eronet.ba/mms/wapenc" mmsproxy="10.12.3.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="218" mnc="3" carrier="Ht Eronet MMS" apn="mms.eronet.ba" mmsc="http://mms.gprs.eronet.ba/mms/wapenc" mmsproxy="10.12.3.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="218" mnc="05" carrier="mtelmms" apn="mtelmms" mmsc="http://mmsc.mtel.ba/mms/wapenc" mmsproxy="192.168.61.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="218" mnc="5" carrier="mtel MMS" apn="mtelmms" mmsc="http://mmsc.mtel.ba/mms/wapenc" mmsproxy="192.168.61.11" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="218" mnc="5" carrier="mtelmms" apn="mtelmms" mmsc="http://mmsc.mtel.ba/mms/wapenc" mmsproxy="192.168.61.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="218" mnc="90" carrier="BH Mobile MMS" apn="mms.bhmobile.ba" mmsc="http://mms.bhmobile.ba/cmmsc/post" mmsproxy="195.222.56.41" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="218" mnc="90" carrier="BHMobileMMS" apn="mms.bhmobile.ba" mmsc="http://mms.bhmobile.ba/cmmsc/post" mmsproxy="195.222.56.41" mmsport="8080" type="mms"></apn>
+      <apn mcc="218" mnc="90" carrier="BHMobileMMS" apn="mms.bhmobile.ba" mmsc="http://mms.bhmobile.ba/cmmsc/post" mmsproxy="195.222.56.41" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="219" mnc="01" carrier="T-Mobile MMS" apn="mms.htgprs" mmsc="http://mms.t-mobile.hr/servlets/mms" mmsproxy="10.12.0.4" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="219" mnc="01" carrier="bonbon MMS" apn="mms.htgprs" mmsc="http://mms.bonbon.com.hr/servlets/mms" mmsproxy="10.12.0.4" mmsport="8080" type="mms" authtype="1" mvno_match_data="bonbon" mvno_type="spn"></apn>
+      <apn mcc="219" mnc="1" carrier="MMS" apn="mms.htgprs" mmsc="http://mms.t-mobile.hr/servlets/mms" mmsproxy="10.12.0.4" mmsport="8080" type="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="219" mnc="1" carrier="T-Mobile MMS" apn="mms.htgprs" mmsc="http://mms.t-mobile.hr/servlets/mms" mmsproxy="10.12.0.4" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="219" mnc="02" carrier="Tele2" apn="internet.tele2.hr" mmsc="http://mmsc.tele2.hr" mmsproxy="193.12.40.66" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="219" mnc="2" carrier="TELE2" apn="internet.tele2.hr" mmsc="http://mmsc.tele2.hr" mmsproxy="193.12.40.66" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="219" mnc="2" carrier="Tele2" apn="internet.tele2.hr" mmsc="http://mmsc.tele2.hr" mmsproxy="193.12.40.66" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="219" mnc="10" carrier="HR VIP mms" apn="mms.vipnet.hr" mmsc="http://mms.vipnet.hr/servlets/mms" mmsproxy="212.91.99.91" mmsport="8080" type="mms" user="38591" password="38591" authtype="0"></apn>
+      <apn mcc="219" mnc="10" carrier="VIP.mms" apn="mms.vipnet.hr" mmsc="http://mms.vipnet.hr/servlets/mms" mmsproxy="212.91.99.91" mmsport="8080" type="mms"></apn>
+      <apn mcc="219" mnc="10" carrier="VIP.mms" apn="mms.vipnet.hr" mmsc="http://mms.vipnet.hr/servlets/mms" mmsproxy="212.91.99.91" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="220" mnc="01" carrier="Telenor MMS" apn="mms" mmsc="http://mms.telenor.rs/servlets/mms" mmsproxy="217.65.192.33" mmsport="8080" type="mms"></apn>
+      <apn mcc="220" mnc="1" carrier="Telenor MMS" apn="mms" mmsc="http://mms.telenor.rs/servlets/mms" mmsproxy="217.65.192.33" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="220" mnc="1" carrier="Telenor SRB MMS" apn="mms" mmsc="http://mms.telenor.rs/servlets/mms" mmsproxy="217.65.192.33" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="220" mnc="02" carrier="Telenor MNE mms" apn="mms" mmsc="http://mm.vor.telenor.me" mmsproxy="192.168.246.5" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="220" mnc="2" carrier="Telenor MNE mms" apn="mms" mmsc="http://mm.vor.telenor.me" mmsproxy="192.168.246.5" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="220" mnc="03" carrier="mt:s mms" apn="mms" mmsc="http://mms.mts064.telekom.rs/mms/wapenc" mmsproxy="172.17.85.131" mmsport="8080" type="mms" user="mts" password="064" authtype="1"></apn>
+      <apn mcc="220" mnc="3" carrier="MTS MMS RS" apn="mms" mmsc="http://mms.mts064.telekom.rs/mms/wapenc" mmsproxy="172.17.85.131" mmsport="8080" type="mms" user="mts" password="064" authtype="0"></apn>
+      <apn mcc="220" mnc="04" carrier="T-Mobile MMS" apn="mms" mmsc="http://192.168.180.100/servlets/mms" mmsproxy="10.0.5.19" mmsport="8080" type="mms" user="38267" password="38267"></apn>
+      <apn mcc="220" mnc="05" carrier="Vip MMS" apn="vipmobile.mms" mmsc="http://mmsc.vipmobile.rs" mmsproxy="212.15.182.82" mmsport="8080" type="mms" user="vipmobile" password="vipmobile" authtype="1"></apn>
+      <apn mcc="220" mnc="5" carrier="Vip SRB MMS" apn="vipmobile.mms" mmsc="http://mmsc.vipmobile.rs" mmsproxy="212.15.182.82" mmsport="8080" type="mms" user="vipmobile" password="vipmobile" authtype="0"></apn>
+      <apn mcc="222" mnc="01" carrier="MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="0" mvno_match_data="IUSACELL" mvno_type="spn"></apn>
+      <apn mcc="222" mnc="01" carrier="MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="0" mvno_match_data="UNEFON" mvno_type="spn"></apn>
+      <apn mcc="222" mnc="01" carrier="MMS" apn="mms.windmobile.ca" mmsc="http://mms.windmobile.ca" mmsproxy="74.115.197.70" mmsport="8080" type="mms" mvno_match_data="FFFFFF00" mvno_type="gid"></apn>
+      <apn mcc="222" mnc="01" carrier="NOVERCA MMS" apn="mms.noverca.it" mmsc="http://mms.noverca.it/" mmsproxy="213.230.130.89" mmsport="80" type="mms" authtype="0" mvno_match_data="Noverca" mvno_type="spn"></apn>
+      <apn mcc="222" mnc="01" carrier="TIM MMS" apn="unico.tim.it" mmsc="http://mms.tim.it/servlets/mms" mmsproxy="213.230.130.89" mmsport="80" type="mms"></apn>
+      <apn mcc="222" mnc="1" carrier="TIM MMS" apn="unico.tim.it" mmsc="http://mms.tim.it/servlets/mms" mmsproxy="213.230.130.89" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="222" mnc="10" carrier="MMS Vodafone" apn="mms.vodafone.it" mmsc="http://mms.vodafone.it/servlets/mms" mmsproxy="10.128.224.10" mmsport="80" type="mms"></apn>
+      <apn mcc="222" mnc="10" carrier="MMS Vodafone" apn="mms.vodafone.it" mmsc="http://mms.vodafone.it/servlets/mms" mmsproxy="10.128.224.10" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="222" mnc="10" carrier="PosteMobile MMS" apn="mms.postemobile.it" mmsc="http://mms.postemobile.it/servlets/mms" mmsproxy="10.128.224.10" mmsport="80" type="mms" authtype="0" mvno_match_data="PosteMobile" mvno_type="spn"></apn>
+      <apn mcc="222" mnc="88" carrier="MMS" apn="mms.windmobile.ca" mmsc="http://mms.windmobile.ca" mmsproxy="74.115.197.70" mmsport="8080" type="mms" mvno_match_data="FFFFFF00" mvno_type="gid"></apn>
+      <apn mcc="222" mnc="88" carrier="MMS WIND" apn="mms.wind" mmsc="http://mms.wind.it" mmsproxy="212.245.244.100" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="222" mnc="88" carrier="WIND MMS" apn="mms.wind" mmsc="http://mms.wind.it" mmsproxy="212.245.244.100" mmsport="8080" type="mms"></apn>
+      <apn mcc="222" mnc="88" carrier="WIND MMS" apn="mms.wind" mmsc="http://mms.wind.it" mmsproxy="212.245.244.100" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="222" mnc="99" carrier="3" apn="tre.it" mmsc="http://10.216.59.240:10021/mmsc" mmsproxy="62.13.171.3" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="222" mnc="99" carrier="3" apn="tre.it" mmsc="http://10.216.59.240:10021/mmsc" mmsproxy="62.13.171.3" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="222" mnc="99" carrier="3 ITA" apn="tre.it" mmsc="http://10.216.59.240:10021/mmsc" mmsproxy="62.13.171.3" mmsport="8799" type="default,mms" authtype="0" port="80"></apn>
+      <apn mcc="222" mnc="99" carrier="Fastweb" apn="apn.fastweb.it" mmsc="http://mms.fastweb.it/mms/wapenc" mmsproxy="10.0.65.9" mmsport="8080" type="default,mms" authtype="0" mvno_match_data="FASTWEB" mvno_type="spn" port="80"></apn>
+      <apn mcc="222" mnc="99" carrier="Fastweb WEB" apn="apn.fastweb.it" mmsc="http://mms.fastweb.it/mms/wapenc" mmsproxy="10.0.65.9" mmsport="8080" type="default,supl,mms" mvno_match_data="FASTWEB" mvno_type="spn"></apn>
+      <apn mcc="222" mnc="99" carrier="Fastweb WEB" apn="apn.fastweb.it" mmsc="http://mms.fastweb.it/mms/wapenc" mmsproxy="10.0.65.9" mmsport="8080" type="default,supl,mms" authtype="0" mvno_match_data="FASTWEB" mvno_type="spn"></apn>
+      <apn mcc="226" mnc="01" carrier="Vodafone MMS" apn="mms.vodafone.ro" mmsc="http://multimedia/servlets/mms" mmsproxy="193.230.161.231" mmsport="8080" type="mms" user="mms" password="vodafone" authtype="1"></apn>
+      <apn mcc="226" mnc="1" carrier="Vodafone MMS" apn="mms.vodafone.ro" mmsc="http://multimedia/servlets/mms" mmsproxy="193.230.161.231" mmsport="8080" type="mms" user="mms" password="vodafone" authtype="1"></apn>
+      <apn mcc="226" mnc="1" carrier="Vodafone RO MMS" apn="mms.vodafone.ro" mmsc="http://multimedia/servlets/mms" mmsproxy="193.230.161.231" mmsport="8080" type="mms" user="mms" password="vodafone" authtype="0"></apn>
+      <apn mcc="226" mnc="03" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="226" mnc="3" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="226" mnc="3" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="226" mnc="05" carrier="MMS" apn="mms" mmsc="http://10.10.3.133:8002" mmsproxy="10.10.3.130" mmsport="8080" type="mms"></apn>
+      <apn mcc="226" mnc="5" carrier="MMS" apn="mms" mmsc="http://10.10.3.133:8002" mmsproxy="10.10.3.130" mmsport="8080" type="mms"></apn>
+      <apn mcc="226" mnc="06" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="226" mnc="6" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="226" mnc="6" carrier="Cosmote MMS" apn="mms" mmsc="http://mmsc1.mms.cosmote.ro:8002" mmsproxy="10.252.1.62" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="226" mnc="10" carrier="ORANGE RO MMS" apn="mms" mmsc="http://wap.mms.orange.ro:8002" mmsproxy="62.217.247.252" mmsport="8799" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="226" mnc="10" carrier="Orange MMS" apn="mms" mmsc="http://wap.mms.orange.ro:8002" mmsproxy="62.217.247.252" mmsport="8799" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="228" mnc="01" carrier="Swisscom MMS" apn="event.swisscom.ch" mmsc="http://mms.natel.ch:8079" mmsproxy="192.168.210.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="228" mnc="1" carrier="Swisscom MMS" apn="event.swisscom.ch" mmsc="http://mms.natel.ch:8079" mmsproxy="192.168.210.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="228" mnc="1" carrier="Swisscom MMS (CH)" apn="event.swisscom.ch" mmsc="http://mms.natel.ch:8079" mmsproxy="192.168.210.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="228" mnc="02" carrier="Sunrise MMS" apn="mms.sunrise.ch" mmsc="http://mmsc.sunrise.ch" mmsproxy="212.35.34.75" mmsport="8080" type="mms"></apn>
+      <apn mcc="228" mnc="2" carrier="Sunrise MMS" apn="mms.sunrise.ch" mmsc="http://mmsc.sunrise.ch" mmsproxy="212.35.34.75" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="228" mnc="2" carrier="Sunrise MMS (CH)" apn="mms.sunrise.ch" mmsc="http://mmsc.sunrise.ch" mmsproxy="212.35.34.75" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="228" mnc="03" carrier="Orange MMS" apn="mms" mmsc="http://192.168.151.3:8002" mmsproxy="192.168.151.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="228" mnc="3" carrier="Orange MMS" apn="mms" mmsc="http://192.168.151.3:8002" mmsproxy="192.168.151.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="228" mnc="3" carrier="Orange MMS (CH)" apn="mms" mmsc="http://192.168.151.3:8002" mmsproxy="192.168.151.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="230" mnc="01" carrier="T-Mobile CZ" apn="internet.t-mobile.cz" mmsc="http://mms" mmsproxy="010.000.000.010" mmsport="80" type="default,supl"></apn>
+      <apn mcc="230" mnc="01" carrier="T-Mobile CZ MMS" apn="mms.t-mobile.cz" mmsc="http://mms" mmsproxy="010.000.000.010" mmsport="80" type="mms"></apn>
+      <apn mcc="230" mnc="01" carrier="T-Mobile MMS" apn="mms.t-mobile.cz" mmsc="http://mms" mmsproxy="10.0.0.10" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="230" mnc="1" carrier="T-Mobile MMS" apn="mms.t-mobile.cz" mmsc="http://mms" mmsproxy="10.0.0.10" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="230" mnc="1" carrier="T-Mobile MMS" apn="mms.t-mobile.cz" mmsc="http://mms" mmsproxy="10.0.0.10" mmsport="80" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="230" mnc="02" carrier="O2 MMS" apn="mms" mmsc="http://mms.o2active.cz:8002" mmsproxy="160.218.160.218" mmsport="8080" type="mms"></apn>
+      <apn mcc="230" mnc="2" carrier="O2 MMS" apn="mms" mmsc="http://mms.o2active.cz:8002" mmsproxy="160.218.160.218" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="230" mnc="03" carrier="MMS" apn="mms" mmsc="http://mms" mmsproxy="10.11.10.111" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="230" mnc="03" carrier="Vodafone MMS" apn="mms" mmsc="http://mms" mmsproxy="10.11.10.111" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="230" mnc="3" carrier="MMS" apn="mms" mmsc="http://mms" mmsproxy="10.11.10.111" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="230" mnc="3" carrier="Vodafone CZ mms" apn="mms" mmsc="http://mms" mmsproxy="10.11.10.111" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="231" mnc="01" carrier="Orange SK MMS" apn="mms" mmsc="http://imms.orange.sk" mmsproxy="213.151.208.145" mmsport="8799" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="231" mnc="1" carrier="Orange  MMS" apn="mms" mmsc="http://imms.orange.sk" mmsproxy="213.151.208.145" mmsport="8799" type="mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="231" mnc="1" carrier="Orange SK MMS" apn="mms" mmsc="http://imms.orange.sk" mmsproxy="213.151.208.145" mmsport="8799" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="231" mnc="02" carrier="T-Mobile MMS" apn="mms" mmsc="http://mms" mmsproxy="192.168.1.1" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="231" mnc="2" carrier="T-Mobile MMS" apn="mms" mmsc="http://mms" mmsproxy="192.168.1.1" mmsport="8080" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="231" mnc="06" carrier="O2 MMS" apn="o2mms" mmsc="http://mms.o2world.sk:8002" mmsproxy="10.97.1.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="231" mnc="6" carrier="O2 MMS" apn="o2mms" mmsc="http://mms.o2world.sk:8002" mmsproxy="10.97.1.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="231" mnc="6" carrier="O2-SK mms" apn="o2mms" mmsc="http://mms.o2world.sk:8002" mmsproxy="10.97.1.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="232" mnc="01" carrier="A1 MMS" apn="free.a1.net" mmsc="http://mmsc.a1.net" mmsproxy="194.48.124.71" mmsport="8001" type="mms" user="ppp@a1plus.at" password="ppp" authtype="1"></apn>
+      <apn mcc="232" mnc="1" carrier="MMS Account" apn="free.A1.net" mmsc="http://mmsc.A1.net" mmsproxy="194.48.124.85" mmsport="8001" type="mms" user="ppp@A1plus.at" password="ppp" authtype="2" server="*"></apn>
+      <apn mcc="232" mnc="03" carrier="T-Mobile A" apn="gprsinternet" mmsc="http://mmsc.t-mobile.at/servlets/mms" mmsproxy="010.012.000.020" mmsport="80" type="default,supl"></apn>
+      <apn mcc="232" mnc="03" carrier="T-Mobile A MMS" apn="gprsmms" mmsc="http://mmsc.t-mobile.at/servlets/mms" mmsproxy="010.012.000.020" mmsport="80" type="mms"></apn>
+      <apn mcc="232" mnc="03" carrier="T-Mobile MMS" apn="gprsmms" mmsc="http://mmsc.t-mobile.at/servlets/mms" mmsproxy="10.12.0.20" mmsport="80" type="mms" user="t-mobile" password="tm" authtype="1"></apn>
+      <apn mcc="232" mnc="3" carrier="T-Mobile MMS" apn="gprsmms" mmsc="http://mmsc.t-mobile.at/servlets/mms" mmsproxy="10.12.0.20" mmsport="80" type="mms" user="t-mobile" password="tm" authtype="1"></apn>
+      <apn mcc="232" mnc="3" carrier="T-Mobile MMS" apn="gprsmms" mmsc="http://mmsc.t-mobile.at/servlets/mms" mmsproxy="10.12.0.20" mmsport="80" type="mms" user="t-mobile" password="tm" authtype="1" protocol="IP"></apn>
+      <apn mcc="232" mnc="05" carrier="Planet 3" apn="drei.at" mmsc="http://mmsc" mmsproxy="213.94.78.133" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="232" mnc="5" carrier="Orange MMS (AT)" apn="orange.mms" mmsc="http://mmsc.orange.at/mms/wapenc" mmsproxy="194.24.128.118" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="232" mnc="5" carrier="Planet 3" apn="drei.at" mmsc="http://mmsc" mmsproxy="213.94.78.133" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="232" mnc="07" carrier="tele.ring mms" apn="mms" mmsc="http://relay.mms.telering.at" mmsproxy="212.95.31.50" mmsport="80" type="mms" user="wap@telering.at" password="wap" authtype="1"></apn>
+      <apn mcc="232" mnc="7" carrier="telering mms" apn="mms" mmsc="http://relay.mms.telering.at" mmsproxy="212.95.31.50" mmsport="80" type="mms" user="wap@telering.at" password="wap" authtype="1" protocol="IP"></apn>
+      <apn mcc="232" mnc="10" carrier="3 AT" apn="drei.at" mmsc="http://mmsc" mmsproxy="213.94.78.133" mmsport="8799" type="default,mms" authtype="0"></apn>
+      <apn mcc="232" mnc="10" carrier="Planet3" apn="drei.at" mmsc="http://mmsc" mmsproxy="213.94.78.133" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="232" mnc="10" carrier="Planet3" apn="drei.at" mmsc="http://mmsc" mmsproxy="213.94.78.133" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="232" mnc="11" carrier="data.bob MMS" apn="mms.bob.at" mmsc="http://mmsc.bob.at" mmsproxy="194.48.124.7" mmsport="8001" type="mms" user="data@bob.at" password="ppp" authtype="1"></apn>
+      <apn mcc="232" mnc="11" carrier="data.bob mms" apn="mms.bob.at" mmsc="http://mmsc.bob.at" mmsproxy="194.48.124.7" mmsport="8001" type="mms" user="data@bob.at" password="ppp" authtype="0"></apn>
+      <apn mcc="234" mnc="02" carrier="O2 MMS Postpay" apn="wap.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="o2wap" password="password"></apn>
+      <apn mcc="234" mnc="02" carrier="O2 MMS Prepay" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="payandgo" password="password"></apn>
+      <apn mcc="234" mnc="08" carrier="BT One Phone MMS" apn="mms.btonephone.com" mmsc="http://MMSC/" mmsproxy="proxy.btonephone.com" mmsport="8080" type="mms" mvno_match_data="B2" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="10" carrier="O2 MMS" apn="wap.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="o2wap" password="password" authtype="0"></apn>
+      <apn mcc="234" mnc="10" carrier="O2 MMS" apn="wap.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="o2wap" password="password" authtype="1"></apn>
+      <apn mcc="234" mnc="10" carrier="O2 Pay &amp; Go" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="default,mms" user="payandgo" password="password" authtype="0"></apn>
+      <apn mcc="234" mnc="10" carrier="O2 Pay &amp; Go" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="default,supl,mms" user="payandgo" password="password" proxy="82.132.254.1" port="8080"></apn>
+      <apn mcc="234" mnc="10" carrier="O2 Pay &amp; Go" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="default,supl,mms" user="payandgo" password="password" authtype="3" proxy="82.132.254.1" port="8080"></apn>
+      <apn mcc="234" mnc="10" carrier="TESCO" apn="prepay.tesco-mobile.com" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="193.113.200.195" mmsport="8080" type="default,supl,mms" user="tescowap" password="password" authtype="1" mvno_match_data="0A" mvno_type="gid" proxy="193.113.200.195" port="8080"></apn>
+      <apn mcc="234" mnc="10" carrier="Tesco Mobile" apn="prepay.tesco-mobile.com" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="193.113.200.195" mmsport="8080" type="default,mms" user="tescowap" password="password" authtype="1" mvno_match_data="TESCO" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="10" carrier="giffgaff" apn="giffgaff.com" mmsc="http://mmsc.mediamessaging.co.uk:8002" mmsproxy="193.113.200.195" mmsport="8080" user="giffgaff" password="password" authtype="1" mvno_match_data="giffgaff" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="11" carrier="O2 MMS Postpay" apn="wap.o2.co.uk" mmsc="http://mmsc.mms.02.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="o2wap" password="password"></apn>
+      <apn mcc="234" mnc="11" carrier="O2 MMS Postpay" apn="wap.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="o2wap" password="password"></apn>
+      <apn mcc="234" mnc="11" carrier="O2 MMS Prepay" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.02.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="payandgo" password="password"></apn>
+      <apn mcc="234" mnc="11" carrier="O2 MMS Prepay" apn="payandgo.o2.co.uk" mmsc="http://mmsc.mms.o2.co.uk:8002" mmsproxy="82.132.254.1" mmsport="8080" type="mms" user="payandgo" password="password"></apn>
+      <apn mcc="234" mnc="15" carrier="ASDA Mobile" apn="asdamobiles.co.uk" mmsc="http://mms.asdamobiles.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" user="wap" password="wap" authtype="0" mvno_match_data="ASDA Mobile" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="ASDA WAP" apn="asdamobiles.co.uk" mmsc="http://mms.asdamobiles.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1" mvno_match_data="A0" mvno_type="gid" proxy="212.183.137.12" port="8799"></apn>
+      <apn mcc="234" mnc="15" carrier="BT Mobile" apn="btmobile.bt.com" mmsc="http://mms.bt.com/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" user="bt" password="bt" authtype="1" mvno_match_data="B3" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="15" carrier="Contract WAP" apn="wap.vodafone.co.uk" mmsc="http://mms.vodafone.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="234" mnc="15" carrier="Lebara Internet" apn="uk.lebara.mobi" mmsc="http://mms.lebara.co.uk/servlets/mms" mmsproxy="212.183.137.012" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1" mvno_match_data="Lebara" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="PAYG WAP" apn="pp.vodafone.co.uk" mmsc="http://mms.vodafone.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="234" mnc="15" carrier="Sainsbury&#39;s PAYG" apn="payg.mobilebysainsburys.co.uk" mmsc="http://mms.mobilebysainsburys.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" authtype="1" mvno_match_data="Sainsbury&#39;s" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="TalkTalk" apn="mobile.talktalk.co.uk" mmsc="http://mms.talktalk.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" user="wap" password="wap" authtype="0" mvno_match_data="TalkTalk" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="TalkTalk WAP" apn="mobile.talktalk.co.uk" mmsc="http://mms.talktalk.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" mvno_match_data="70" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="15" carrier="TalkTalk WAP" apn="mobile.talktalk.co.uk" mmsc="http://mms.talktalk.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" authtype="0" mvno_match_data="70" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="15" carrier="Talkmob Internet" apn="talkmobile.co.uk" mmsc="http://mms.talkmobile.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" password="wap" authtype="0" mvno_match_data="Talkmobile" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="Talkmob PAYG Int" apn="payg.talkmobile.co.uk" mmsc="http://mms.talkmobile.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,mms" password="wap" authtype="0" mvno_match_data="Talkmobile" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="15" carrier="Talkmob PAYG WAP" apn="payg.talkmobile.co.uk" mmsc="http://mms.talkmobile.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1" mvno_match_data="C1" mvno_type="gid" proxy="212.183.137.12" port="8799"></apn>
+      <apn mcc="234" mnc="15" carrier="Talkmob WAP" apn="talkmobile.co.uk" mmsc="http://mms.talkmobile.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1" mvno_match_data="C1" mvno_type="gid" proxy="212.183.137.12" port="8799"></apn>
+      <apn mcc="234" mnc="15" carrier="Vodafone UK" apn="wap.vodafone.co.uk" mmsc="http://mms.vodafone.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="234" mnc="15" carrier="Vodafone UK Prepay" apn="pp.vodafone.co.uk" mmsc="http://mms.vodafone.co.uk/servlets/mms" mmsproxy="212.183.137.12" mmsport="8799" type="default,supl,mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="234" mnc="20" carrier="3" apn="three.co.uk" mmsc="http://mms.um.three.co.uk:10021/mmsc" mmsproxy="mms.three.co.uk" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="234" mnc="20" carrier="3" apn="three.co.uk" mmsc="http://mms.um.three.co.uk:10021/mmsc" mmsproxy="mms.three.co.uk" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="234" mnc="20" carrier="3 UK" apn="three.co.uk" mmsc="http://mms.um.three.co.uk:10021/mmsc" mmsproxy="217.171.129.2" mmsport="8799" type="default,mms" authtype="0"></apn>
+      <apn mcc="234" mnc="30" carrier="BT MMS" apn="mms.bt.com" mmsc="http://MMS/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="bt" password="bt" authtype="1" mvno_match_data="B3" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="30" carrier="BT MMS" apn="mms.bt.com" mmsc="http://MMS/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="bt" password="bt" authtype="1" mvno_match_data="C3" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="30" carrier="BT One Phone MMS" apn="mms.btonephone.com" mmsc="http://MMSC/" mmsproxy="proxy.btonephone.com" mmsport="8080" type="mms" mvno_match_data="B2" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="30" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="30" carrier="MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="30" carrier="T-Mobile UK" apn="general.t-mobile.uk" mmsc="http://mmsc.t-mobile.co.uk:8002" mmsproxy="149.254.201.135" mmsport="8080"></apn>
+      <apn mcc="234" mnc="30" carrier="Virgin Media Mobile Internet" apn="goto.virginmobile.uk" mmsc="http://mms.virginmobile.co.uk:8002" mmsproxy="193.30.166.2" mmsport="8080" type="default,mms" user="user" authtype="0" mvno_match_data="Virgin" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="30" carrier="Virgin Media Mobile Internet" apn="goto.virginmobile.uk" mmsc="http://mms.virginmobile.co.uk:8002" mmsproxy="193.30.166.2" mmsport="8080" type="default,supl,mms" user="user" authtype="1" mvno_match_data="28" mvno_type="gid"></apn>
+      <apn mcc="234" mnc="31" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="32" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="33" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="33" carrier="MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="33" carrier="MMS" apn="tslmms" mmsc="http://mms/" mmsproxy="193.35.133.194" mmsport="8080" type="mms" user="wap" password="wap" authtype="1" mvno_match_data="LIFE" mvno_type="spn"></apn>
+      <apn mcc="234" mnc="34" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="234" mnc="50" carrier="Jersey Telecom" apn="mms" mmsc="http://mms.surfmail.com/mmsc" mmsproxy="212.9.19.199" mmsport="3130" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="234" mnc="55" carrier="Sure Picture Messaging" apn="mms" mmsc="http://mmsc.gprs.cw.com/" mmsproxy="10.0.3.101" mmsport="80" type="mms"></apn>
+      <apn mcc="234" mnc="58" carrier="Manx Telecom Contract MMS" apn="mms.manxpronto.net" mmsc="http://mms.manxpronto.net:8002" mmsproxy="195.10.99.46" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="234" mnc="58" carrier="Manx Telecom Prepay MMS" apn="mms.prontogo.net" mmsc="http://mms.manxpronto.net:8002" mmsproxy="195.10.99.41" mmsport="8080" type="mms" user="mmsgo" password="mmsgo"></apn>
+      <apn mcc="234" mnc="86" carrier="EE MMS" apn="eezone" mmsc="http://mms/" mmsproxy="149.254.201.135" mmsport="8080" type="mms" user="eesecure" password="secure" authtype="1"></apn>
+      <apn mcc="235" mnc="94" carrier="3" apn="three.co.uk" mmsc="http://mms.um.three.co.uk:10021/mmsc" mmsproxy="mms.three.co.uk" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="238" mnc="01" carrier="DK TDC mms" apn="mms" mmsc="http://192.168.241.114:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="238" mnc="01" carrier="TDC MMS" apn="mms" mmsc="http://mmsc.tdc.dk:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" mvno_match_data="2380101xxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="238" mnc="01" carrier="Telmore MMS" apn="mms" mmsc="http://192.168.241.114:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" mvno_match_data="TELMORE" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="1" carrier="TDC MMS" apn="mms" mmsc="http://mmsc.tdc.dk:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" authtype="0" mvno_match_data="2380101xxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="238" mnc="1" carrier="TELMORE MMS" apn="mms" mmsc="http://192.168.241.114:8002" mmsproxy="194.182.251.15" mmsport="8080" type="mms" authtype="0" mvno_match_data="TELMORE" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="02" carrier="BiBoB" apn="mms.bibob.dk" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms" mvno_match_data="BiBoB" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="02" carrier="CBB MMS" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms" mvno_match_data="CBB Mobil" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="02" carrier="Telenor MMS" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms"></apn>
+      <apn mcc="238" mnc="2" carrier="Sonofon mms" apn="sonofon" mmsc="http://mms.sonofon.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="238" mnc="2" carrier="Telenor MMS" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="238" mnc="06" carrier="3" apn="data.tre.dk" mmsc="http://mms.3.dk/" mmsproxy="mmsproxy.3.dk" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="238" mnc="6" carrier="3" apn="data.tre.dk" mmsc="http://mms.3.dk/" mmsproxy="mmsproxy.3.dk" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="238" mnc="6" carrier="3 DK" apn="data.tre.dk" mmsc="http://mms.3.dk" mmsproxy="172.16.1.25" mmsport="8799" type="default,mms" authtype="0" port="80"></apn>
+      <apn mcc="238" mnc="20" carrier="Call me MMS" apn="mmsSP" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" mvno_match_data="Call me" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="Call me MMS" apn="mmsSP" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" authtype="0" mvno_match_data="Call me" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="Call me MMS" apn="mmssp" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="80" type="mms" authtype="0" mvno_match_data="Call me" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="DLG MMS" apn="mmssp" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="80" type="mms" authtype="0" mvno_match_data="DLG" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="DLG Tele MMS" apn="mmsSP" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" mvno_match_data="DLG Tele" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="DLG Tele MMS" apn="mmsSP" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" authtype="0" mvno_match_data="DLG Tele" mvno_type="spn"></apn>
+      <apn mcc="238" mnc="20" carrier="Telia MMS" apn="www.mms.mtelia.dk" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" mvno_match_data="2382010x" mvno_type="imsi"></apn>
+      <apn mcc="238" mnc="20" carrier="Telia MMS" apn="www.mms.mtelia.dk" mmsc="http://mms.telia.dk" mmsproxy="193.209.134.131" mmsport="8080" type="mms" mvno_match_data="2382030x" mvno_type="imsi"></apn>
+      <apn mcc="238" mnc="77" carrier="Telenor MMS" apn="telenor" mmsc="http://mms.telenor.dk" mmsproxy="212.88.64.8" mmsport="8080" type="mms"></apn>
+      <apn mcc="240" mnc="01" carrier="Halebop MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms" mvno_match_data="240017xxxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="240" mnc="01" carrier="Telia MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms"></apn>
+      <apn mcc="240" mnc="1" carrier="TELIA S mms" apn="mms.telia.se" mmsc="http://mmss/" mmsproxy="193.209.134.132" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="240" mnc="1" carrier="Telia MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="240" mnc="02" carrier="3" apn="data.tre.se" mmsc="http://mms.tre.se" mmsproxy="mmsproxy.tre.se" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="240" mnc="2" carrier="3" apn="data.tre.se" mmsc="http://mms.tre.se" mmsproxy="mmsproxy.tre.se" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="240" mnc="2" carrier="3 SE" apn="data.tre.se" mmsc="http://mms.tre.se" mmsproxy="172.16.1.25" mmsport="8799" type="default,mms" authtype="0"></apn>
+      <apn mcc="240" mnc="04" carrier="3" apn="data.tre.se" mmsc="http://mms.tre.se" mmsproxy="mmsproxy.tre.se" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="240" mnc="04" carrier="Telenor SE" apn="services.telenor.se" mmsc="http://mms" mmsproxy="172.30.253.241" mmsport="8799" type="default,supl,mms" mvno_match_data="Telenor SE" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="4" carrier="3" apn="data.tre.se" mmsc="http://mms.tre.se" mmsproxy="mmsproxy.tre.se" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="240" mnc="05" carrier="Halebop MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms" mvno_match_data="Halebop" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="05" carrier="Tele2 MMS" apn="4g.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" mvno_match_data="Tele2" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="05" carrier="Tele2 MMS 3G" apn="internet.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" mvno_match_data="Tele2" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="05" carrier="Telia MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms" mvno_match_data="Telia" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="5" carrier="Halebop MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="80" type="mms" mvno_match_data="Halebop" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="5" carrier="Tele2 MMS 3G" apn="internet.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" mvno_match_data="Tele2" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="06" carrier="Telenor MMS" apn="services.telenor.se" mmsc="http://mms" mmsproxy="173.30.253.241" mmsport="8799" type="mms"></apn>
+      <apn mcc="240" mnc="07" carrier="Tele2" apn="internet.tele2.no" mmsc="http://mmsc.tele2.no" mmsproxy="193.12.40.14" mmsport="8080" type="default,supl,mms" protocol="IP"></apn>
+      <apn mcc="240" mnc="07" carrier="Tele2 MMS" apn="4g.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms"></apn>
+      <apn mcc="240" mnc="07" carrier="Tele2 MMS" apn="internet.tele2.no" mmsc="http://mmsc.tele2.no" mmsproxy="193.12.40.14" mmsport="8080" type="mms" mvno_match_data="2400768xxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="240" mnc="07" carrier="Tele2 MMS 3G" apn="internet.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms"></apn>
+      <apn mcc="240" mnc="7" carrier="Tele2 MMS" apn="4g.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="240" mnc="7" carrier="Tele2 MMS 3G" apn="internet.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="240" mnc="7" carrier="Tele2Comviq Internet" apn="4g.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="240" mnc="08" carrier="Telenor SE" apn="services.telenor.se" mmsc="http://mms" mmsproxy="172.30.253.241" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="240" mnc="8" carrier="Telenor MMS (240.08)" apn="services.telenor.se" mmsc="http://mms" mmsproxy="172.30.253.241" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="240" mnc="8" carrier="Telenor SE" apn="services.telenor.se" mmsc="http://mms" mmsproxy="172.30.253.241" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="240" mnc="09" carrier="Telenor MMS" apn="services.telenor.se" mmsc="http://mms" mmsproxy="173.30.253.241" mmsport="8799" type="mms"></apn>
+      <apn mcc="240" mnc="10" carrier="Spring MMS" apn="mms.springmobil.se" mmsc="http://mms.springmobil.se" mmsproxy="213.88.184.37" mmsport="8080" type="mms"></apn>
+      <apn mcc="240" mnc="017" carrier="Halebop MMS" apn="mms.telia.se" mmsc="http://mmss" mmsproxy="193.209.134.132" mmsport="9201" type="mms" user="mms" password="telia"></apn>
+      <apn mcc="240" mnc="24" carrier="Tele2 MMS" apn="4g.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" mvno_match_data="Tele2" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="24" carrier="Tele2 MMS 3G" apn="internet.tele2.se" mmsc="http://mmsc.tele2.se" mmsproxy="130.244.202.30" mmsport="8080" type="mms" mvno_match_data="Tele2" mvno_type="spn"></apn>
+      <apn mcc="240" mnc="24" carrier="Telenor SE" apn="services.telenor.se" mmsc="http://mms" mmsproxy="172.30.253.241" mmsport="8799" type="default,supl,mms" mvno_match_data="Telenor SE" mvno_type="spn"></apn>
+      <apn mcc="242" mnc="01" carrier="Telenor" apn="telenor" mmsc="http://mmsc" mmsproxy="10.10.10.11" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="242" mnc="01" carrier="Ventelo MMS" apn="mms.ventelo.no" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" type="mms" user="ventelo" password="1111" authtype="1" mvno_match_data="24201700xxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="242" mnc="1" carrier="N Telenor" apn="telenor" mmsc="http://mmsc/" mmsproxy="10.10.10.11" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="242" mnc="1" carrier="Telenor" apn="telenor" mmsc="http://mmsc" mmsproxy="10.10.10.11" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="242" mnc="02" carrier="Chess MMS" apn="netcom" mmsc="http://mm/" mmsproxy="212.169.66.4" mmsport="8080" type="mms" user="mms" password="netcom" authtype="1" mvno_match_data="2420256xxxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="242" mnc="02" carrier="NetCom" apn="netcom" mmsc="http://mm/" mmsproxy="212.169.66.4" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="242" mnc="2" carrier="N NetCom mms" apn="mms.netcom.no" mmsc="http://mms/" mmsproxy="193.209.134.133" mmsport="80" type="mms" user="mms" password="netcom" authtype="0"></apn>
+      <apn mcc="242" mnc="2" carrier="NetCom" apn="netcom" mmsc="http://mm/" mmsproxy="212.169.66.4" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="242" mnc="04" carrier="Tele2 Internet" apn="internet.tele2.no" mmsc="http://mmsc.tele2.no" mmsproxy="193.12.40.14" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="242" mnc="05" carrier="NwN MMS" apn="mms" mmsc="http://mms.nwn.no" mmsproxy="188.149.250.10" mmsport="80" type="mms"></apn>
+      <apn mcc="244" mnc="03" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dna.fi" mmsproxy="10.1.1.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="244" mnc="3" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dna.fi" mmsproxy="10.1.1.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="3" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="04" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms"></apn>
+      <apn mcc="244" mnc="4" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="3"></apn>
+      <apn mcc="244" mnc="4" carrier="DNA MMS 1" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="05" carrier="Elisa MMS" apn="mms" mmsc="http://mms.elisa.fi" mmsproxy="213.161.41.57" mmsport="80" type="mms"></apn>
+      <apn mcc="244" mnc="05" carrier="Saunalahti MMS" apn="mms.saunalahti.fi" mmsc="http://mms.saunalahti.fi:8002/" mmsproxy="62.142.4.197" mmsport="8080" type="mms" mvno_match_data="2440541" mvno_type="imsi"></apn>
+      <apn mcc="244" mnc="5" carrier="Elisa MMS" apn="mms" mmsc="http://mms.elisa.fi" mmsproxy="213.161.41.57" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="10" carrier="TDC MMS" apn="mms.song.fi" mmsc="http://mms.song.fi" mmsproxy="213.161.41.58" mmsport="80" type="mms"></apn>
+      <apn mcc="244" mnc="12" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dna.fi" mmsproxy="10.1.1.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="244" mnc="12" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dna.fi" mmsproxy="10.1.1.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="12" carrier="DNA MMS 2" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="12" carrier="DNA Pro MMS" apn="mms.dnapro.fi" mmsc="http://mmsc.dnapro.fi/" mmsproxy="10.1.1.21" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="244" mnc="12" carrier="TDC MMS Finland" apn="mms.tdc.fi" mmsc="http://mmsc.tdc.fi" mmsproxy="10.1.12.2" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="244" mnc="13" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms"></apn>
+      <apn mcc="244" mnc="13" carrier="DNA MMS" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="3"></apn>
+      <apn mcc="244" mnc="13" carrier="DNA MMS 3" apn="mms" mmsc="http://mmsc.dnafinland.fi/" mmsproxy="10.1.1.2" mmsport="8080" type="mms" user="dna" password="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="21" carrier="Saunalahti MMS" apn="mms.saunalahti.fi" mmsc="http://mms.saunalahti.fi:8002/" mmsproxy="62.142.4.197" mmsport="8080" type="mms"></apn>
+      <apn mcc="244" mnc="21" carrier="Saunalahti MMS" apn="mms.saunalahti.fi" mmsc="http://mms.saunalahti.fi:8002/" mmsproxy="62.142.4.197" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="91" carrier="SONERA MMS" apn="wap.sonera.net" mmsc="http://mms.sonera.fi:8002" mmsproxy="195.156.25.33" mmsport="80" type="mms"></apn>
+      <apn mcc="244" mnc="91" carrier="SONERA MMS" apn="wap.sonera.net" mmsc="http://mms.sonera.fi:8002" mmsproxy="195.156.25.33" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="244" mnc="91" carrier="TeliaSonera MMS" apn="wap.sonera.net" mmsc="http://mms.sonera.net:8002/" mmsproxy="195.156.25.33" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="246" mnc="01" carrier="Omnitel MMS" apn="gprs.mms.lt" mmsc="http://mms.omnitel.net:8002/" mmsproxy="194.176.32.149" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="246" mnc="1" carrier="OMNI MMS" apn="gprs.mms.lt" mmsc="http://mms.omnitel.net:8002/" mmsproxy="194.176.32.149" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="246" mnc="1" carrier="Omnitel MMS" apn="gprs.mms.lt" mmsc="http://mms.omnitel.net:8002/" mmsproxy="194.176.32.149" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="246" mnc="02" carrier="Bite MMS" apn="mms" mmsc="http://mmsc/servlets/mms" mmsproxy="192.168.150.2" mmsport="8080" type="mms" user="mms@mms" password="mms" authtype="1"></apn>
+      <apn mcc="246" mnc="2" carrier="Bite MMS" apn="mms" mmsc="http://mmsc" mmsproxy="192.168.150.2" mmsport="8080" type="mms" user="mms@mms" password="mms" authtype="0"></apn>
+      <apn mcc="246" mnc="2" carrier="Bite MMS" apn="mms" mmsc="http://mmsc/servlets/mms" mmsproxy="192.168.150.2" mmsport="8080" type="mms" user="mms@mms" password="mms" authtype="1"></apn>
+      <apn mcc="246" mnc="03" carrier="Tele2 Internet LT" apn="internet.tele2.lt" mmsc="http://mmsc.tele2.lt/" mmsproxy="193.12.40.29" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="246" mnc="3" carrier="MMS" apn="mms.tele2.lt" mmsc="http://mmsc.tele2.lt" mmsproxy="193.12.40.29" mmsport="8080" type="mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="246" mnc="3" carrier="Prepaid MMS" apn="mms.tele2.lt" mmsc="http://mmsc.tele2.lt" mmsproxy="193.12.40.29" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="246" mnc="3" carrier="Tele2 Internet LT" apn="internet.tele2.lt" mmsc="http://mmsc.tele2.lt/" mmsproxy="193.12.40.29" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="246" mnc="081" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="081" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="081" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="246" mnc="81" carrier="EHRPD - VZW Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="81" carrier="LTE - VZW Test CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="81" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="81" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="246" mnc="81" carrier="Test Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="247" mnc="01" carrier="LMT MMS" apn="internet.lmt.lv" mmsc="http://mmsc.lmt.lv/mmsc" type="mms"></apn>
+      <apn mcc="247" mnc="1" carrier="LMT MMS" apn="internet.lmt.lv" mmsc="http://mmsc.lmt.lv/mmsc" type="mms" authtype="0"></apn>
+      <apn mcc="247" mnc="1" carrier="LMT MMS" apn="mms.lmt.lv" mmsc="http://mmsc.lmt.lv/mmsc" mmsproxy="212.93.97.201" mmsport="8080" type="mms" user="lmt" password="lmt" authtype="0" port="8080"></apn>
+      <apn mcc="247" mnc="02" carrier="Tele2 LV MMS" apn="mms.tele2.lv" mmsc="http://mmsc.tele2.lv/" mmsproxy="193.12.40.38" mmsport="8080" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="247" mnc="2" carrier="MMS" apn="mms.tele2.lv" mmsc="http://mmsc.tele2.lv" mmsproxy="193.12.40.38" mmsport="8080" type="mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="247" mnc="2" carrier="Prepaid MMS" apn="mms.tele2.lv" mmsc="http://mmsc.tele2.lv" mmsproxy="193.12.40.38" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="247" mnc="05" carrier="Bite LV MMS" apn="mms" mmsc="http://mmsc/servlets/mms" mmsproxy="192.168.150.2" mmsport="8080" type="mms" user="mms@mms" password="mms" authtype="1"></apn>
+      <apn mcc="247" mnc="5" carrier="Bite MMS" apn="MMS" mmsc="http://mmsc" mmsproxy="192.168.150.2" mmsport="8080" type="mms" user="mms@mms" password="mms" authtype="0"></apn>
+      <apn mcc="248" mnc="01" carrier="EMT MMS" apn="mms.emt.ee" mmsc="http://mms.emt.ee/servlets/mms" mmsproxy="217.71.32.82" mmsport="8080" type="mms"></apn>
+      <apn mcc="248" mnc="01" carrier="Send" apn="send.ee" mmsc="http://mms.emt.ee/servlets/mms" mmsproxy="217.71.32.82" mmsport="8080" type="default,supl,mms" mvno_match_data="248010x2" mvno_type="imsi"></apn>
+      <apn mcc="248" mnc="01" carrier="Send" apn="send.ee" mmsc="http://mms.emt.ee/servlets/mms" mmsproxy="217.71.32.82" mmsport="8080" type="default,supl,mms" mvno_match_data="248010x3" mvno_type="imsi"></apn>
+      <apn mcc="248" mnc="1" carrier="EMT MMS" apn="mms.emt.ee" mmsc="http://mms.emt.ee/servlets/mms" mmsproxy="217.71.32.82" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="248" mnc="1" carrier="EMT MMS" apn="mms.emt.ee" mmsc="http://mms.emt.ee/servlets/mms" mmsproxy="217.71.32.82" mmsport="8080" type="mms" password="password" authtype="0"></apn>
+      <apn mcc="248" mnc="02" carrier="Elisa MMS" apn="mms" mmsc="http://194.204.2.10" mmsproxy="194.204.2.6" mmsport="8000" type="mms"></apn>
+      <apn mcc="248" mnc="2" carrier="Elisa MMS" apn="mms" mmsc="194.204.2.10" mmsproxy="194.204.2.6" mmsport="8000" type="mms" authtype="0"></apn>
+      <apn mcc="248" mnc="2" carrier="Elisa MMS" apn="mms" mmsc="http://194.204.2.10" mmsproxy="194.204.2.6" mmsport="8000" type="mms" authtype="0"></apn>
+      <apn mcc="248" mnc="03" carrier="Smart/Ultra MMS" apn="internet.tele2.ee" mmsc="http://mmsc.tele2.ee" mmsproxy="193.12.40.6" mmsport="8080" type="mms" mvno_match_data="24803000x" mvno_type="imsi"></apn>
+      <apn mcc="248" mnc="03" carrier="Smart/Ultra MMS" apn="internet.tele2.ee" mmsc="http://mmsc.tele2.ee" mmsproxy="193.12.40.6" mmsport="8080" type="mms" mvno_match_data="24803005x" mvno_type="imsi"></apn>
+      <apn mcc="248" mnc="03" carrier="Tele2 MMS" apn="mms.tele2.ee" mmsc="http://mmsc.tele2.ee" mmsproxy="193.12.40.6" mmsport="8080" type="mms"></apn>
+      <apn mcc="248" mnc="03" carrier="Tele2 MMS" apn="mms.tele2.ee" mmsc="http://mmsc.tele2.ee" mmsproxy="193.12.40.6" mmsport="8080" type="mms" mvno_match_data="24803005x" mvno_type="imsi"></apn>
+      <apn mcc="250" mnc="01" carrier="MTS MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms" user="mts" password="mts" authtype="1"></apn>
+      <apn mcc="250" mnc="01" carrier="МТS MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="1" carrier="MTS MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="9201" type="mms" user="mts" password="mts" authtype="0"></apn>
+      <apn mcc="250" mnc="002" carrier="Megafon MMS" apn="mms" mmsc="http://mmsc:8002" mmsproxy="10.10.10.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="250" mnc="02" carrier="Megafon MMS" apn="mms" mmsc="http://mmsc:8002" mmsproxy="10.10.10.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="250" mnc="2" carrier="MegaFon MMS" apn="mms" mmsc="http://mmsc:8002" mmsproxy="10.10.10.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="250" mnc="2" carrier="Megafon MMS" apn="mms" mmsc="http://mmsc:8002" mmsproxy="10.10.10.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="250" mnc="03" carrier="NCC" apn="mms" mmsc="http://10.0.3.50" mmsproxy="10.0.3.20" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="04" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="05" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="07" carrier="mms" apn="mms.smarts.ru" mmsc="http://172.24.120.135/mms/wapenc" mmsproxy="172.24.128.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="10" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="11" carrier="Beeline MMS" apn="mms.beeline.ru" mmsc="http://mms/" mmsproxy="192.168.094.023" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="12" carrier="BWC MMS" apn="mms.bwc.ru" mmsc="http://mmsc/mms" mmsproxy="10.10.17.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="13" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="16" carrier="MMS" apn="mms.ntc" mmsc="http://mmsc.vntc.ru/was" mmsproxy="80.243.64.68" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="17" carrier="MMS" apn="mms.usi.ru" mmsc="http://mms" mmsproxy="192.168.168.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="20" carrier="TELE2 MMS" apn="mms.tele2.ru" mmsc="http://mmsc.tele2.ru" mmsproxy="193.12.40.65" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="20" carrier="TELE2 MMS" apn="mms.tele2.ru" mmsc="http://mmsc.tele2.ru" mmsproxy="193.12.40.65" mmsport="9201" type="mms"></apn>
+      <apn mcc="250" mnc="39" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="44" carrier="Beeline MMS" apn="mms.beeline.ru" mmsc="http://mms/" mmsproxy="192.168.94.23" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="92" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="93" carrier="МТС Центр MMS" apn="mms.mts.ru" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="250" mnc="99" carrier="Beeline MMS" apn="mms.beeline.ru" mmsc="http://mms/" mmsproxy="192.168.94.23" mmsport="8080" type="mms" user="beeline" password="beeline" authtype="0"></apn>
+      <apn mcc="250" mnc="99" carrier="Beeline MMS" apn="mms.beeline.ru" mmsc="http://mms/" mmsproxy="192.168.94.23" mmsport="8080" type="mms" user="beeline" password="beeline" authtype="1"></apn>
+      <apn mcc="255" mnc="01" carrier="MTS MMS" apn="mms" mmsc="http://mmsc:8002/" mmsproxy="192.168.10.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="255" mnc="1" carrier="MTS MMS" apn="mms" mmsc="http://mmsc:8002/" mmsproxy="192.168.10.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="1" carrier="MTS UKR MMS" apn="mms" mmsc="http://mms/" mmsproxy="192.168.10.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="02" carrier="Beeline MMS" apn="mms.beeline.ua" mmsc="http://mms/" mmsproxy="172.29.18.192" mmsport="8080" type="mms"></apn>
+      <apn mcc="255" mnc="2" carrier="Beeline MMS" apn="mms.beeline.ua" mmsc="http://mms/" mmsproxy="172.29.18.192" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="2" carrier="Beeline UKR MMS" apn="mms.beeline.ua" mmsc="http://mms/" mmsproxy="172.29.18.192" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="03" carrier="Djuice MMS" apn="mms.djuice.com.ua" mmsc="http://mms.kyivstar.net" mmsproxy="10.10.10.10" mmsport="8080" type="mms" user="djuice" password="mms" authtype="1" mvno_match_data="DJUICE" mvno_type="spn"></apn>
+      <apn mcc="255" mnc="03" carrier="Kyivstar MMS" apn="mms.kyivstar.net" mmsc="http://mms.kyivstar.net" mmsproxy="10.10.10.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="255" mnc="3" carrier="UA-KYIVSTAR MMS" apn="mms.kyivstar.net" mmsc="http://mms.kyivstar.net" mmsproxy="10.10.10.10" mmsport="9201" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="06" carrier="Life:) MMS" apn="mms" mmsc="http://mms.life.com.ua/cmmsc/post" mmsproxy="212.58.162.230" mmsport="8080" type="mms"></apn>
+      <apn mcc="255" mnc="6" carrier="life:) MMS" apn="mms" mmsc="http://mms.life.com.ua/cmmsc/post" mmsproxy="212.58.162.230" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="255" mnc="07" carrier="Utel MMS" apn="3g.utel.ua" mmsc="http://10.212.1.4/mms/wapenc" mmsproxy="10.212.3.148" mmsport="8080" type="mms"></apn>
+      <apn mcc="257" mnc="01" carrier="Velcom MMS" apn="mms.velcom.by" mmsc="http://mmsc" mmsproxy="10.200.15.15" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="257" mnc="1" carrier="Velcom MMS" apn="mms.velcom.by" mmsc="http://mmsc" mmsproxy="10.200.15.15" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="257" mnc="02" carrier="MTS MMS" apn="mts" mmsc="http://mmsc" mmsproxy="192.168.192.192" mmsport="8080" type="mms" user="mts" password="mts" authtype="1"></apn>
+      <apn mcc="257" mnc="04" carrier="life:) MMS" apn="mms.life.com.by" mmsc="http://mms.life.com.by/mmsc/" mmsproxy="10.10.10.20" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="257" mnc="4" carrier="life:) MMS" apn="mms.life.com.by" mmsc="http://mms.life.com.by/mmsc/" mmsproxy="10.10.10.20" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="259" mnc="01" carrier="Orange MMS" apn="mms.orange.md" mmsc="http://mms/mms" mmsproxy="192.168.127.125" mmsport="3128" type="mms"></apn>
+      <apn mcc="259" mnc="01" carrier="Orange_MMS_GPRS" apn="mms.orange.md" mmsc="http://mms/mms" mmsproxy="192.168.127.125" mmsport="3128" type="mms"></apn>
+      <apn mcc="259" mnc="1" carrier="Orange_MMS_GPRS" apn="mms.orange.md" mmsc="http://mms/mms" mmsproxy="192.168.127.125" mmsport="3128" type="mms"></apn>
+      <apn mcc="259" mnc="02" carrier="Moldcell MMS" apn="mms" mmsc="http://mms.moldcell.md/cmmsc/post" mmsproxy="10.0.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="259" mnc="2" carrier="Moldcell MMS" apn="mms" mmsc="http://mms.moldcell.md/cmmsc/post" mmsproxy="10.0.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="259" mnc="05" carrier="Unite MMS" apn="mms.unite.md" mmsc="http://10.32.15.68:38090/was" mmsproxy="10.32.15.164" mmsport="8080" type="mms"></apn>
+      <apn mcc="260" mnc="01" carrier="Plus MMS" apn="mms" mmsc="http://mms.plusgsm.pl:8002" mmsproxy="212.2.96.16" mmsport="8080" type="mms"></apn>
+      <apn mcc="260" mnc="1" carrier="Plus mms" apn="mms" mmsc="http://mms.plusgsm.pl:8002" mmsproxy="212.2.96.16" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="260" mnc="02" carrier="T-mobile.pl" apn="mms" mmsc="http://mms/servlets/mms" mmsproxy="213.158.194.226" mmsport="8080" type="mms"></apn>
+      <apn mcc="260" mnc="02" carrier="heyahmms" apn="heyahmms" mmsc="http://mms.heyah.pl/servlets/mms" mmsproxy="213.158.194.226" mmsport="8080" type="mms"></apn>
+      <apn mcc="260" mnc="2" carrier="MMS" apn="mms" mmsc="http://mms/servlets/mms" mmsproxy="213.158.194.226" mmsport="8080" type="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="260" mnc="2" carrier="T-mobile.pl" apn="mms" mmsc="http://mms/servlets/mms" mmsproxy="213.158.194.226" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="260" mnc="2" carrier="heyahmms" apn="heyahmms" mmsc="http://mms.heyah.pl/servlets/mms" mmsproxy="213.158.194.226" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="260" mnc="03" carrier="Orange MMS" apn="mms" mmsc="http://mms.orange.pl" mmsproxy="192.168.6.104" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="260" mnc="3" carrier="Orange PL mms" apn="mms" mmsc="http://mms.orange.pl" mmsproxy="192.168.6.104" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="260" mnc="06" carrier="Play MMS" apn="mms" mmsc="http://10.10.28.164/mms/wapenc" mmsproxy="10.10.25.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="260" mnc="6" carrier="PLAY mms" apn="mms" mmsc="http://10.10.28.164/mms/wapenc" mmsproxy="10.10.25.5" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="260" mnc="6" carrier="Play MMS" apn="mms" mmsc="http://10.10.28.164/mms/wapenc" mmsproxy="10.10.25.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="262" mnc="01" carrier="T-Mobile D" apn="internet.t-mobile" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.028.023.131" mmsport="8008"></apn>
+      <apn mcc="262" mnc="01" carrier="Telekom Internet" apn="internet.telekom" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.28.23.131" mmsport="8008" user="telekom" password="telekom" authtype="1" mvno_match_data="debitel" mvno_type="spn" protocol="IP"></apn>
+      <apn mcc="262" mnc="01" carrier="Telekom Internet" apn="internet.telekom" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.28.23.131" mmsport="8008" type="default,supl,mms" user="telekom" password="telekom" authtype="1"></apn>
+      <apn mcc="262" mnc="1" carrier="T-Mobile Internet" apn="internet.t-mobile" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.28.23.131" mmsport="8008" type="default,mms" user="t-mobile" password="tm" authtype="1"></apn>
+      <apn mcc="262" mnc="1" carrier="Telekom Internet" apn="internet.telekom" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.28.23.131" mmsport="8008" type="default,mms" user="telekom" password="telekom" authtype="1" protocol="IP"></apn>
+      <apn mcc="262" mnc="1" carrier="Telekom Internet" apn="internet.telekom" mmsc="http://mms.t-mobile.de/servlets/mms" mmsproxy="172.28.23.131" mmsport="8008" type="default,supl,mms" user="telekom" password="telekom" authtype="1"></apn>
+      <apn mcc="262" mnc="02" carrier="Vodafone DE-MMS" apn="event.vodafone.de" mmsc="http://139.7.24.1/servlets/mms" mmsproxy="139.7.29.17" mmsport="80" type="mms"></apn>
+      <apn mcc="262" mnc="2" carrier="Vodafone DE-MMS" apn="event.vodafone.de" mmsc="http://139.7.24.1/servlets/mms" mmsproxy="139.7.29.17" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="262" mnc="2" carrier="Vodafone MMS (DE)" apn="event.vodafone.de" mmsc="http://139.7.24.1/servlets/mms" mmsproxy="139.7.29.17" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="262" mnc="03" carrier="E-Plus MMS" apn="mms.eplus.de" mmsc="http://mms/eplus/" mmsproxy="212.23.97.153" mmsport="5080" type="mms" user="mms" password="eplus" authtype="1"></apn>
+      <apn mcc="262" mnc="3" carrier="E-Plus MMS (DE)" apn="mms.eplus.de" mmsc="http://mms/eplus" mmsproxy="212.23.97.153" mmsport="5080" type="mms" user="mms" password="eplus" authtype="0"></apn>
+      <apn mcc="262" mnc="07" carrier="Alice" apn="internet.partner1" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.41" mmsport="8080" authtype="0" mvno_match_data="Alice" mvno_type="spn"></apn>
+      <apn mcc="262" mnc="07" carrier="Fonic" apn="pinternet.interkom.net" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.6" mmsport="8080" authtype="0" mvno_match_data="26207515" mvno_type="imsi"></apn>
+      <apn mcc="262" mnc="07" carrier="o2" apn="internet" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.5" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="262" mnc="07" carrier="o2 Internet" apn="internet" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.5" mmsport="8080" type="default,supl,mms" mvno_match_data="2620739" mvno_type="imsi"></apn>
+      <apn mcc="262" mnc="07" carrier="o2 Internet Prepaid" apn="pinternet.interkom.de" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.6" mmsport="8080" type="default,supl,mms" proxy="82.113.100.6" port="8080"></apn>
+      <apn mcc="262" mnc="07" carrier="o2 Internet Prepaid" apn="pinternet.interkom.de" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.6" mmsport="8080" type="default,supl,mms" mvno_match_data="2620749" mvno_type="imsi"></apn>
+      <apn mcc="262" mnc="7" carrier="o2" apn="internet" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.5" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="262" mnc="7" carrier="o2 (DE)" apn="internet" mmsc="http://10.81.0.7:8002/" mmsproxy="82.113.100.5" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="262" mnc="7" carrier="o2 Internet Prepaid" apn="pinternet.interkom.de" mmsc="http://10.81.0.7:8002" mmsproxy="82.113.100.6" mmsport="8080" type="default,supl,mms" authtype="0" proxy="82.113.100.6" port="8080"></apn>
+      <apn mcc="268" mnc="01" carrier="Vodafone Net2" apn="net2.vodafone.pt" mmsc="http://mms.vodafone.pt/servlets/mms" mmsproxy="iproxy.vodafone.pt" mmsport="80" type="default,supl,mms" user="vodafone" password="vodafone" authtype="1" proxy="iproxy.vodafone.pt" port="80"></apn>
+      <apn mcc="268" mnc="01" carrier="ZON MMS" apn="vas.zon.pt" mmsc="http://mms/servlets/mms" mmsproxy="213.30.27.63" mmsport="8799" type="mms" user="vas" password="vas" authtype="1" mvno_match_data="ZON" mvno_type="spn"></apn>
+      <apn mcc="268" mnc="1" carrier="Vodafone Net2" apn="net2.vodafone.pt" mmsc="http://mms.vodafone.pt/servlets/mms" mmsproxy="iproxy.vodafone.pt" mmsport="80" type="default,mms,supl,agps,fota" user="vodafone" password="vodafone" authtype="0" proxy="iproxy.vodafone.pt" port="80"></apn>
+      <apn mcc="268" mnc="1" carrier="Vodafone Net2" apn="net2.vodafone.pt" mmsc="http://mms.vodafone.pt/servlets/mms" mmsproxy="iproxy.vodafone.pt" mmsport="80" type="default,supl,mms" user="vodafone" password="vodafone" authtype="1" proxy="iproxy.vodafone.pt" port="80"></apn>
+      <apn mcc="268" mnc="03" carrier="PortalOptimus" apn="umts" mmsc="http://mmsc:10021/mmsc" mmsproxy="62.169.66.5" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="268" mnc="3" carrier="P OPTIMUS" apn="umts" mmsc="http://mmsc:10021/mmsc" mmsproxy="62.169.66.5" mmsport="8799" type="default,mms" authtype="0"></apn>
+      <apn mcc="268" mnc="3" carrier="PortalOptimus" apn="umts" mmsc="http://mmsc:10021/mmsc" mmsproxy="62.169.66.5" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="268" mnc="06" carrier="mms tmn" apn="mmsc.tmn.pt" mmsc="http://mmsc/" mmsproxy="10.111.2.16" mmsport="8080" type="mms" user="tmn" password="tmnnet" authtype="1"></apn>
+      <apn mcc="268" mnc="6" carrier="P TMN mms" apn="mmsc.tmn.pt" mmsc="http://mmsc" mmsproxy="10.111.2.16" mmsport="8080" type="mms" user="tmn" password="tmnnet" authtype="0"></apn>
+      <apn mcc="268" mnc="6" carrier="mms tmn" apn="mmsc.tmn.pt" mmsc="http://mmsc/" mmsproxy="10.111.2.16" mmsport="8080" type="mms" user="tmn" password="tmnnet" authtype="1"></apn>
+      <apn mcc="270" mnc="01" carrier="LUXGSM MMS" apn="mms.pt.lu" mmsc="http://mmsc.pt.lu" mmsproxy="194.154.192.88" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="270" mnc="1" carrier="LUXGSM MMS" apn="mms.pt.lu" mmsc="http://mmsc.pt.lu" mmsproxy="194.154.192.88" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="270" mnc="1" carrier="LUXGSM mms" apn="mms.pt.lu" mmsc="http://mmsc.pt.lu" mmsproxy="194.154.192.88" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="270" mnc="77" carrier="TANGO mms" apn="mms" mmsc="http://mms.tango.lu" mmsproxy="212.66.75.3" mmsport="8080" type="mms" user="tango" password="tango" authtype="1"></apn>
+      <apn mcc="270" mnc="77" carrier="Tango MMS" apn="mms" mmsc="http://mms.tango.lu" mmsproxy="212.66.75.3" mmsport="8080" type="mms" user="tango" password="tango"></apn>
+      <apn mcc="270" mnc="77" carrier="Tango MMS" apn="mms" mmsc="http://mms.tango.lu" mmsproxy="212.66.75.3" mmsport="8080" type="mms" user="tango" password="tango" authtype="3"></apn>
+      <apn mcc="270" mnc="99" carrier="Orange" apn="orange.lu" mmsc="http://mms.orange.lu" mmsproxy="212.88.139.44" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="270" mnc="99" carrier="Vox Mobile" apn="vox.lu" mmsc="http://mms.vox.lu" mmsproxy="212.88.139.44" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="270" mnc="99" carrier="Vox Mobile" apn="vox.lu" mmsc="http://mms.vox.lu" mmsproxy="212.88.139.44" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="272" mnc="01" carrier="Vodafone IE-MMS" apn="mms.vodafone.net" mmsc="http://www.vodafone.ie/mms" mmsproxy="10.24.59.200" mmsport="80" type="mms"></apn>
+      <apn mcc="272" mnc="1" carrier="Vodafone IE-MMS" apn="mms.vodafone.net" mmsc="http://www.vodafone.ie/mms" mmsproxy="10.24.59.200" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="272" mnc="1" carrier="Vodafone MMS" apn="mms.vodafone.net" mmsc="http://www.vodafone.ie/mms" mmsproxy="10.24.59.200" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="272" mnc="02" carrier="O2 Ireland" apn="internet" mmsc="http://mmsc.mms.o2.ie:8002" mmsproxy="62.40.32.40" mmsport="8080" type="default,supl,mms" proxy="62.40.32.40" port="8080"></apn>
+      <apn mcc="272" mnc="2" carrier="O2 Ireland" apn="internet" mmsc="http://mmsc.mms.o2.ie:8002" mmsproxy="62.40.32.40" mmsport="8080" type="default,supl,mms" authtype="0" proxy="62.40.32.40" port="8080"></apn>
+      <apn mcc="272" mnc="2" carrier="O2.ie Mobile Internet" apn="internet" mmsc="http://mmsc.mms.o2.ie:8002" mmsproxy="62.40.32.40" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="272" mnc="03" carrier="Meteor MMS" apn="mms.mymeteor.ie" mmsc="http://mms.mymeteor.ie" mmsproxy="10.85.85.85" mmsport="8799" type="mms" user="my" password="wap" authtype="1"></apn>
+      <apn mcc="272" mnc="3" carrier="Meteor MMS" apn="mms.mymeteor.ie" mmsc="http://mms.mymeteor.ie" mmsproxy="10.85.85.85" mmsport="8799" type="mms" user="my" password="mms" authtype="0"></apn>
+      <apn mcc="272" mnc="3" carrier="Meteor MMS" apn="mms.mymeteor.ie" mmsc="http://mms.mymeteor.ie" mmsproxy="10.85.85.85" mmsport="8799" type="mms" user="my" password="wap" authtype="1"></apn>
+      <apn mcc="272" mnc="05" carrier="3" apn="3ireland.ie" mmsc="http://mms.um.3ireland.ie:10021/mmsc" mmsproxy="mms.3ireland.ie" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="272" mnc="5" carrier="3" apn="3ireland.ie" mmsc="http://mms.um.3ireland.ie:10021/mmsc" mmsproxy="mms.3ireland.ie" mmsport="8799" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="272" mnc="5" carrier="3 Ireland" apn="3ireland.ie" mmsc="http://mms.um.3ireland.ie:10021/mmsc/" mmsproxy="mms.3ireland.ie" mmsport="8799" type="default,supl,agps,fota,dun,mms" authtype="0"></apn>
+      <apn mcc="272" mnc="11" carrier="Tesco" apn="tescomobile.liffeytelecom.com" mmsc="http://mmc1/servlets/mms" mmsproxy="10.1.11.19" mmsport="8080" type="default,supl,mms" mvno_match_data="0A" mvno_type="gid"></apn>
+      <apn mcc="274" mnc="01" carrier="Siminn MMS" apn="mms.simi.is" mmsc="http://mms.simi.is/servlets/mms" mmsproxy="213.167.138.200" mmsport="8080" type="mms"></apn>
+      <apn mcc="274" mnc="1" carrier="Siminn MMS" apn="mms.simi.is" mmsc="http://mms.simi.is/servlets/mms" mmsproxy="213.167.138.200" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="274" mnc="02" carrier="Vodafone MMS" apn="mms.gprs.is" mmsc="http://mmsc.vodafone.is" mmsproxy="10.22.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="274" mnc="2" carrier="Vodafone MMS" apn="mms.gprs.is" mmsc="http://mmsc.vodafone.is" mmsproxy="10.22.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="274" mnc="03" carrier="Vodafone MMS" apn="mms.gprs.is" mmsc="http://mmsc.vodafone.is" mmsproxy="10.22.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="274" mnc="3" carrier="Vodafone MMS" apn="mms.gprs.is" mmsc="http://mmsc.vodafone.is" mmsproxy="10.22.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="274" mnc="11" carrier="MMS Nova" apn="mms.nova.is" mmsc="http://mmsc.nova.is" mmsproxy="10.10.2.60" mmsport="8080" type="mms"></apn>
+      <apn mcc="274" mnc="11" carrier="MMS Nova" apn="mms.nova.is" mmsc="http://mmsc.nova.is" mmsproxy="10.10.2.60" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="274" mnc="11" carrier="Nova MMS" apn="mms.nova.is" mmsc="http://mmsc.nova.is" mmsproxy="10.10.2.60" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="278" mnc="01" carrier="Vodafone MT-MMS" apn="mms.vodafone.com.mt" mmsc="http://mms.vodafone.com.mt/servlets/mms" mmsproxy="10.12.0.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="278" mnc="1" carrier="Vodafone MMS (MT)" apn="mms.vodafone.com.mt" mmsc="http://mms.vodafone.com.mt/servlets/mms" mmsproxy="10.12.0.3" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="278" mnc="1" carrier="Vodafone MT-MMS" apn="mms.vodafone.com.mt" mmsc="http://mms.vodafone.com.mt/servlets/mms" mmsproxy="10.12.0.3" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="280" mnc="01" carrier="CYTA" apn="cytamobile" mmsc="http://mmsc.cyta.com.cy" mmsproxy="212.31.96.161" mmsport="8080" type="default,supl,mms" user="user" password="pass"></apn>
+      <apn mcc="280" mnc="1" carrier="CYTA" apn="cytamobile" mmsc="http://mmsc.cyta.com.cy" mmsproxy="212.31.96.161" mmsport="8080" type="default,supl,mms" user="user" password="pass"></apn>
+      <apn mcc="280" mnc="10" carrier="MTN MMS" apn="mms" mmsc="http://mms.mtn.com.cy/mmsc" mmsproxy="172.24.97.1" mmsport="3130" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="283" mnc="10" carrier="Orange Armenia MMS" apn="mms" mmsc="http://mms/" mmsproxy="192.168.220.251" mmsport="3128" type="mms" authtype="1"></apn>
+      <apn mcc="284" mnc="01" carrier="MTel MMS" apn="mms-gprs.mtel.bg" mmsc="http://mmsc/" mmsproxy="10.150.0.33" mmsport="8080" type="mms" user="mtel" password="mtel" authtype="1"></apn>
+      <apn mcc="284" mnc="1" carrier="M-Tel BG MMS" apn="mms-gprs.mtel.bg" mmsc="http://mmsc/" mmsproxy="10.150.0.33" mmsport="8080" type="mms" user="mtel" password="mtel" authtype="0"></apn>
+      <apn mcc="284" mnc="03" carrier="Vivacom MMS" apn="mms.vivacom.bg" mmsc="http://mmsc.vivacom.bg" mmsproxy="192.168.123.123" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="284" mnc="3" carrier="VIVACOM MMS" apn="mms.vivacom.bg" mmsc="http://mmsc.vivacom.bg" mmsproxy="192.168.123.123" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="284" mnc="3" carrier="Vivacom MMS" apn="mms.vivacom.bg" mmsc="http://mmsc.vivacom.bg" mmsproxy="192.168.123.123" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="284" mnc="05" carrier="GLOBUL MMS GPRS" apn="mms.globul.bg" mmsc="http://mmsc1.mms.globul.bg:8002" mmsproxy="192.168.87.11" mmsport="8004" type="mms" user="mms"></apn>
+      <apn mcc="284" mnc="5" carrier="GLOBUL MMS GPRS" apn="mms.globul.bg" mmsc="http://mmsc1.mms.globul.bg:8002" mmsproxy="192.168.87.11" mmsport="8004" type="mms" user="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="284" mnc="5" carrier="GLOBUL MMS GPRS" apn="mms.globul.bg" mmsc="http://mmsc1.mms.globul.bg:8002" mmsproxy="192.168.87.11" mmsport="8004" type="mms" user="mms" authtype="3"></apn>
+      <apn mcc="286" mnc="01" carrier="TURKCELL MMS" apn="mms" mmsc="http://mms.turkcell.com.tr/servlets/mms" mmsproxy="212.252.169.217" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="286" mnc="1" carrier="TR TURKCELL mms" apn="mms" mmsc="http://mms.turkcell.com.tr/servlets/mms" mmsproxy="212.252.169.217" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="286" mnc="1" carrier="TURKCELL MMS" apn="mms" mmsc="http://mms.turkcell.com.tr/servlets/mms" mmsproxy="212.252.169.217" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="286" mnc="02" carrier="Vodafone MMS" apn="mms" mmsc="http://217.31.233.18:6001/MM1Servlet" mmsproxy="217.31.233.18" mmsport="9401" type="mms" user="vodafone" password="vodafone" authtype="1"></apn>
+      <apn mcc="286" mnc="2" carrier="VODAFONE TR mms" apn="mms" mmsc="http://217.31.233.18:6001/MM1Servlet" mmsproxy="217.31.233.18" mmsport="9401" type="mms" user="vodafone" password="vodafone" authtype="0"></apn>
+      <apn mcc="286" mnc="2" carrier="Vodafone MMS" apn="mms" mmsc="http://217.31.233.18:6001/MM1Servlet" mmsproxy="217.31.233.18" mmsport="9401" type="mms" user="vodafone" password="vodafone" authtype="1"></apn>
+      <apn mcc="286" mnc="03" carrier="AVEA MMS" apn="mms" mmsc="http://mms.avea.com.tr/servlets/mms" mmsproxy="213.161.151.201" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="286" mnc="3" carrier="AVEA MMS" apn="mms" mmsc="http://mms.avea.com.tr/servlets/mms" mmsproxy="213.161.151.201" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="286" mnc="3" carrier="AVEA-MMS" apn="mms" mmsc="http://mms.avea.com.tr/servlets/mms" mmsproxy="213.161.151.201" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="290" mnc="01" carrier="Tele MMS" apn="mms" mmsc="http://mms.tele.gl/mms/wapenc" mmsproxy="10.112.222.37" mmsport="8080" type="mms"></apn>
+      <apn mcc="293" mnc="40" carrier="Si.mobil MMS" apn="mms.simobil.si" mmsc="http://mmc/" mmsproxy="80.95.224.46" mmsport="9201" type="mms" user="simobil" password="internet" authtype="1"></apn>
+      <apn mcc="293" mnc="40" carrier="Si.mobil mms" apn="mms.simobil.si" mmsc="http://mmc/" mmsproxy="80.95.224.46" mmsport="9090" type="mms" user="simobil" password="internet" authtype="0"></apn>
+      <apn mcc="293" mnc="41" carrier="MOBITEL" apn="internet" mmsc="http://mms.mobitel.si/servlets/mms" mmsproxy="213.229.249.40" mmsport="8080" type="default,mms" user="mobitel" password="internet" authtype="0" proxy="213.229.249.40" port="8080"></apn>
+      <apn mcc="293" mnc="41" carrier="Mobilni Internet" apn="internet" mmsc="http://mms.mobitel.si/servlets/mms" mmsproxy="213.229.249.40" mmsport="8080" type="default,supl,mms" user="mobitel" password="internet" authtype="1"></apn>
+      <apn mcc="293" mnc="64" carrier="T2" apn="internet.t-2.net" mmsc="http://www.mms.t-2.net:8002" mmsproxy="172.20.18.137" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="293" mnc="70" carrier="SI TUSMOBIL mms" apn="mms.tusmobil.si" mmsc="http://mms.tusmobil.si:8002" mmsproxy="91.185.221.85" mmsport="8080" type="mms" user="tusmobil" password="mms" authtype="0"></apn>
+      <apn mcc="293" mnc="70" carrier="Telemach Internet" apn="telemach.net" mmsc="http://mms.telemach.net:8002" mmsproxy="91.185.221.85" mmsport="8080" type="default,supl,mms" mvno_match_data="29370029xxxxxxx" mvno_type="imsi"></apn>
+      <apn mcc="293" mnc="70" carrier="Tusmobil MMS" apn="mms.tusmobil.si" mmsc="http://mms.tusmobil.si:8002" mmsproxy="91.185.221.85" mmsport="8080" type="mms" user="tusmobil" password="mms" authtype="1"></apn>
+      <apn mcc="294" mnc="01" carrier="T-Mobile MK MMS" apn="mms" mmsc="http://mms.t-mobile.com.mk" mmsproxy="62.162.155.227" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="294" mnc="1" carrier="T-Mobile MK MMS" apn="mms" mmsc="http://mms.t-mobile.com.mk" mmsproxy="62.162.155.227" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="294" mnc="1" carrier="TM MK MMS" apn="mms" mmsc="http://mms.t-mobile.com.mk" mmsproxy="62.162.155.227" mmsport="8080" type="mms" user="mms" password="mms" authtype="1" protocol="IP"></apn>
+      <apn mcc="294" mnc="02" carrier="Cosmofon MMS" apn="mms" mmsc="http://195.167.65.220:8002" mmsproxy="10.10.10.20" mmsport="8080" type="mms"></apn>
+      <apn mcc="294" mnc="2" carrier="Cosmofon MMS" apn="mms" mmsc="http://195.167.65.220:8002" mmsproxy="10.10.10.20" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="294" mnc="2" carrier="ONE MK MMS" apn="mms" mmsc="http://195.167.65.220:8002" mmsproxy="10.10.10.20" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="294" mnc="03" carrier="MMS" apn="vipoperator.mms" mmsc="http://mmsc.vipoperator.com.mk" mmsproxy="78.40.0.1" mmsport="8080" type="mms" user="vipoperator" password="vipoperator"></apn>
+      <apn mcc="294" mnc="3" carrier="MMS" apn="vipoperator.mms" mmsc="http://mmsc.vipoperator.com.mk" mmsproxy="78.40.0.1" mmsport="8080" type="mms" user="vipoperator" password="vipoperator" authtype="3"></apn>
+      <apn mcc="294" mnc="3" carrier="VIP MK MMS" apn="vipoperator" mmsc="http://mmsc.vipoperator.com.mk" mmsproxy="78.40.0.1" mmsport="8080" type="mms" user="vipoperator" authtype="0"></apn>
+      <apn mcc="297" mnc="02" carrier="T-Mobile MMS" apn="mms" mmsc="http://192.168.180.100/servlets/mms" mmsproxy="10.0.5.19" mmsport="8080" type="mms" user="38267" password="38267"></apn>
+      <apn mcc="297" mnc="2" carrier="T-Mobile MMS" apn="mms" mmsc="http://192.168.180.100/servlets/mms" mmsproxy="10.0.5.19" mmsport="8080" type="mms" user="38267" password="38267" authtype="3"></apn>
+      <apn mcc="297" mnc="2" carrier="Telekom MMS" apn="mms" mmsc="http://192.168.180.100/servlets/mms" mmsproxy="10.0.5.19" mmsport="8080" type="mms" user="38267" password="38267" authtype="1" protocol="IP"></apn>
+      <apn mcc="302" mnc="220" carrier="Koodo" apn="sp.koodo.com" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl,dun" mvno_match_data="4B" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="Koodo" apn="sp.koodo.com" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl,dun" authtype="0" mvno_match_data="4B" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="Koodo SP" apn="sp.koodo.com" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,agps,supl,fota,hipri,dun" authtype="0" mvno_match_data="4B4F" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="Mobile Internet" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,agps,supl,fota,hipri" mvno_match_data="4D4F" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="Mobile Internet" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,agps,supl,fota,hipri" authtype="0" mvno_match_data="5043" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="Mobile Internet" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="50" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="PC mobile" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="50" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="PC mobile" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" authtype="0" mvno_match_data="50" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="TELUS" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="54" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="TELUS" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" authtype="0" mvno_match_data="54" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="220" carrier="TELUS SP" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,agps,supl,fota,hipri" authtype="0" mvno_match_data="5455" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="221" carrier="Koodo" apn="sp.koodo.com" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="4B" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="221" carrier="Koodo" apn="sp.koodo.com" mmsc="http://aliasredirect.net/proxy/koodo/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl,dun" mvno_match_data="4B" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="221" carrier="PC mobile" apn="sp.mb.com" mmsc="http://aliasredirect.net/proxy/mb/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="50" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="221" carrier="TELUS" apn="sp.telus.com" mmsc="http://aliasredirect.net/proxy/mmsc" mmsproxy="74.49.0.18" mmsport="80" type="default,mms,supl" mvno_match_data="54" mvno_type="gid"></apn>
+      <apn mcc="302" mnc="270" carrier="Eastlink MMS" apn="mms.mobi.eastlink.ca" mmsc="http://mmss.mobi.eastlink.ca" mmsproxy="10.232.12.49" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="270" carrier="MMS" apn="mms.mobi.eastlink.ca" mmsc="http://mmss.mobi.eastlink.ca" mmsproxy="10.232.12.49" mmsport="8080" type="mms"></apn>
+      <apn mcc="302" mnc="270" carrier="MMS" apn="mms.mobi.eastlink.ca" mmsc="http://mmss.mobi.eastlink.ca" mmsproxy="10.232.12.49" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="320" carrier="MOMMS" apn="mms.davewireless.com" mmsc="http://mms.mobilicity.net" mmsproxy="10.100.3.4" mmsport="8080" type="mms"></apn>
+      <apn mcc="302" mnc="320" carrier="MOMMS" apn="mms.davewireless.com" mmsc="http://mms.mobilicity.net" mmsproxy="10.100.3.4" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="320" carrier="Mobilicity MMS" apn="mms.davewireless.com" mmsc="http://mms.mobilicity.net" mmsproxy="10.100.3.4" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="370" carrier="Fido Internet" apn="ltemobile.apn" mmsc="http://mms.fido.ca" mmsproxy="mmsproxy.fido.ca" mmsport="80" type="default,mms,agps,supl,fota,hipri" mvno_match_data="DD" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IP"></apn>
+      <apn mcc="302" mnc="370" carrier="Fido LTE" apn="ltemobile.apn" mmsc="http://mms.fido.ca" mmsproxy="mmsproxy.fido.ca" mmsport="80" type="default,mms,supl" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="370" carrier="MTS" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,supl" mvno_match_data="2C" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="370" carrier="MTS" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,supl" authtype="0" mvno_match_data="2C" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="370" carrier="MTS Internet S" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,agps,supl,fota,hipri" authtype="0" mvno_match_data="MTS" mvno_type="spn" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="490" carrier="MMS" apn="mms.windmobile.ca" mmsc="http://mms.windmobile.ca" mmsproxy="74.115.197.70" mmsport="8080" type="mms"></apn>
+      <apn mcc="302" mnc="490" carrier="MMS" apn="mms.windmobile.ca" mmsc="http://mms.windmobile.ca" mmsproxy="74.115.197.70" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="490" carrier="WIND MMS" apn="mms.windmobile.ca" mmsc="http://mms.windmobile.ca" mmsproxy="74.115.197.70" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="302" mnc="500" carrier="Media" apn="media.ng" mmsc="http://media.videotron.com" type="default,supl,mms"></apn>
+      <apn mcc="302" mnc="500" carrier="Videotron" apn="media.videotron" mmsc="http://media.videotron.com" type="default,mms,dun,agps,supl,fota,hipri" authtype="0"></apn>
+      <apn mcc="302" mnc="500" carrier="Videotron" apn="media.videotron" mmsc="http://media.videotron.com" type="default,supl,mms"></apn>
+      <apn mcc="302" mnc="500" carrier="Videotron" apn="media.videotron" mmsc="http://media.videotron.com" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="302" mnc="510" carrier="Media" apn="media.ng" mmsc="http://media.videotron.com" type="default,supl,mms"></apn>
+      <apn mcc="302" mnc="510" carrier="Videotron" apn="media.videotron" mmsc="http://media.videotron.com" type="default,supl,mms"></apn>
+      <apn mcc="302" mnc="520" carrier="Media" apn="media.ng" mmsc="http://media.videotron.com" type="default,supl,mms"></apn>
+      <apn mcc="302" mnc="610" carrier="Bell Mobility" apn="pda.bell.ca" mmsc="http://mms.bell.ca/mms/wapenc" type="default,mms,dun,supl"></apn>
+      <apn mcc="302" mnc="610" carrier="Bell Mobility" apn="pda.bell.ca" mmsc="http://mms.bell.ca/mms/wapenc" type="default,mms,dun,supl" authtype="0"></apn>
+      <apn mcc="302" mnc="610" carrier="Bell Mobility" apn="pda.bell.ca" mmsc="http://mms.bell.ca/mms/wapenc" type="default,mms,supl"></apn>
+      <apn mcc="302" mnc="610" carrier="Bell-Internet" apn="pda.bell.ca" mmsc="http://mms.bell.ca/mms/wapenc" mmsproxy="web.wireless.bell.ca" mmsport="80" type="default,mms" authtype="0"></apn>
+      <apn mcc="302" mnc="660" carrier="MTS" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,supl" mvno_match_data="2C" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="660" carrier="MTS" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,supl" authtype="0" mvno_match_data="2C" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="660" carrier="MTS Internet" apn="sp.mts" mmsc="http://mmsc2.mts.net/" mmsproxy="wapgw1.mts.net" mmsport="9201" type="default,mms,agps,supl,fota,hipri" authtype="0" mvno_match_data="MTS" mvno_type="spn" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="720" carrier="Chatr Internet" apn="chatrweb.apn" mmsc="http://mms.chatrwireless.com" mmsproxy="205.151.11.11" mmsport="80" type="default,mms,agps,supl,fota,hipri" authtype="0" mvno_match_data="chatr" mvno_type="spn" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="720" carrier="Cityfone Internet" apn="ltemobile.apn" mmsc="http://mms.gprs.rogers.com" mmsproxy="mmsproxy.rogers.com" mmsport="80" type="default,mms,agps,supl,fota,hipri" mvno_match_data="CITYFONE" mvno_type="spn" protocol="IPV4V6" roaming_protocol="IP"></apn>
+      <apn mcc="302" mnc="720" carrier="Rogers Internet" apn="ltemobile.apn" mmsc="http://mms.gprs.rogers.com" mmsproxy="mmsproxy.rogers.com" mmsport="80" type="default,mms,agps,supl,fota,hipri" mvno_match_data="ROGERS" mvno_type="spn" protocol="IPV4V6" roaming_protocol="IP"></apn>
+      <apn mcc="302" mnc="720" carrier="Rogers LTE" apn="ltemobile.apn" mmsc="http://mms.gprs.rogers.com" mmsproxy="mmsproxy.rogers.com" mmsport="80" type="default,mms,supl" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="302" mnc="720" carrier="Tbaytel Internet" apn="ltemobile.apn" mmsc="http://mms.gprs.rogers.com" mmsproxy="mmsproxy.rogers.com" mmsport="80" type="default,mms,agps,supl,fota,hipri" mvno_match_data="BA" mvno_type="gid" protocol="IPV4V6" roaming_protocol="IP"></apn>
+      <apn mcc="302" mnc="720" carrier="chatr" apn="chatrweb.apn" mmsc="http://mms.chatrwireless.com" mmsproxy="205.151.11.11" mmsport="80" type="default,mms,supl" mvno_match_data="302720x94" mvno_type="imsi" protocol="IPV4V6" roaming_protocol="IPV4V6" proxy="205.151.11.11" port="80"></apn>
+      <apn mcc="302" mnc="720" carrier="chatr" apn="chatrweb.apn" mmsc="http://mms.chatrwireless.com" mmsproxy="205.151.11.11" mmsport="80" type="default,mms,supl" authtype="0" mvno_match_data="302720x94" mvno_type="imsi" protocol="IPV4V6" roaming_protocol="IPV4V6" proxy="205.151.11.11" port="80"></apn>
+      <apn mcc="302" mnc="780" carrier="SaskTel" apn="pda.stm.sk.ca" mmsc="http://mms.sasktel.com/" mmsproxy="mig.sasktel.com" mmsport="80" type="default,mms,supl"></apn>
+      <apn mcc="302" mnc="780" carrier="SaskTel" apn="pda.stm.sk.ca" mmsc="http://mms.sasktel.com/" mmsproxy="mig.sasktel.com" mmsport="80" type="default,mms,supl,dun"></apn>
+      <apn mcc="310" mnc="0" carrier="MetroPCS" apn="internet" mmsc="http://mms.metropcs.net:3128/mmsc" user="*" password="*" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="1" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="10" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="11" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="15" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="16" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="2" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="3" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="9" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint" apn="mms_over_wifi" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="wifi" user="*" password="*" server="*"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="310" mnc="0" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="000" carrier="Verizon CDMA HRPD" mmsc="http://mms.vzwreseller.com/servlets/mms" type="default,mms,hipri,dun,supl" authtype="3" mvno_match_data="Tracfone" mvno_type="spn"></apn>
+      <apn mcc="310" mnc="000" carrier="Bluewire" apn="CdmaNai" mmsc="http://mms.blueunlimited.com" mmsport="8514" type="mms" mvno_match_data="bluewire" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="Bluewire" apn="VZWINTERNET" mmsc="http://mms.blueunlimited.com" mmsport="8514" type="default,mms,dun,supl" mvno_match_data="bluewire" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Bluewire" apn="VZWINTERNET" mmsc="http://mms.blueunlimited.com" mmsport="8514" type="default,mms,dun,supl" mvno_match_data="bluewire" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Commnet" apn="CdmaNai" mmsc="http://mmsc.cccomm.csky.us" mmsport="6672" type="mms" mvno_match_data="commnet" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="Distribution" apn="VZWINTERNET" mmsc="http://mms.dst.com/mms/" type="default,mms,dun,supl" mvno_match_data="distribution" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Distribution" apn="VZWINTERNET" mmsc="http://mms.dst.com/mms/" type="default,mms,dun,supl" mvno_match_data="distribution" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Flatwire" apn="VZWINTERNET" mmsc="http://mmsc.cleartalk.csky.us/" type="default,mms,dun,supl" mvno_match_data="flatwire" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Flatwire" apn="VZWINTERNET" mmsc="http://mmsc.cleartalk.csky.us/" type="default,mms,dun,supl" mvno_match_data="flatwire" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Internet" apn="n.ispsn" mmsc="http://mms.plspictures.com" mmsproxy="68.28.31.7" mmsport="80" type="default" protocol="IPV4V6" bearer="0"></apn>
+      <apn mcc="310" mnc="000" carrier="Mobilenation" apn="VZWINTERNET" mmsc="http://mms.mymn3g.net" mmsproxy="mms.mymn3g.net" mmsport="8081" type="default,mms,dun,supl" mvno_match_data="mobilenation" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Mobilenation" apn="VZWINTERNET" mmsc="http://mms.mymn3g.net" mmsproxy="mms.mymn3g.net" mmsport="8081" type="default,mms,dun,supl" mvno_match_data="mobilenation" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Mobipcs" apn="VZWINTERNET" mmsc="http://mms.mobipcs.com" type="default,mms,dun,supl" mvno_match_data="mobipcs" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Mobipcs" apn="VZWINTERNET" mmsc="http://mms.mobipcs.com" type="default,mms,dun,supl" mvno_match_data="mobipcs" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Mohave" apn="VZWINTERNET" mmsc="http://mms.mohavewireless.com" type="default,mms,dun,supl" mvno_match_data="mohave" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Mohave" apn="VZWINTERNET" mmsc="http://mms.mohavewireless.com" type="default,mms,dun,supl" mvno_match_data="mohave" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Peopleswire" apn="VZWINTERNET" mmsc="http://172.16.16.130/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="Peopleswire" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Peopleswire" apn="VZWINTERNET" mmsc="http://172.16.16.130/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="Peopleswire" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Revol" apn="VZWINTERNET" mmsc="http://mms.revol.us/revol/mms.php" type="default,mms,dun,supl" mvno_match_data="revol" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="Revol" apn="VZWINTERNET" mmsc="http://mms.revol.us/revol/mms.php" type="default,mms,dun,supl" mvno_match_data="revol" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="000" carrier="distribution" apn="CdmaNai" mmsc="http://mms.dst.com/mms/" type="mms" mvno_match_data="distribution" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="flatwire" apn="CdmaNai" mmsc="http://mmsc.cleartalk.csky.us/" type="mms" mvno_match_data="flatwire" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="mobilenation" apn="CdmaNai" mmsc="http://mms.mymn3g.net" mmsproxy="mms.mymn3g.net" mmsport="8081" type="mms" mvno_match_data="mobilenation" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="mobipcs" apn="CdmaNai" mmsc="http://mms.mobipcs.com" type="mms" mvno_match_data="mobipcs" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="mohave" apn="CdmaNai" mmsc="http://mms.mohavewireless.com" type="mms" mvno_match_data="mohave" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="peopleswire" apn="CdmaNai" mmsc="http://172.16.16.130/mms/" mmsport="80" type="mms" mvno_match_data="peopleswire" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="000" carrier="revol" apn="CdmaNai" mmsc="http://mms.revol.us/revol/mms.php" type="mms" mvno_match_data="revol" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun" protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="12"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="4"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="5"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="6"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="7"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="8"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="12"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="4"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="5"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="6"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="7"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="8"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="004" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon CDMA HRPD" apn="CdmaNai" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,hipri,dun,stdhipri,supl" protocol="IPV4V6" bearer="6" carrier_enabled="FALSE"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon CDMA HRPD" apn="CdmaNai" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,hipri,dun,stdhipri,supl" protocol="IPV4V6" bearer="6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri,supl" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="4" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri,supl" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="016" carrier="Cricket" apn="wap.mycricket.com" mmsc="http://mms.mycricket.com/servlets/mms" user="\@mycricket.com" password="cricket" authtype="2"></apn>
+      <apn mcc="310" mnc="020" carrier="Union Wireless MMS" apn="union.mms.com" mmsc="http://mmsc/01" mmsproxy="166.230.4.83" mmsport="8799" type="mms"></apn>
+      <apn mcc="310" mnc="028" carrier=" ALU Test-SIM CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="028" carrier=" ALU Test-SIM Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="28" carrier="ALU Test-SIM CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="28" carrier="ALU Test-SIM Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="030" carrier="myBlue Pix" apn="mmswap.centennialwireless.com" mmsc="http://mms.myblue.com/servlets/mms" mmsproxy="63.99.231.135" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="30" carrier="myBlue Pix" apn="mmswap.centennialwireless.com" mmsc="http://mms.myblue.com/servlets/mms" mmsproxy="63.99.231.135" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="035" carrier="Etex" apn="VZWINTERNET" mmsc="http://mmsi.etex.mobi" type="default,mms,dun,supl" mvno_match_data="etex" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="035" carrier="Etex" apn="VZWINTERNET" mmsc="http://mmsi.etex.mobi" type="default,mms,dun,supl" mvno_match_data="etex" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="035" carrier="etex" apn="CdmaNai" mmsc="http://mmsi.etex.mobi" type="mms" mvno_match_data="etex" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="040" carrier="Mta" apn="VZWINTERNET" mmsc="http://mmsc.mta.dataonair.net/" mmsproxy="209.4.229.85" mmsport="6672" type="default,mms,dun,supl" mvno_match_data="mta" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="040" carrier="Mta" apn="VZWINTERNET" mmsc="http://mmsc.mta.dataonair.net/" mmsproxy="209.4.229.85" mmsport="6672" type="default,mms,dun,supl" mvno_match_data="mta" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="040" carrier="mta" apn="CdmaNai" mmsc="http://mmsc.mta.dataonair.net/" mmsproxy="209.4.229.85" mmsport="6672" type="mms" mvno_match_data="mta" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="050" carrier="Alaskacomm" apn="VZWINTERNET" mmsc="http://mmsc1.acsalaska.net/servlets/mms" mvno_match_data="alaskacomm" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="050" carrier="Alaskacomm" apn="VZWINTERNET" mmsc="http://mmsc1.acsalaska.net/servlets/mms" type="default,mms,dun,supl" mvno_match_data="alaskacomm" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="050" carrier="alaskacomm" apn="CdmaNai" mmsc="http://mmsc1.acsalaska.net/servlets/mms" type="mms" mvno_match_data="alaskacomm" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="066" carrier="U.S.Cellular" apn="internet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" user="*" password="*" server="*"></apn>
+      <apn mcc="310" mnc="080" carrier="CorrMMS" apn="corrmms" mmsc="http://mms.iot1.com/corr/mms.php" mmsproxy="66.255.55.23" mmsport="80" type="mms"></apn>
+      <apn mcc="310" mnc="090" carrier="Edge MMS Prepay" apn="ppmms" mmsc="http://mms.edgemobile.net/mmsc" mmsproxy="12.108.12.13" mmsport="3128" type="mms"></apn>
+      <apn mcc="310" mnc="090" carrier="LTE DNSADMIN" apn="apndnsota.4g.mycricket.com" mmsc="http://mms.mycricket.com/servlets/mms" type="fota" authtype="0"></apn>
+      <apn mcc="310" mnc="090" carrier="LTE INTERNET" apn="4g.mycricket.com" mmsc="http://mms.mycricket.com/servlets/mms" type="default,dun,mms" authtype="0"></apn>
+      <apn mcc="310" mnc="090" carrier="MMS" apn="mms" mmsc="http://mms.edgemobile.net/mmsc" mmsproxy="12.108.12.13" mmsport="3128" type="mms"></apn>
+      <apn mcc="310" mnc="90" carrier="LTE ADMIN" apn="Apnota.4g.mycricket.com" mmsc="http://mms.mycricket.com/servlets/mms" type="default,dun,mms" authtype="0"></apn>
+      <apn mcc="310" mnc="100" carrier="PLAT-OTA-MMS" apn="plateaumms" mmsc="208.254.124.11:8514" mmsproxy="208.254.124.11" mmsport="8080" type="mms" password="mmsc"></apn>
+      <apn mcc="310" mnc="100" carrier="PLATMMS" apn="mms.plateau" mmsc="http://mms" mmsproxy="172.23.253.206" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="1"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="10"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="11"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="15"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="16"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="2"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="3"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" bearer="9"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="1"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="10"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="11"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="15"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="16"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="2"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="3"></apn>
+      <apn mcc="310" mnc="120" carrier="SPCS Global" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms" authtype="0" bearer="9"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="1" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="10" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="11" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="15" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="16" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="2" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="3" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" authtype="3" bearer="9" server="*"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="12"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="4"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="5"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="6"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="7"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" bearer="8"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="12"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="4"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="5"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="6"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="7"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs" authtype="0" bearer="8"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="12"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="4"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="5"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="6"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="7"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint" apn="sprint" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,supl,mms,ims,cbs,dun" bearer="8"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" authtype="0" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="310" mnc="120" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" authtype="0" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="130" carrier="Carolina West Wireless" apn="home.cww.com" mmsc="" mmsproxy="" mmsport="" type="default,supl,fota"></apn>
+      <apn mcc="310" mnc="130" carrier="Carolina West Wireless IMS" apn="ims" mmsc="" mmsproxy="" mmsport="" type="ims"></apn>
+      <apn mcc="310" mnc="130" carrier="Carolina West Wireless MMS" apn="mms" mmsc="http://mms.cwwmms.com/cww/mms.php" mmsproxy="" mmsport="" type="mms"></apn>
+      <apn mcc="310" mnc="130" carrier="Carolina West Wireless Tethering" apn="tethering.cww.com" mmsc="" mmsproxy="" mmsport="80" type="dun"></apn>
+      <apn mcc="310" mnc="150" carrier="internet" apn="ndo" mmsc="http://mmsc.aiowireless.net" mmsproxy="proxy.aiowireless.net" mmsport="80" type="default,mms,fota,hipri,supl"></apn>
+      <apn mcc="310" mnc="160" carrier="MetroPCS 160" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="160" carrier="T-Mobile US 160" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="160" carrier="T-Mobile US 160" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="160" carrier="T-Mobile US 160" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="160" carrier="T-Mobile US 160" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="170" carrier="Cingular MMS" apn="wap.cingular" mmsc="http://mmsc.cingular.com" mmsproxy="66.209.11.32" mmsport="8080" type="mms" user="WAP@CINGULARGPRS.COM" password="CINGULAR1"></apn>
+      <apn mcc="310" mnc="180" carrier="WCW-MMS" apn="mms.wcc.net" mmsc="http://mms.wcc.net" mmsproxy="209.55.70.246" mmsport="80" type="mms" user="13257630000" password="mmsc" authtype="3"></apn>
+      <apn mcc="310" mnc="200" carrier="MetroPCS 200" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="200" carrier="T-Mobile US 200" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="200" carrier="T-Mobile US 200" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="200" carrier="T-Mobile US 200" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="200" carrier="T-Mobile US 200" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="210" carrier="MetroPCS 210" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="210" carrier="T-Mobile US 210" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="210" carrier="T-Mobile US 210" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="210" carrier="T-Mobile US 210" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="210" carrier="T-Mobile US 210" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="220" carrier="MetroPCS 220" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="220" carrier="T-Mobile US 220" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="220" carrier="T-Mobile US 220" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="220" carrier="T-Mobile US 220" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="220" carrier="T-Mobile US 220" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="230" carrier="MetroPCS 230" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="230" carrier="T-Mobile US 230" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="230" carrier="T-Mobile US 230" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="230" carrier="T-Mobile US 230" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="230" carrier="T-Mobile US 230" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="240" carrier="MetroPCS 240" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="240" carrier="T-Mobile US 240" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="240" carrier="T-Mobile US 240" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="240" carrier="T-Mobile US 240" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="240" carrier="T-Mobile US 240" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="250" carrier="MetroPCS 250" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="250" carrier="T-Mobile US 250" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="250" carrier="T-Mobile US 250" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="250" carrier="T-Mobile US 250" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="250" carrier="T-Mobile US 250" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="T-Mobile GPRS" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="T-Mobile GPRS" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="T-Mobile US" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="260" carrier="T-Mobile US" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="260" carrier="SIMPLE" apn="simple" mmsc="http://smpl.mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" mvno_match_data="534D" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="Consumer Cellular" apn="wholesale" mmsc="http://wholesale.mmsmvno.com/mms/wapenc" mmsport="80" type="default,mms,supl,hipri" mvno_match_data="2AC9" mvno_type="gid"></apn>
+      <apn mcc="310" mnc="260" carrier="MetroPCS" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="TFWAP" apn="wap.tracfone" mmsc="http://mms.tracfone.com" type="default,mms,supl,hipri,fota" mvno_match_data="ddff" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="260" carrier="TFWAP" apn="wap.tracfone" mmsc="http://mms.tracfone.com" type="default,mms,supl,hipri,fota" mvno_match_data="deff" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="270" carrier="MetroPCS 270" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="270" carrier="T-Mobile US 270" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="270" carrier="T-Mobile US 270" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="270" carrier="T-Mobile US 270" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="270" carrier="T-Mobile US 270" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="300" carrier="MetroPCS 300" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="300" carrier="T-Mobile US 300" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="300" carrier="T-Mobile US 300" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="300" carrier="T-Mobile US 300" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="310" carrier="MetroPCS 310" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="310" carrier="T-Mobile US 310" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="310" carrier="T-Mobile US 310" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="310" carrier="T-Mobile US 310" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="310" carrier="T-Mobile US 310" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="320" carrier="Cellular One ClearSky MMS" apn="wap.c1csky.net" mmsc="http://mmsc.c1neaz.csky.us:6672" mmsproxy="209.4.229.94" mmsport="9401" type="mms"></apn>
+      <apn mcc="310" mnc="330" carrier="Alltel2" apn="VZWINTERNET" mmsc="http://mms.alltel.com/servlets/mms" mmsproxy="mms.alltel.com" mmsport="8080" type="default,mms,dun,supl" mvno_match_data="alltel2" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="330" carrier="Alltel2" apn="VZWINTERNET" mmsc="http://mms.alltel.com/servlets/mms" mmsproxy="mms.alltel.com" mmsport="8080" type="default,mms,dun,supl" mvno_match_data="alltel2" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="330" carrier="alltel2" apn="CdmaNai" mmsc="http://mms.alltel.com/servlets/mms" mmsproxy="mms.alltel.com" mmsport="8080" type="mms" mvno_match_data="alltel2" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="360" carrier="Pioneer" apn="VZWINTERNET" mmsc="http://mms1.zsend.com" type="default,mms,dun,supl" mvno_match_data="pioneer" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="360" carrier="Pioneer" apn="VZWINTERNET" mmsc="http://mms1.zsend.com" type="default,mms,dun,supl" mvno_match_data="pioneer" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="360" carrier="pioneer" apn="CdmaNai" mmsc="http://mms1.zsend.com" type="mms" mvno_match_data="pioneer" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="380" carrier="AWS MMS" apn="proxy" mmsc="http://mmsc.mymmode.com" mmsproxy="10.250.250.55" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="380" carrier="Cingular 380 ATT" apn="proxy" mmsc="http://mmsc.cingular.com/" mmsproxy="wireless.cingular.com" type="default,supl,mms"></apn>
+      <apn mcc="310" mnc="390" carrier="Celloneet MMS" apn="mms.celloneet.com" mmsc="http://mms.celloneet.com/servlets/mms" mmsproxy="63.99.231.135" mmsport="8080" type="mms" user="user1@mms.celloneet.com" password="celloneet"></apn>
+      <apn mcc="310" mnc="410" carrier="AT&amp;T PTA" apn="pta" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl,hipri,dun" authtype="0"></apn>
+      <apn mcc="310" mnc="410" carrier="AT&amp;T US MMS" apn="phone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="310" mnc="410" carrier="AT&amp;T US MMS" apn="wap.cingular" mmsc="http://mmsc.cingular.com" mmsproxy="wireless.cingular.com" mmsport="80" type="mms" authtype="0" proxy="wireless.cingular.com" port="80"></apn>
+      <apn mcc="310" mnc="410" carrier="ATT Nextgenphone" apn="nxtgenphone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl,fota,hipri"></apn>
+      <apn mcc="310" mnc="410" carrier="ATT Phone" apn="phone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl,fota"></apn>
+      <apn mcc="310" mnc="410" carrier="ATT Phone" apn="phone" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl,fota" authtype="0"></apn>
+      <apn mcc="310" mnc="410" carrier="ATT WAP" apn="wap.cingular" mmsc="http://mmsc.cingular.com/" mmsproxy="wireless.cingular.com" type="default,supl,mms" server="cingulargprs.com" proxy="wireless.cingular.com" port="80"></apn>
+      <apn mcc="310" mnc="410" carrier="ATT WAP" apn="wap.cingular" mmsc="http://mmsc.cingular.com/" mmsproxy="wireless.cingular.com" type="default,supl,mms" authtype="0" server="cingulargprs.com" proxy="wireless.cingular.com" port="80"></apn>
+      <apn mcc="310" mnc="410" carrier="Defense Mobile" apn="PRODATA" mmsc="http://mmsc.mobile.att.net" mmsproxy="proxy.mobile.att.net" mmsport="80" type="default,mms,supl" mvno_match_data="60FF" mvno_type="gid" protocol="IP"></apn>
+      <apn mcc="310" mnc="410" carrier="TFDATA" apn="tfdata" mmsc="http://mms-tf.net" mmsproxy="mms3.tracfone.com" mmsport="80" type="default,mms,supl,hipri,fota" mvno_match_data="ddff" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="410" carrier="TFDATA" apn="tfdata" mmsc="http://mms-tf.net" mmsproxy="mms3.tracfone.com" mmsport="80" type="default,mms,supl,hipri,fota" mvno_match_data="deff" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="420" carrier="CBW Data" apn="wap.gocbw.com" mmsc="http://mms.gocbw.com:8088/mms" mmsproxy="216.68.79.202" mmsport="80" type="default,supl,mms"></apn>
+      <apn mcc="310" mnc="430" carrier="Gci" apn="VZWINTERNET" mmsc="http://mmsc.akdt.dataonair.net:6672/" type="default,mms,dun,supl" mvno_match_data="gci" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="430" carrier="Gci" apn="VZWINTERNET" mmsc="http://mmsc.akdt.dataonair.net:6672/" type="default,mms,dun,supl" mvno_match_data="gci" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="430" carrier="gci" apn="CdmaNai" mmsc="http://mmsc.akdt.dataonair.net:6672/" type="mms" mvno_match_data="gci" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="450" carrier="Viaero MMS" apn="mms" mmsc="http://mms.viaero.com" mmsproxy="10.168.3.23" mmsport="9401" type="mms"></apn>
+      <apn mcc="310" mnc="470" carrier="MediaNet" apn="wap.cingular" mmsc="http://mmsc.cingular.com" mmsproxy="66.209.11.32" mmsport="8080" type="default,supl,mms" user="WAP@CINGULARGPRS.COM" password="CINGULAR1"></apn>
+      <apn mcc="310" mnc="470" carrier="MediaNet" apn="wap.cingular" mmsc="http://mmsc.cingular.com" mmsproxy="66.209.11.32" mmsport="8080" type="default,supl,mms" user="WAP@CINGULARGPRS.COM" password="CINGULAR1" authtype="3"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Ota" apn="admin.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="admin,fota,ota" protocol="IPV4V6" bearer="13" server="*"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Ota" apn="admin.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="admin,fota,ota" protocol="IPV4V6" bearer="14" server="*"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Tether" apn="tethering.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="dun,pam" protocol="IPV4V6" bearer="13" server="*"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Tether" apn="tethering.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="dun,pam" protocol="IPV4V6" bearer="14" server="*"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Wireless" apn="CdmaNai" mmsc="http://mms.ntelospcs.net/" type="mms" mvno_match_data="ntelos" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Wireless" apn="internet.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="default,internet,supl,hipri,mms" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="310" mnc="470" carrier="nTelos Wireless" apn="internet.4g.ntelos.com" mmsc="http://mms.ntelospcs.net" type="default,internet,supl,hipri,mms" authtype="0" protocol="IPV4V6" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="310" mnc="480" carrier="MediaNet" apn="wap.cingular" mmsc="http://mmsc.cingular.com" mmsproxy="66.209.11.32" mmsport="8080" type="default,supl,mms" user="WAP@CINGULARGPRS.COM" password="CINGULAR1"></apn>
+      <apn mcc="310" mnc="490" carrier="GoodCall Picture Message" apn="good.call" mmsc="http://mms.suncom.net:8088/mms" mmsproxy="66.150.33.125" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="490" carrier="GoodCall Picture Message" apn="good.call" mmsc="http://mms.suncom.net:8088/mms" mmsproxy="66.150.33.125" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="310" mnc="490" carrier="MetroPCS 490" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="490" carrier="Suncom MMS" apn="mms" mmsc="http://mms.suncom.net:8088/mms" mmsproxy="66.150.33.125" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="490" carrier="Suncom MMS" apn="mms" mmsc="http://mms.suncom.net:8088/mms" mmsproxy="66.150.33.125" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="310" mnc="490" carrier="T-Mobile US 490" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="490" carrier="T-Mobile US 490" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="490" carrier="T-Mobile US 490" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="490" carrier="T-Mobile US 490" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="530" carrier="MetroPCS 530" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="530" carrier="T-Mobile US 530" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="530" carrier="T-Mobile US 530" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="530" carrier="T-Mobile US 530" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="560" carrier="DobsonMMS" apn="dobsoncellularwap" mmsc="http://mmsc" mmsproxy="172.23.1.252" mmsport="8799" type="mms"></apn>
+      <apn mcc="310" mnc="570" carrier="Cellular One MMS" apn="clearsky" mmsc="http://mmsc.mtpcs.csky.us:6672/" mmsproxy="209.4.229.229" mmsport="9201" type="mms"></apn>
+      <apn mcc="310" mnc="570" carrier="ChinookMMS" apn="wapgw.chinookwireless.net" mmsc="http://mms.cellonenation.net/mms/" mmsproxy="204.181.155.195" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="580" carrier="Inland" apn="VZWINTERNET" mmsc="http://mms.inland3g.com/inland/mms.php" type="default,mms,dun,supl" mvno_match_data="inland" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="580" carrier="Inland" apn="VZWINTERNET" mmsc="http://mms.inland3g.com/inland/mms.php" type="default,mms,dun,supl" mvno_match_data="inland" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="580" carrier="MetroPCS 580" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="580" carrier="T-Mobile US 580" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="580" carrier="T-Mobile US 580" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="580" carrier="T-Mobile US 580" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="580" carrier="T-Mobile US 580" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="580" carrier="inland" apn="CdmaNai" mmsc="http://mms.inland3g.com/inland/mms.php" type="mms" mvno_match_data="inland" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="590" carrier="CellularOne MMS" apn="cellular1wap" mmsc="http://mmsc" mmsproxy="172.23.1.252" mmsport="8799" type="mms"></apn>
+      <apn mcc="310" mnc="590" carrier="CellularOne MMS" apn="cellular1wap" mmsc="http://mmsc" mmsproxy="172.23.1.252" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="310" mnc="590" carrier="MetroPCS 590" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="590" carrier="T-Mobile US 590" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="590" carrier="T-Mobile US 590" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="590" carrier="T-Mobile US 590" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="600" carrier="Cellcom" apn="Cellcom mms" mmsc="http://mms.cellcom.com:9201/cellcom/mms.php" type="mms" protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="600" carrier="Cellcom" apn="VZWINTERNET" mmsc="http://mms.cellcom.com/cellcom/mms.php" type="default,mms,dun,supl" mvno_match_data="cellcom" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="600" carrier="Cellcom" apn="VZWINTERNET" mmsc="http://mms.cellcom.com/cellcom/mms.php" type="default,mms,dun,supl" mvno_match_data="cellcom" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="600" carrier="cellcom" apn="CdmaNai" mmsc="http://mms.cellcom.com/cellcom/mms.php" type="mms" mvno_match_data="cellcom" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="610" carrier="EpicMMS" apn="mms.epictouch" mmsc="http://mmsc.westlinkcom.com/servlets/mms" mmsproxy="63.99.231.135" mmsport="8080" type="mms"></apn>
+      <apn mcc="310" mnc="640" carrier="MetroPCS 640" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="640" carrier="T-Mobile US 640" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="640" carrier="T-Mobile US 640" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="640" carrier="T-Mobile US 640" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="660" carrier="MetroPCS 660" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="660" carrier="T-Mobile US 660" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="660" carrier="T-Mobile US 660" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="660" carrier="T-Mobile US 660" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="660" carrier="T-Mobile US 660" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="750" carrier="Appalachian" apn="VZWINTERNET" mmsc="http://mms.ekn.com" mmsport="80" type="default,mms,dun,supl" mvno_match_data="appalachian" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="750" carrier="Appalachian" apn="VZWINTERNET" mmsc="http://mms.ekn.com" mmsport="80" type="default,mms,dun,supl" mvno_match_data="appalachian" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="750" carrier="appalachian" apn="CdmaNai" mmsc="http://mms.ekn.com" mmsport="80" type="mms" mvno_match_data="appalachian" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="770" carrier="Picture Messaging" apn="wap1.iwireless.com" mmsc="http://mmsc.iwireless.dataonair.net:6672" mmsproxy="209.4.229.31" mmsport="9401" type="mms"></apn>
+      <apn mcc="310" mnc="770" carrier="Picture Messaging" apn="wap1.iwireless.com" mmsc="http://mmsc.iwireless.dataonair.net:6672" mmsproxy="209.4.229.32" mmsport="9401" type="mms"></apn>
+      <apn mcc="310" mnc="800" carrier="MetroPCS 800" apn="fast.metropcs.com" mmsc="http://metropcs.mmsmvno.com/mms/wapenc" type="default,supl,mms" mvno_match_data="6D" mvno_type="gid" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="800" carrier="T-Mobile US 800" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"></apn>
+      <apn mcc="310" mnc="800" carrier="T-Mobile US 800" apn="epc.tmobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,mms,supl,hipri,fota" user="none" password="none" authtype="3" protocol="IP" server="*"></apn>
+      <apn mcc="310" mnc="800" carrier="T-Mobile US 800" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="800" carrier="T-Mobile US 800" apn="fast.t-mobile.com" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" type="default,supl,mms" authtype="0" protocol="IPV6" roaming_protocol="IP"></apn>
+      <apn mcc="310" mnc="820" carrier="Nepa" apn="VZWINTERNET" mmsc="http://mmsc.c1nepa.csky.us:6672/" type="default,mms,dun,supl" mvno_match_data="nepa" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="820" carrier="Nepa" apn="VZWINTERNET" mmsc="http://mmsc.c1nepa.csky.us:6672/" type="default,mms,dun,supl" mvno_match_data="nepa" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="820" carrier="nepa" apn="CdmaNai" mmsc="http://mmsc.c1nepa.csky.us:6672/" type="mms" mvno_match_data="nepa" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="840" carrier="Edge MMS Prepay" apn="ppmms" mmsc="http://mms.edgemobile.net/mmsc" mmsproxy="12.108.12.13" mmsport="3128" type="mms"></apn>
+      <apn mcc="310" mnc="840" carrier="MMS" apn="mms" mmsc="http://mms.edgemobile.net/mmsc" mmsproxy="12.108.12.13" mmsport="3128" type="mms"></apn>
+      <apn mcc="310" mnc="880" carrier="DTC MMS" apn="mms.adv.com" mmsc="http://mms.iot1.com/advantage/mms.php" type="mms"></apn>
+      <apn mcc="310" mnc="900" carrier="Midrivers" apn="VZWINTERNET" mmsc="http://mmsc.midrivers.csky.us:6672/" mmsproxy="209.4.229.27" mmsport="9401" type="default,mms,dun,supl" mvno_match_data="midrivers" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="900" carrier="Midrivers" apn="VZWINTERNET" mmsc="http://mmsc.midrivers.csky.us:6672/" mmsproxy="209.4.229.27" mmsport="9401" type="default,mms,dun,supl" mvno_match_data="midrivers" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="900" carrier="midrivers" apn="CdmaNai" mmsc="http://mmsc.midrivers.csky.us:6672/" mmsproxy="209.4.229.27" mmsport="9401" type="mms" mvno_match_data="midrivers" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="910" carrier="WOW_WAP" apn="wap.firstcellular.com" mmsc="mms.firstcellular.net/mmsc" mmsproxy="10.101.1.5" mmsport="3128" type="default,supl,mms"></apn>
+      <apn mcc="310" mnc="920" carrier="Jamesvalley" apn="VZWINTERNET" mmsc="http://m.iot1.com/jamesvalley/mms.php" mmsproxy="m.iot1.com" mmsport="9201" type="default,mms,dun,supl" mvno_match_data="jamesvalley" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="920" carrier="Jamesvalley" apn="VZWINTERNET" mmsc="http://m.iot1.com/jamesvalley/mms.php" mmsproxy="m.iot1.com" mmsport="9201" type="default,mms,dun,supl" mvno_match_data="jamesvalley" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="920" carrier="jamesvalley" apn="CdmaNai" mmsc="http://m.iot1.com/jamesvalley/mms.php" mmsproxy="m.iot1.com" mmsport="9201" type="mms" mvno_match_data="jamesvalley" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="930" carrier="Copper Valley" apn="VZWINTERNET" mmsc="http://cvwmms.com/servlets/mms" type="default,mms,dun,supl" mvno_match_data="coppervalley" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="930" carrier="Copper Valley" apn="VZWINTERNET" mmsc="http://cvwmms.com/servlets/mms" type="default,mms,dun,supl" mvno_match_data="coppervalley" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="930" carrier="coppervalley" apn="CdmaNai" mmsc="http://cvwmms.com/servlets/mms" type="mms" mvno_match_data="coppervalley" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="Nntcwire" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="nntcwire" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Nntcwire" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="nntcwire" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Silverstar" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="silverstar" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Silverstar" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="silverstar" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Snakeriver" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="snakeriver" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Snakeriver" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="snakeriver" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Southcentral" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="southcentral" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Southcentral" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="southcentral" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Syringa" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="syringa" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="Syringa" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="syringa" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="nntcwire" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="nntcwire" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="silverstar" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="silverstar" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="snakeriver" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="snakeriver" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="southcentral" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="southcentral" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="strata" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="strata" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="310" mnc="960" carrier="strata" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="strata" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="strata" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="strata" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="310" mnc="960" carrier="syringa" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="syringa" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="050" carrier="Thumbcellular" apn="VZWINTERNET" mmsc="http://mms.thumbcell.com/thumb/mms.php" type="default,mms,dun,supl" mvno_match_data="thumbcellular" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="050" carrier="Thumbcellular" apn="VZWINTERNET" mmsc="http://mms.thumbcell.com/thumb/mms.php" type="default,mms,dun,supl" mvno_match_data="thumbcellular" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="050" carrier="thumbcellular" apn="CdmaNai" mmsc="http://mms.thumbcell.com/thumb/mms.php" type="mms" mvno_match_data="thumbcellular" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="070" carrier="Elementmobile" apn="VZWINTERNET" mmsc="http://mms.elementmobile.net" mmsport="8080" type="default,mms,dun,supl" mvno_match_data="elementmobile" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="070" carrier="Elementmobile" apn="VZWINTERNET" mmsc="http://mms.elementmobile.net" mmsport="8080" type="default,mms,dun,supl" mvno_match_data="elementmobile" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="070" carrier="elementmobile" apn="CdmaNai" mmsc="http://mms.elementmobile.net" mmsport="8080" type="mms" mvno_match_data="elementmobile" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="080" carrier="PINE WAP" apn="PINE" mmsc="http://69.8.34.146/mms/" mmsproxy="69.8.34.146" mmsport="9401" type="default,mms"></apn>
+      <apn mcc="311" mnc="100" carrier="NexTech Wireless" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="mms" authtype="3" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="311" mnc="100" carrier="NexTech Wireless" apn="CdmaNai" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="mms" protocol="IPV4V6" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="140" carrier="Sprocket" apn="VZWINTERNET" mmsc="http://mms.sprocketwireless.com" type="default,mms,dun,supl" mvno_match_data="sprocket" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="140" carrier="Sprocket" apn="VZWINTERNET" mmsc="http://mms.sprocketwireless.com" type="default,mms,dun,supl" mvno_match_data="sprocket" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="140" carrier="sprocket" apn="CdmaNai" mmsc="http://mms.sprocketwireless.com" type="mms" mvno_match_data="sprocket" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="190" carrier="MMS" apn="mms.cellular1.net" mmsc="http://mms.cellular1.net" mmsproxy="10.10.0.97" mmsport="9201" type="mms"></apn>
+      <apn mcc="311" mnc="190" carrier="MMS" apn="wap.cellular1.net" mmsc="http://mms.cellular1.net/ecit/mms.php" type="mms"></apn>
+      <apn mcc="311" mnc="210" carrier="Farmers MMS" apn="mms.farmers.com" mmsc="172.16.0.37:8514" type="mms"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="220" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="220" carrier="USCC" apn="internet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" mmsport="80" type="mms" authtype="3"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="221" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="222" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="223" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="224" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="true"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="225" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="true"></apn>
+      <apn mcc="311" mnc="225" carrier="USCC INTERNET 2" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,dun,mms,fota"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="226" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="227" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="228" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="229" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire" apn="CdmaNai" mmsc="http://pix.cspire.com/servlets/mms" mmsproxy="66.175.144.91" mmsport="80" type="mms" mvno_match_data="cspire" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire" apn="Cspire mms" mmsc="http://pix.cspire.com/servlets/mms" type="mms" protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire internet" apn="internet.cs4glte.com" mmsc="http://pix.cspire.com" type="default,internet,mms" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire internet" apn="internet.cs4glte.com" mmsc="http://pix.cspire.com" type="default,internet,mms" protocol="IPV4V6" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire ota" apn="admin.cs4glte.com" mmsc="http://pix.cspire.com" type="admin,fota,ota" protocol="IPV4V6" bearer="13" server="*"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire ota" apn="admin.cs4glte.com" mmsc="http://pix.cspire.com" type="admin,fota,ota" protocol="IPV4V6" bearer="13" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire ota" apn="admin.cs4glte.com" mmsc="http://pix.cspire.com" type="admin,fota,ota" protocol="IPV4V6" bearer="14" server="*"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire ota" apn="admin.cs4glte.com" mmsc="http://pix.cspire.com" type="admin,fota,ota" protocol="IPV4V6" bearer="14" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire tether" apn="tethering.cs4glte.com" mmsc="http://pix.cspire.com" type="dun,pam" protocol="IPV4V6" bearer="13" server="*"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire tether" apn="tethering.cs4glte.com" mmsc="http://pix.cspire.com" type="dun,pam" protocol="IPV4V6" bearer="13" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire tether" apn="tethering.cs4glte.com" mmsc="http://pix.cspire.com" type="dun,pam" protocol="IPV4V6" bearer="14" server="*"></apn>
+      <apn mcc="311" mnc="230" carrier="CSpire tether" apn="tethering.cs4glte.com" mmsc="http://pix.cspire.com" type="dun,pam" protocol="IPV4V6" bearer="14" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="310" carrier="Leaco" apn="VZWINTERNET" mmsc="http://204.181.155.217/mms/" type="default,mms,dun,supl" mvno_match_data="leaco" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="310" carrier="Leaco" apn="VZWINTERNET" mmsc="http://204.181.155.217/mms/" type="default,mms,dun,supl" mvno_match_data="leaco" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="310" carrier="leaco" apn="CdmaNai" mmsc="http://204.181.155.217/mms/" type="mms" mvno_match_data="leaco" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="340" carrier="Illinois valley" apn="VZWINTERNET" mmsc="http://mms.iot1.com/ivc/mms.php" type="default,mms,dun,supl" mvno_match_data="illinoisvalley" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="340" carrier="Illinois valley" apn="VZWINTERNET" mmsc="http://mms.iot1.com/ivc/mms.php" type="default,mms,dun,supl" mvno_match_data="illinoisvalley" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="340" carrier="illinoisvalley" apn="CdmaNai" mmsc="http://mms.iot1.com/ivc/mms.php" type="mms" mvno_match_data="illinoisvalley" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="350" carrier="Nemont" apn="VZWINTERNET" mmsc="http://mms.nemont.mobi/mms/" type="default,mms,dun,supl" mvno_match_data="nemont" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="350" carrier="Nemont" apn="VZWINTERNET" mmsc="http://mms.nemont.mobi/mms/" type="default,mms,dun,supl" mvno_match_data="nemont" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="350" carrier="nemont" apn="CdmaNai" mmsc="http://mms.nemont.mobi/mms/" type="mms" mvno_match_data="nemont" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="370" carrier="ACS MMS" apn="mms.acs" mmsc="http://mmsc.acsalaska.net" mmsproxy="209.4.229.92" mmsport="9201" type="mms" mvno_match_data="3113702" mvno_type="imsi"></apn>
+      <apn mcc="311" mnc="370" carrier="GCI MMS" apn="mms.gci" mmsc="http://mmsc.gci.csky.us:6672" mmsproxy="209.4.229.92" mmsport="9201" type="mms" proxy="209.4.229.92" port="9201"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="390" carrier="Ericsson Test-SIM Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="410" carrier="Chatmobrsa2" apn="VZWINTERNET" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobrsa2" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="410" carrier="Chatmobrsa2" apn="VZWINTERNET" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobrsa2" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="410" carrier="chatmobrsa2" apn="CdmaNai" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="mms" mvno_match_data="chatmobrsa2" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="420" carrier="Northwestcell" apn="VZWINTERNET" mmsc="http://mms.nwmcell.com/mms/" type="default,mms,dun,supl" mvno_match_data="northwestcell" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="420" carrier="Northwestcell" apn="VZWINTERNET" mmsc="http://mms.nwmcell.com/mms/" type="default,mms,dun,supl" mvno_match_data="northwestcell" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="420" carrier="northwestcell" apn="CdmaNai" mmsc="http://mms.nwmcell.com/mms/" type="mms" mvno_match_data="northwestcell" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="430" carrier="Chatmobrsa1" apn="VZWINTERNET" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobrsa1" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="430" carrier="Chatmobrsa1" apn="VZWINTERNET" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobrsa1" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="430" carrier="chatmobrsa1" apn="CdmaNai" mmsc="http://mmsc.hawkeyeswitch.net/mms/" mmsport="80" type="mms" mvno_match_data="chatmobrsa1" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="440" carrier="Bluegrass" apn="Bluegrass mms" mmsc="http://m.iot1.com/bluegrass/mms.php" type="mms" protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="440" carrier="Bluegrass" apn="VZWINTERNET" mmsc="http://mms.iot1.com/bluegrass/mms.php" type="default,mms,dun,supl" mvno_match_data="bluegrass" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="440" carrier="Bluegrass" apn="VZWINTERNET" mmsc="http://mms.iot1.com/bluegrass/mms.php" type="default,mms,dun,supl" mvno_match_data="bluegrass" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="440" carrier="bluegrass" apn="CdmaNai" mmsc="http://mms.iot1.com/bluegrass/mms.php" type="mms" mvno_match_data="bluegrass" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="450" carrier="Ptci" apn="VZWINTERNET" mmsc="http://mmsc.ptci.net" mmsport="6672" type="default,mms,dun,supl" mvno_match_data="ptci" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="450" carrier="Ptci" apn="VZWINTERNET" mmsc="http://mmsc.ptci.net" mmsport="6672" type="default,mms,dun,supl" mvno_match_data="ptci" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="450" carrier="ptci" apn="CdmaNai" mmsc="http://mmsc.ptci.net" mmsport="6672" type="mms" mvno_match_data="ptci" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="480" carrier="EHRPD - Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="LTE - Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="1" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="10" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="11" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="15" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="2" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="3" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,mms" protocol="IPV4V6" bearer="9" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="12"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="4"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="5"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="7"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs" authtype="3" protocol="IPV4V6" bearer="8"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="12"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="4"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="5"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="6"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="7"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon" apn="internet" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,supl,fota,ims,cbs,dun" authtype="3" protocol="IPV4V6" bearer="8"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="1" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="10" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="11" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="15" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="2" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="3" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CBS" apn="VZWAPP" mmsc="http://mms.vtext.com/servlets/mms" type="cbs,hipri" protocol="IPV4V6" bearer="9" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CDMA HRPD" apn="CdmaNai" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,hipri,dun,stdhipri,supl" protocol="IPV4V6" bearer="6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon CDMA HRPD" apn="CdmaNai" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,hipri,dun,stdhipri,supl" protocol="IPV4V6" bearer="6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="1" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="10" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="11" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="15" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="2" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="3" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri" protocol="IPV4V6" bearer="9" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri,supl" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="480" carrier="Verizon Internet" apn="VZWINTERNET" mmsc="http://mms.vtext.com/servlets/mms" type="default,mms,dun,stdhipri,supl" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="1" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="10" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="11" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="15" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="16" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="2" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="3" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="cinet.spcs" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" user="none" password="none" bearer="9" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint" apn="mms_over_wifi" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="wifi" user="*" password="*" server="*"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint CdmaNai" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="default,mms" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="490" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mmsc.vmobl.com:8088" mmsproxy="68.28.31.2" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="490" carrier="Virgin Mobile US" apn="0" mmsc="http://mmsc.vmobl.com:8088/mms?" mmsproxy="205.239.233.136" mmsport="81" authtype="0"></apn>
+      <apn mcc="311" mnc="500" carrier="24-7 WAP" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672" mmsproxy="09.4.229.46" mmsport="9201" mvno_match_data="24-7 Wireless" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="24-7 WAP AT&amp;T" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672" mmsproxy="09.4.229.46" mmsport="9201" mvno_match_data="24-7 Wireless RPA" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="24-7 WAP Other networks" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672" mmsproxy="09.4.229.46" mmsport="9201" mvno_match_data="24-7 Wireless RPO" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="24-7 WAP T-Mobile" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672" mmsproxy="09.4.229.46" mmsport="9201" mvno_match_data="24-7 Wireless RPT" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Mosaic WAP" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Mosaic Mobile" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Mosaic WAP AT&amp;T" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Mosaic RPA" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Mosaic WAP Other networks" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Mosaic RPO" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Mosaic WAP T-Mobile" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Mosaic RPT" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Norvado" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Norvado Wireless" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Norvado AT&amp;T" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Norvado Wireless RPA" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Norvado Other networks" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Norvado Wireless RPO" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="500" carrier="Norvado T-Mobile" apn="wap" mmsc="http://mmsc.ctc.csky.us:6672/" mmsproxy="209.4.229.46" mmsport="9201" type="default,mms" mvno_match_data="Norvado Wireless RPT" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="530" carrier="Blaze" apn="mms.mymobiletxt.com" mmsc="http://mms2.mymobiletxt.net" type="default,mms" mvno_match_data="Blaze Wireless" mvno_type="spn"></apn>
+      <apn mcc="311" mnc="530" carrier="Duet Internet" apn="wap.mymobiletxt.com" mmsc="http://172.16.16.103/mms/" mmsproxy="172.16.16.102" mmsport="8080" type="default,mms" protocol="IP"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="580" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="580" carrier="USCC INTERNET" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,dun,mms,fota"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="581" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="582" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="583" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="584" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="585" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="586" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="587" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="588" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="12" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="4" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="5" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="7" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" authtype="3" protocol="IPV4V6" bearer="8" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="CdmaNai" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="589" carrier="U.S. Cellular" apn="usccinternet" mmsc="http://mmsc1.uscc.net/mmsc/MMS" type="default,mms,dun,hipri,fota" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="590" carrier="Gsc" apn="VZWINTERNET" mmsc="http://mmsc1.gscdata.com" type="default,mms,dun,supl" mvno_match_data="gsc" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="590" carrier="Gsc" apn="VZWINTERNET" mmsc="http://mmsc1.gscdata.com" type="default,mms,dun,supl" mvno_match_data="gsc" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="590" carrier="gsc" apn="CdmaNai" mmsc="http://mmsc1.gscdata.com" type="mms" mvno_match_data="gsc" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="600" carrier="Cox" apn="VZWINTERNET" mmsc="http://mms.cox.net/cox/mms.php" type="default,mms,dun,supl" mvno_match_data="cox" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="600" carrier="Cox" apn="VZWINTERNET" mmsc="http://mms.cox.net/cox/mms.php" type="default,mms,dun,supl" mvno_match_data="cox" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="600" carrier="cox" apn="CdmaNai" mmsc="http://mms.cox.net/cox/mms.php" type="mms" mvno_match_data="cox" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="610" carrier="Srtcomm" apn="VZWINTERNET" mmsc="http://mms.iot1.com/srt/mms.php" mmsproxy="mms.iot1.com" mmsport="9201" type="default,mms,dun,supl" mvno_match_data="srtcomm" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="610" carrier="Srtcomm" apn="VZWINTERNET" mmsc="http://mms.iot1.com/srt/mms.php" mmsproxy="mms.iot1.com" mmsport="9201" type="default,mms,dun,supl" mvno_match_data="srtcomm" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="610" carrier="srtcomm" apn="CdmaNai" mmsc="http://mms.iot1.com/srt/mms.php" mmsproxy="mms.iot1.com" mmsport="9201" type="mms" mvno_match_data="srtcomm" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="650" carrier="Unitedwireless" apn="VZWINTERNET" mmsc="http://mms.unitedwireless.com/united/mms.php" type="default,mms,dun,supl" mvno_match_data="unitedwireless" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="650" carrier="Unitedwireless" apn="VZWINTERNET" mmsc="http://mms.unitedwireless.com/united/mms.php" type="default,mms,dun,supl" mvno_match_data="unitedwireless" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="650" carrier="unitedwireless" apn="CdmaNai" mmsc="http://mms.unitedwireless.com/united/mms.php" type="mms" mvno_match_data="unitedwireless" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="660" carrier="MetroPCS IMS" apn="ims.metropcs" mmsc="http://mms.metropcs.net:3128/mmsc" type="ims" authtype="0"></apn>
+      <apn mcc="311" mnc="660" carrier="MetroPCS LTE" apn="internet.metropcs" mmsc="http://mms.metropcs.net:3128/mmsc" type="default,hipri,admin,mms" authtype="0"></apn>
+      <apn mcc="311" mnc="670" carrier="Pinebelt" apn="VZWINTERNET" mmsc="http://mmsc.pinebelt.csky.us:6672/" type="default,mms,dun,supl" mvno_match_data="pinebelt" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="670" carrier="Pinebelt" apn="VZWINTERNET" mmsc="http://mmsc.pinebelt.csky.us:6672/" type="default,mms,dun,supl" mvno_match_data="pinebelt" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="670" carrier="pinebelt" apn="CdmaNai" mmsc="http://mmsc.pinebelt.csky.us:6672/" type="mms" mvno_match_data="pinebelt" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="870" carrier="Internet" apn="n.ispsn" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default" protocol="IPV4V6" bearer="0"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="1" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="10" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="11" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="15" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="16" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="2" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="3" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="cinet.spcs" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="9" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint" apn="mms_over_wifi" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="wifi" user="*" password="*" server="*"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint CdmaNai" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="311" mnc="870" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mm.myboostmobile.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="311" mnc="910" carrier="MobileNation" apn="mymn4g.net" mmsc="http://mms.mymn3g.net" mmsproxy="mms.mymn3g.net" mmsport="8081" type="default,internet,admin,fota,dun,mms" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="311" mnc="920" carrier="Chariton valley" apn="VZWINTERNET" mmsc="http://mms.cvalley.net" mmsport="80" type="default,mms,dun,supl" mvno_match_data="charitonvalley" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="920" carrier="Chariton valley" apn="VZWINTERNET" mmsc="http://mms.cvalley.net" mmsport="80" type="default,mms,dun,supl" mvno_match_data="charitonvalley" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="311" mnc="920" carrier="charitonvalley" apn="CdmaNai" mmsc="http://mms.cvalley.net" mmsport="80" type="mms" mvno_match_data="charitonvalley" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="311" mnc="930" carrier="Syringa Wireless" apn="internet.syringawireless.com" mmsc="http://mms.rinawireless.com" mmsport="80" type="default,internet,admin,fota,dun,mms" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="312" mnc="040" carrier="Custer" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="custer" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="312" mnc="040" carrier="Custer" apn="VZWINTERNET" mmsc="http://mms.rinawireless.com" type="default,mms,dun,supl" mvno_match_data="custer" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="312" mnc="040" carrier="custer" apn="CdmaNai" mmsc="http://mms.rinawireless.com" type="mms" mvno_match_data="custer" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="312" mnc="160" carrier="chatmobility" apn="CdmaNai" mmsc="http://mms.chatmobility.com/mms/" mmsport="80" type="mms" mvno_match_data="chatmobility" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="312" mnc="160" carrier="chatmobility" apn="VZWINTERNET" mmsc="http://mms.chatmobility.com/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobility" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="312" mnc="160" carrier="chatmobility" apn="VZWINTERNET" mmsc="http://mms.chatmobility.com/mms/" mmsport="80" type="default,mms,dun,supl" mvno_match_data="chatmobility" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Ota" apn="admin.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="admin,fota,ota" protocol="IP" bearer="13" server="*"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Ota" apn="admin.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="admin,fota,ota" protocol="IP" bearer="13" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Ota" apn="admin.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="admin,fota,ota" protocol="IP" bearer="14" server="*"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Ota" apn="admin.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="admin,fota,ota" protocol="IP" bearer="14" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Tether" apn="modem.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="dun,pam" protocol="IPV4V6" bearer="13" server="*"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Tether" apn="modem.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="dun,pam" protocol="IPV4V6" bearer="13" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Tether" apn="modem.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="dun,pam" protocol="IPV4V6" bearer="14" server="*"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Tether" apn="modem.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="dun,pam" protocol="IPV4V6" bearer="14" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Wireless" apn="internet.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="default,internet,supl,hipri,mms" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="312" mnc="420" carrier="NexTech Wireless" apn="internet.lte.ntwls.com" mmsc="http://mms.ntwls.net/nex-tech/mms.php" type="default,internet,supl,hipri,mms" protocol="IPV4V6" server="*" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="1" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="10" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="11" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="15" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="16" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="2" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="3" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" user="none" password="none" bearer="9" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint" apn="mms_over_wifi" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="wifi" user="*" password="*" server="*"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default,mms" authtype="3" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="FALSE"></apn>
+      <apn mcc="312" mnc="530" carrier="Sprint CdmaNai" apn="CdmaNai" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="mms" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="TRUE"></apn>
+      <apn mcc="312" mnc="570" carrier="Blue Wireless" apn="Blue Hotspot" mmsc="http://mms.blueunlimited.com" mmsport="8514" type="default,dun,mms" user="%M@dun.bluehandset.com" password="wirelessblue" protocol="IPV4V6" server="*"></apn>
+      <apn mcc="316" mnc="010" carrier="Sprint APN" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default" user="none" password="none" server="*"></apn>
+      <apn mcc="316" mnc="10" carrier="Sprint" apn="mms_over_wifi" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="wifi" user="*" password="*" server="*"></apn>
+      <apn mcc="316" mnc="10" carrier="Sprint APN" apn="cinet.spcs" mmsc="http://mms.sprintpcs.com" mmsproxy="68.28.31.7" mmsport="80" type="default" user="none" password="none" server="*"></apn>
+      <apn mcc="330" mnc="000" carrier="Openmobile" apn="VZWINTERNET" mmsc="http://mms.openmobilepr.com:1981/" type="default,mms,dun,supl" mvno_match_data="openmobile" mvno_type="spn" protocol="IPV4V6" bearer="13" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="330" mnc="000" carrier="Openmobile" apn="VZWINTERNET" mmsc="http://mms.openmobilepr.com:1981/" type="default,mms,dun,supl" mvno_match_data="openmobile" mvno_type="spn" protocol="IPV4V6" bearer="14" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="330" mnc="000" carrier="openmobile" apn="CdmaNai" mmsc="http://mms.openmobilepr.com:1981/" type="mms" mvno_match_data="openmobile" mvno_type="spn" protocol="IPV4V6" bearer="6" roaming_protocol="IPV4V6" carrier_enabled="false"></apn>
+      <apn mcc="330" mnc="110" carrier="MMS CLARO" apn="mms.claropr.com" mmsc="http://mmsg.claropr.com:10021/mmsc" mmsproxy="10.50.38.3" mmsport="8799" type="mms"></apn>
+      <apn mcc="330" mnc="110" carrier="MMS CLARO" apn="mms.claropr.com" mmsc="http://mmsg.claropr.com:10021/mmsc" mmsproxy="10.50.38.3" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="330" mnc="110" carrier="Puerto Rico:Claro:MMS" apn="mms.claropr.com" mmsc="http://mmsg.claropr.com:10021/mmsc" mmsproxy="10.50.38.3" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="330" mnc="110" carrier="Puerto Rico:Claro:MMS" apn="mmslte.claropr.com" mmsc="http://mmsg.claropr.com:10021/mmsc" mmsproxy="10.50.38.3" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="334" mnc="03" carrier="Movistar MMS" apn="mms.movistar.mx" mmsc="http://mms.movistar.mx" mmsproxy="10.2.20.1" mmsport="80" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="334" mnc="3" carrier="Movistar MMS" apn="mms.movistar.mx" mmsc="http://mms.movistar.mx" mmsproxy="10.2.20.1" mmsport="80" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="334" mnc="020" carrier="Mensajes Multimedia" apn="mms.itelcel.com" mmsc="http://mms.itelcel.com/servlets/mms" mmsproxy="148.233.151.240" mmsport="8080" type="mms" user="mmsgprs" password="mmsgprs2003" authtype="1"></apn>
+      <apn mcc="334" mnc="20" carrier="Mexico:Telcel:Mensajes Multimedia" apn="mms.itelcel.com" mmsc="http://mms.itelcel.com/servlets/mms" mmsproxy="148.233.151.240" mmsport="8080" type="mms" user="mmsgprs" password="mmsgprs2003" authtype="1"></apn>
+      <apn mcc="334" mnc="030" carrier="Movistar MMS" apn="mms.movistar.mx" mmsc="http://mms.movistar.mx" mmsproxy="10.2.20.1" mmsport="80" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="334" mnc="30" carrier="Movistar MMS" apn="mms.movistar.mx" mmsc="http://mms.movistar.mx" mmsproxy="10.2.20.1" mmsport="80" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="334" mnc="050" carrier="Iusacell MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm"></apn>
+      <apn mcc="334" mnc="50" carrier="Iusacell MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="3"></apn>
+      <apn mcc="334" mnc="50" carrier="Mexico:Iusacell MMS" apn="mms.iusacellgsm.mx" mmsc="http://mms.iusacell3g.com/" type="mms" user="mmsiusacellgsm" password="mmsiusacellgsm" authtype="0"></apn>
+      <apn mcc="334" mnc="090" carrier="Nextel MMS" apn="mms.nexteldata.com.mx" mmsc="http://3gmms.nexteldata.com.mx" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="334" mnc="90" carrier="Nextel MMS" apn="mms.nexteldata.com.mx" mmsc="http://3gmms.nexteldata.com.mx" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="338" mnc="05" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms"></apn>
+      <apn mcc="338" mnc="5" carrier="Jamaica:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="338" mnc="5" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="338" mnc="18" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="338" mnc="18" carrier="Lime Prepaid MMS" apn="ppmms" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="338" mnc="050" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms"></apn>
+      <apn mcc="338" mnc="50" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms"></apn>
+      <apn mcc="338" mnc="070" carrier="Claro MMS" apn="mms.ideasclaro.com.jm" mmsc="http://mms.ideasclaro.com.jm/mms/wapenc" mmsproxy="190.80.147.118" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="338" mnc="70" carrier="Jamaica:Claro:MMS" apn="mms.ideasclaro.com.jm" mmsc="http://mms.ideasclaro.com.jm/mms/wapenc" mmsproxy="190.80.147.118" mmsport="8080" type="mms" user="claro" password="claro" authtype="1"></apn>
+      <apn mcc="338" mnc="180" carrier="Jamaica:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="338" mnc="180" carrier="Jamaica:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="338" mnc="180" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="338" mnc="180" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="338" mnc="180" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="338" mnc="180" carrier="Lime Prepaid MMS" apn="ppmms" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="338" mnc="180" carrier="Lime Prepaid MMS" apn="ppmms" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="340" mnc="01" carrier="Orange MMS Caraïbe" apn="orangewap" mmsc="http://193.251.160.246/servlets/mms" mmsproxy="10.0.0.10" mmsport="8082" type="mms" user="orange" password="orange"></apn>
+      <apn mcc="340" mnc="1" carrier="Orange MMS Caraïbe" apn="orangewap" mmsc="http://193.251.160.246/servlets/mms" mmsproxy="10.0.0.10" mmsport="8082" type="mms" user="orange" password="orange"></apn>
+      <apn mcc="340" mnc="20" carrier="Digicel Web" apn="web.digicelfr.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="340" mnc="20" carrier="Digicel Web" apn="web.digicelfr.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="340" mnc="20" carrier="French West Indies:Digicel:Mms" apn="wap.digicelfr.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="340" mnc="20" carrier="French West Indies:Digicel:Modem" apn="wap.digicelfr.com" mmsc="http://wapdigicel.com" type="dun" user="wap" password="wap" authtype="1" proxy="172.20.6.12" port="8080"></apn>
+      <apn mcc="342" mnc="60" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="342" mnc="600" carrier="Barbado:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="342" mnc="600" carrier="Barbado:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="342" mnc="600" carrier="Barbados:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="344" mnc="92" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="344" mnc="920" carrier="Antigua:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="344" mnc="920" carrier="Antigua:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="344" mnc="920" carrier="Antigua:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="346" mnc="14" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="346" mnc="140" carrier="Cayman Islands:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="346" mnc="140" carrier="Cayman Islands:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="346" mnc="140" carrier="Cayman Islands:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="348" mnc="17" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="348" mnc="77" carrier="Bvi:Digicel:Mms" apn="wap.digicelbvi.com" mmsc="http://mmc.digiceljamaica.com/servlets/mms" mmsproxy="172.16.7.12" mmsport="9201" type="mms" user="wapbvi" password="wapbvi" authtype="1"></apn>
+      <apn mcc="348" mnc="77" carrier="Bvi:Digicel:Modem" apn="wap.digicelbvi.com" mmsc="http://wapdigicel.com" type="dun" user="wapbvi" password="wapbvi" authtype="1" proxy="172.16.7.12" port="8080"></apn>
+      <apn mcc="348" mnc="170" carrier="Bvi:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="348" mnc="170" carrier="Bvi:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="348" mnc="170" carrier="Bvi:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="352" mnc="11" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="352" mnc="110" carrier="Grenada:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="352" mnc="110" carrier="Grenada:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="352" mnc="110" carrier="Grenada:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="354" mnc="86" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="354" mnc="860" carrier="Monserrat:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="354" mnc="860" carrier="Monserrat:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="354" mnc="860" carrier="Monserrat:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="356" mnc="11" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="356" mnc="110" carrier="St Kitts And Nevis:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="356" mnc="110" carrier="St Kitts And Nevis:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="356" mnc="110" carrier="St Kitts And Nevis:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="358" mnc="11" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="358" mnc="110" carrier="St Lucia:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="358" mnc="110" carrier="St Lucia:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="358" mnc="110" carrier="St Lucia:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="360" mnc="11" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="360" mnc="110" carrier="St Vincent:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="360" mnc="110" carrier="St Vincent:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="360" mnc="110" carrier="St Vincent:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="362" mnc="69" carrier="Curacao:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="362" mnc="69" carrier="Curacao:Digicel:Modem" apn="wap" mmsc="http://wapdigicel.com" type="dun" authtype="1" proxy="172.16.7.12" port="8080"></apn>
+      <apn mcc="363" mnc="02" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="363" mnc="2" carrier="Aruba:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="363" mnc="020" carrier="MMS Digicel" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="363" mnc="20" carrier="Aruba:Digicel:Mms:2" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="365" mnc="84" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="365" mnc="840" carrier="Anguilla:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="365" mnc="840" carrier="Anguilla:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="365" mnc="840" carrier="Anguilla:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="366" mnc="11" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="366" mnc="110" carrier="Dominica:Lime:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="366" mnc="110" carrier="Dominica:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="366" mnc="110" carrier="Dominica:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="368" mnc="01" carrier="Cubacel MMS" apn="mms" mmsc="http://mms.cubacel.cu" mmsproxy="200.13.145.52" mmsport="8080" type="mms"></apn>
+      <apn mcc="368" mnc="1" carrier="Cubacel MMS" apn="mms" mmsc="http://mms.cubacel.cu" mmsproxy="200.13.145.52" mmsport="8080" type="mms"></apn>
+      <apn mcc="370" mnc="01" carrier="Orange MMS" apn="orangeworld" mmsc="http://mms.orange.com.do/servlets/mms" mmsproxy="172.16.126.70" mmsport="8080" type="mms" user="orange" password="orange" authtype="1"></apn>
+      <apn mcc="370" mnc="1" carrier="Dominican Rep:Orange:MMS" apn="orangeworld" mmsc="http://mms.orange.com/servlets/mms" mmsproxy="172.16.126.70" mmsport="8080" type="mms" user="orange" password="orange" authtype="1" port="8080"></apn>
+      <apn mcc="370" mnc="1" carrier="Orange MMS" apn="orangeworld" mmsc="http://mms.orange.com.do/servlets/mms" mmsproxy="172.16.126.70" mmsport="8080" type="mms" user="orange" password="orange" authtype="1"></apn>
+      <apn mcc="370" mnc="02" carrier="MMS" apn="internet.ideasclaro.com.do" mmsc="http://mms.ideasclaro.com.do/mms/wapenc" type="mms"></apn>
+      <apn mcc="370" mnc="2" carrier="Dominican Republic:Claro:INTERNET" apn="internet.ideasclaro.com.do" mmsc="http://mms.ideasclaro.com.do/mms/wapenc" type="default" authtype="1"></apn>
+      <apn mcc="370" mnc="2" carrier="MMS" apn="internet.ideasclaro.com.do" mmsc="http://mms.ideasclaro.com.do/mms/wapenc" type="mms" authtype="0"></apn>
+      <apn mcc="370" mnc="04" carrier="Viva MMS" apn="mms.viva.net.do" mmsc="http://10.200.16.4/mms/wapenc" mmsproxy="192.168.16.10" mmsport="9401" type="mms" user="viva" password="viva" authtype="1"></apn>
+      <apn mcc="370" mnc="4" carrier="Dominican Rep:Viva:Internet" apn="edge.viva.net.do" mmsc="http://wap.viva.net.do/WapDeck/" type="default" user="viva" password="viva" authtype="1" proxy="192.168.16.10" port="9401"></apn>
+      <apn mcc="370" mnc="4" carrier="Dominican Rep:Viva:MMS" apn="mms.viva.net.do" mmsc="http://10.200.16.4/mms/wapenc" mmsproxy="192.168.16.10" mmsport="9401" type="mms" user="viva" password="viva" authtype="1"></apn>
+      <apn mcc="370" mnc="4" carrier="Viva MMS" apn="mms.viva.net.do" mmsc="http://10.200.16.4/mms/wapenc" mmsproxy="192.168.16.10" mmsport="9401" type="mms" user="viva" password="viva" authtype="1"></apn>
+      <apn mcc="370" mnc="020" carrier="MMS" apn="internet.ideasclaro.com.do" mmsc="http://mms.ideasclaro.com.do/mms/wapenc" type="mms"></apn>
+      <apn mcc="372" mnc="02" carrier="Haiti:Digicel:Mms" apn="wap.digicelha.com" mmsc="http://mmc.digicelhaiti.com/servlets/mms" mmsproxy="172.20.200.12" mmsport="9201" type="mms" user="wapha" password="wap01ha" authtype="1"></apn>
+      <apn mcc="372" mnc="02" carrier="Haiti:Digicel:Modem" apn="wap.digicelha.com" mmsc="http://wapdigicel.com" type="dun" user="wapha" password="wap01ha" authtype="1" proxy="172.20.200.12" port="8080"></apn>
+      <apn mcc="372" mnc="2" carrier="Haiti:Digicel:Mms" apn="wap.digicelha.com" mmsc="http://mmc.digicelhaiti.com/servlets/mms" mmsproxy="172.20.200.12" mmsport="9201" type="mms" user="wapha" password="wap01ha" authtype="1"></apn>
+      <apn mcc="372" mnc="2" carrier="Haiti:Digicel:Modem" apn="wap.digicelha.com" mmsc="http://wapdigicel.com" type="dun" user="wapha" password="wap01ha" authtype="1" proxy="172.20.200.12" port="8080"></apn>
+      <apn mcc="374" mnc="12" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="12" carrier="Trinidad And Tobago:Bmobile:Internet" apn="internet" mmsc="http://www.time4lime.com/" type="default" authtype="1"></apn>
+      <apn mcc="374" mnc="12" carrier="Trinidad And Tobago:Bmobile:MMS" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.105" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="13" carrier="MMS Trinidad" apn="wap.digiceltt.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="8080" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="374" mnc="120" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="121" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="122" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="123" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="124" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="125" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="126" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="127" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="128" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="129" carrier="Bmobile mms" apn="mms" mmsc="http://192.168.210.104/mmrelay.app" mmsproxy="192.168.210.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="374" mnc="130" carrier="MMS Trinidad" apn="wap.digiceltt.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="8080" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="374" mnc="130" carrier="Trinidad And Tobago:Digicel:Mms" apn="wap.digiceltt.com" mmsc="http://mmc.digiceltt.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="376" mnc="35" carrier="Lime Postpaid MMS" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms"></apn>
+      <apn mcc="376" mnc="350" carrier="Turks And Caicos:Lime:Mms" apn="multimedia" mmsc="http://mmsc" mmsproxy="10.20.5.34" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="376" mnc="350" carrier="Turks And Caicos:Lime:Modem" apn="internet" mmsc="http://www.time4lime.com/" type="dun" authtype="1"></apn>
+      <apn mcc="401" mnc="01" carrier="Beeline MMS" apn="mms.beeline.kz" mmsc="http://mms.beeline.kz/mms/wapenc" mmsproxy="172.27.6.93" mmsport="8080" type="mms" user="\@mms.beeline" password="beeline" authtype="1"></apn>
+      <apn mcc="401" mnc="02" carrier="Kcell MMS" apn="mms" mmsc="http://mms.kcell.kz/post" mmsproxy="195.47.255.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="401" mnc="77" carrier="Tele2 MMS" apn="mms" mmsc="http://mms.tele2.kz/mms/wapenc" mmsproxy="10.1.26.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="001" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="01" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="01" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="1" carrier="Vodafone MMS (40401)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="1" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="002" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="02" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="02" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="2" carrier="Airtel MMS (40402)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="003" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="03" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="03" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="3" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="3" carrier="Airtel MMS (40403)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="004" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="04" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="04" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="04" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="4" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="4" carrier="IDEA MMS (40404)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="005" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="05" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="05" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="5" carrier="Vodafone MMS (40405)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="5" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="006" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="06" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="007" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="07" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="07" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="07" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="7" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="7" carrier="IDEA MMS (40407)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="009" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="09" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="09" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="09" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="9" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="9" carrier="Reliance MMS (40409)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="010" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="10" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="10" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="10" carrier="Airtel MMS (40410)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="011" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="11" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="11" carrier="Vodafone MMS (40411)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="11" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="11" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="012" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="12" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="12" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="12" carrier="IDEA MMS (40412)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="12" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="12" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="013" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="13" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="13" carrier="Vodafone MMS (40413)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="13" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="13" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="014" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="14" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.11.12.180" mmsproxy="10.11.12.13" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="14" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.11.12.180" mmsproxy="10.11.12.13" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="14" carrier="IDEA Punjab MMS (40414)" apn="mmsc" mmsc="http://10.11.12.180" mmsproxy="10.11.12.13" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="14" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="14" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="015" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="15" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="15" carrier="Vodafone MMS (40415)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="15" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="15" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="016" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="16" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="16" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="16" carrier="Airtel MMS (40416)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="017" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="17" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="17" carrier="Aircel MMS (40417)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="17" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="17" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="018" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="18" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="18" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="18" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="18" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="18" carrier="Reliance MMS (40418)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="019" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="19" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="19" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="19" carrier="IDEA MMS (40419)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="19" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="19" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="020" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="20" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="20" carrier="Vodafone MMS (40420)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="20" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="20" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="21" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="404" mnc="21" carrier="Loop MMS (40421)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="21" carrier="Loop Mobile MMS" apn="mizone" mmsc="http://mms.loopmobile.in:8080" mmsproxy="10.0.0.10" mmsport="9401" type="mms" password="mmsc"></apn>
+      <apn mcc="404" mnc="21" carrier="Loop Mobile MMS" apn="mizone" mmsc="http://mms.loopmobile.in:8080" mmsproxy="10.0.0.10" mmsport="9401" type="mms" password="mmsc" authtype="0"></apn>
+      <apn mcc="404" mnc="022" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="22" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="22" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="22" carrier="IDEA MMS (40422)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="22" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="22" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="024" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="24" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="24" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="24" carrier="IDEA MMS (40424)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="24" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="24" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="025" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="25" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="25" carrier="Aircel MMS (40425)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="25" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="25" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="027" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="27" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="27" carrier="Vodafone MMS (40427)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="27" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="27" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="028" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="28" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="28" carrier="Aircel MMS (40428)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="28" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="28" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="029" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="29" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="29" carrier="Aircel MMS (40429)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="29" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="29" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="030" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="30" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="30" carrier="Vodafone MMS (40430)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="30" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="30" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="031" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="31" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="31" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="31" carrier="Airtel MMS (40431)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="033" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="33" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="33" carrier="Aircel MMS (40433)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="33" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="33" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="034" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="34" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="34" carrier="BSNL MMS (40434)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="34" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="34" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="035" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="35" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="35" carrier="Aircel MMS (40435)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="35" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="35" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="036" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="36" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="36" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="36" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="36" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="36" carrier="Reliance MMS (40436)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="037" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="37" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="37" carrier="Aircel MMS (40437)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="37" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="37" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="038" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="38" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="38" carrier="BSNL MMS (40438)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="38" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="38" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="040" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="40" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="40" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="40" carrier="Airtel MMS (40440)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="041" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel MMS (40441)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel MMS (40441)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel-MMS-Postpaid" apn="aircelmms.po" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel-MMS-Postpaid" apn="aircelmms.po" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel-MMS-Prepaid" apn="aircelmms.pr" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="404" mnc="41" carrier="Aircel-MMS-Prepaid" apn="aircelmms.pr" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="042" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel MMS (40442)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel-MMS-Postpaid" apn="aircelmms.po" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel-MMS-Postpaid" apn="aircelmms.po" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel-MMS-Prepaid" apn="aircelmms.pr" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="404" mnc="42" carrier="Aircel-MMS-Prepaid" apn="aircelmms.pr" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="043" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="43" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="43" carrier="Vodafone MMS (40443)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="43" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="43" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="044" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="44" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="44" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="44" carrier="IDEA MMS (40444)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="44" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="045" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="45" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="45" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="45" carrier="Airtel MMS (40445)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="046" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="46" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="46" carrier="Vodafone MMS (40446)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="46" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="46" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="049" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="49" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="49" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="49" carrier="Airtel MMS (40449)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="050" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="50" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="50" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="50" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="50" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="50" carrier="Reliance MMS (40450)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="051" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="51" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="51" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="052" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="52" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="52" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="52" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="52" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="52" carrier="Reliance MMS (40452)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="053" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="53" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="53" carrier="BSNL MMS (40453)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="53" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="53" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="054" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="54" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="54" carrier="BSNL MMS (40454)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="54" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="54" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="055" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="55" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="55" carrier="BSNL MMS (40455)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="55" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="55" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="056" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="56" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="56" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="56" carrier="IDEA MMS (40456)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="56" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="56" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="057" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="57" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="57" carrier="BSNL MMS (40457)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="57" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="57" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="058" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="58" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="58" carrier="BSNL MMS (40458)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="58" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="58" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="059" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="59" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="59" carrier="BSNL MMS (40459)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="59" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="59" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="060" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="60" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="60" carrier="Vodafone MMS (40460)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="60" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="60" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="062" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="62" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="62" carrier="BSNL MMS (40462)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="62" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="62" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="064" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="64" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="64" carrier="BSNL MMS (40464)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="64" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="64" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="066" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="66" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="66" carrier="BSNL MMS (40466)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="66" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="66" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="067" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="67" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="67" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="67" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="67" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="67" carrier="Reliance MMS (40467)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="068" carrier="MTNL MMS" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="68" carrier="Dolphin_Delhi MMS" apn="gprsmtnldel" mmsc="http://172.16.31.136/mms/" mmsproxy="172.16.31.10" mmsport="80" type="mms" user="mtnl" password="mtnl123"></apn>
+      <apn mcc="404" mnc="68" carrier="Dolphin_Delhi MMS" apn="gprsmtnldel" mmsc="http://172.16.31.136/mms/" mmsproxy="172.16.31.10" mmsport="80" type="mms" user="mtnl" password="mtnl123" authtype="3"></apn>
+      <apn mcc="404" mnc="68" carrier="Dolphin_Delhi_3G MMS" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.31.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123"></apn>
+      <apn mcc="404" mnc="68" carrier="Dolphin_Delhi_3G MMS" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.31.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123" authtype="3"></apn>
+      <apn mcc="404" mnc="68" carrier="MTNL" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="default,mms,supl,agps,fota,dun" user="mtnl" password="mtnl123" authtype="0"></apn>
+      <apn mcc="404" mnc="68" carrier="MTNL Delhi MMS (40468)" apn="gprsmtnldel" mmsc="http://172.16.31.136/mms/" mmsproxy="172.16.31.10" mmsport="8080" type="mms" user="mtnl" password="mtnl123" authtype="1" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="68" carrier="MTNL MMS" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="68" carrier="MTNL MMS (40468)" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.31.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123" authtype="1" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="069" carrier="MTNL MMS" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="69" carrier="Dolphin_Mumbai MMS" apn="gprsmtnlmum" mmsc="http://172.16.39.140/mms/" mmsproxy="172.16.39.10" mmsport="80" type="mms" user="mtnl" password="mtnl123"></apn>
+      <apn mcc="404" mnc="69" carrier="Dolphin_Mumbai MMS" apn="gprsmtnlmum" mmsc="http://172.16.39.140/mms/" mmsproxy="172.16.39.10" mmsport="80" type="mms" user="mtnl" password="mtnl123" authtype="3"></apn>
+      <apn mcc="404" mnc="69" carrier="Dolphin_Mumbai_3G MMS" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.39.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123"></apn>
+      <apn mcc="404" mnc="69" carrier="Dolphin_Mumbai_3G MMS" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.39.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123" authtype="3"></apn>
+      <apn mcc="404" mnc="69" carrier="MTNL" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="default,mms,supl,agps,fota,dun" user="mtnl" password="mtnl123" authtype="0" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="404" mnc="69" carrier="MTNL MMS" apn="mtnl.net" mmsc="http://mtnlmms/" mmsproxy="10.10.10.10" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="69" carrier="MTNL MMS (40469)" apn="mtnl3g" mmsc="http://172.16.31.165/mms/" mmsproxy="172.16.39.10" mmsport="9401" type="mms" user="mtnl" password="mtnl123" authtype="1" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="69" carrier="MTNL Mumbai MMS" apn="gprsmtnlmum" mmsc="http://172.16.39.140/mms/" mmsproxy="172.16.39.10" mmsport="8080" type="mms" user="mtnl" password="mtnl123" authtype="1" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="070" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="70" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="70" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="70" carrier="Airtel MMS (40470)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="071" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="71" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="71" carrier="BSNL MMS (40471)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="71" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="71" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="072" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="72" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="72" carrier="BSNL MMS (40472)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="72" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="72" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="073" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="73" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="73" carrier="BSNL MMS (40473)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="73" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="73" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="074" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="74" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="74" carrier="BSNL MMS (40474)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="74" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="74" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="075" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="75" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="75" carrier="BSNL MMS (40475)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="75" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="75" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="076" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="76" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="76" carrier="BSNL MMS (40476)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="76" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="76" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="077" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="77" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="77" carrier="BSNL MMS (40477)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="77" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="77" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="078" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="78" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="78" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="78" carrier="IDEA MMS (40478)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="78" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="78" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="079" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="79" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="79" carrier="BSNL MMS (40479)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="79" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="79" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="080" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="80" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="80" carrier="BSNL MMS (40480)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="80" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="80" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="081" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="81" carrier="BSNL MMS" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="81" carrier="BSNL MMS (40481)" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="81" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="81" carrier="bsnlmms" apn="bsnlmms" mmsc="http://bsnlmmsc.in:8514" mmsproxy="10.210.10.11" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="082" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="82" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="82" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="82" carrier="IDEA MMS (40482)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="82" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="82" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="083" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="83" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="83" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="83" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="83" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="83" carrier="Reliance MMS (40483)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="084" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="84" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="84" carrier="Vodafone MMS (40484)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="84" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="84" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="085" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="85" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="85" carrier="Reliance MMS" apn="mms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="85" carrier="Reliance MMS" apn="mms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.7" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="85" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="85" carrier="Reliance MMS (40485)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="086" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="86" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="86" carrier="Vodafone MMS (40486)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="86" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="86" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="087" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="87" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="87" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="87" carrier="IDEA MMS (40487)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="87" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="87" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="088" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="88" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="88" carrier="Vodafone MMS (40488)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="88" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="404" mnc="88" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="089" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="89" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="89" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="89" carrier="IDEA MMS (40489)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="89" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="89" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="404" mnc="090" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="90" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="90" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="90" carrier="Airtel MMS (40490)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="091" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="91" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="91" carrier="Aircel MMS (40491)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="91" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="404" mnc="91" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="404" mnc="092" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="92" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="92" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="92" carrier="Airtel MMS (40492)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="093" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="93" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="93" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="93" carrier="Airtel MMS (40493)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="094" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="94" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="94" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="94" carrier="Airtel MMS (40494)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="095" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="95" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="95" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="95" carrier="Airtel MMS (40495)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="096" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="96" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="96" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="96" carrier="Airtel MMS (40496)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="097" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="97" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="97" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="97" carrier="Airtel MMS (40497)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="404" mnc="098" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="98" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="404" mnc="98" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="404" mnc="98" carrier="Airtel MMS (40498)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="001" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="01" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="1" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="1" carrier="Reliance MMS (40501)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="03" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="3" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="3" carrier="Reliance MMS (40503)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="04" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="4" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="4" carrier="Reliance MMS (40504)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="005" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="05" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="5" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="5" carrier="Reliance MMS (40505)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="006" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="06" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="6" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="6" carrier="Reliance MMS (40506)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="007" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="07" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="7" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="7" carrier="Reliance MMS (40507)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="08" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="8" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="8" carrier="Reliance MMS (40508)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="009" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="09" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="9" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="9" carrier="Reliance MMS (40509)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="010" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="10" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="10" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="10" carrier="Reliance MMS (40510)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="011" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="11" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="11" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="11" carrier="Reliance MMS (40511)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="12" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="12" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="12" carrier="Reliance MMS (40512)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="013" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="13" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="13" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="13" carrier="Reliance MMS (40513)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="14" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="14" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="14" carrier="Reliance MMS (40514)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="015" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="15" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="15" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="15" carrier="Reliance MMS (40515)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="17" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="17" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="17" carrier="Reliance MMS (40517)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="018" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="18" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="18" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="18" carrier="Reliance MMS (40518)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="019" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="19" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="19" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="19" carrier="Reliance MMS (40519)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="020" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="20" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="20" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="20" carrier="Reliance MMS (40520)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="021" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="21" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="21" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="21" carrier="Reliance MMS (40521)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="022" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="22" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="22" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="22" carrier="Reliance MMS (40522)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="23" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="23" carrier="Reliance MMS" apn="rcommms" mmsc="http://mmsc.rcom.co.in/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="23" carrier="Reliance MMS (40523)" apn="rcommms" mmsc="http://10.239.221.47/mms/" mmsproxy="10.239.221.5" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="025" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="25" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="25" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="25" carrier="TATA DOCOMO MMS (40525)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="026" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="26" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="26" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="26" carrier="TATA DOCOMO MMS (40526)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="027" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="27" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="27" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="27" carrier="TATA DOCOMO MMS (40527)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="028" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="28" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="28" carrier="TATA DOCOMO MMS (40528)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="029" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="29" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="29" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="29" carrier="TATA DOCOMO MMS (40529)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="030" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="30" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="30" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="30" carrier="TATA DOCOMO MMS (40530)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="031" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="31" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="31" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="31" carrier="TATA DOCOMO MMS (40531)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="032" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="32" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="32" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="32" carrier="TATA DOCOMO MMS (40532)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="033" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="33" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="33" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="33" carrier="TATA DOCOMO MMS (40533)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="405" mnc="034" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="34" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="34" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="34" carrier="TATA DOCOMO MMS (40534)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="035" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="35" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="35" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="35" carrier="TATA DOCOMO MMS (40535)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="036" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="36" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="36" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="36" carrier="TATA DOCOMO MMS (40536)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="037" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="37" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="37" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="37" carrier="TATA DOCOMO MMS (40537)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="038" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="38" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="38" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="38" carrier="TATA DOCOMO MMS (405238" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="039" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="39" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="39" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="39" carrier="TATA DOCOMO MMS (40539)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="040" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="40" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="40" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="40" carrier="TATA DOCOMO MMS (40540)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="405" mnc="041" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="41" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="41" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="41" carrier="TATA DOCOMO MMS (40541)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="042" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="42" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="42" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="42" carrier="TATA DOCOMO MMS (40542)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="043" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="43" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="43" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="43" carrier="TATA DOCOMO MMS (40543)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="044" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="44" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="44" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="44" carrier="TATA DOCOMO MMS (40544)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="045" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="45" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="45" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="45" carrier="TATA DOCOMO MMS (40545)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="046" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="46" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="46" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="46" carrier="TATA DOCOMO MMS (40546)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="047" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="47" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="47" carrier="TATA DOCOMO MMS" apn="TATA.DOCOMO.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="47" carrier="TATA DOCOMO MMS (40547)" apn="Tata.Docomo.MMS" mmsc="http://mmsc/" mmsproxy="10.124.26.94" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="051" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="51" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="51" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="51" carrier="Airtel MMS (40551)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="052" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="52" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="52" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="52" carrier="Airtel MMS (40552)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="053" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="53" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="53" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="53" carrier="Airtel MMS (40553)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="054" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="54" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="54" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="54" carrier="Airtel MMS (40554)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="055" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="55" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="55" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="55" carrier="Airtel MMS (40555)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="056" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="56" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="405" mnc="56" carrier="Airtel MMS" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc/" mmsproxy="100.1.201.172" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="56" carrier="Airtel MMS (40556)" apn="airtelmms.com" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="066" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="66" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="66" carrier="Vodafone MMS (40566)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="66" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="66" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="067" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="67" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="67" carrier="Vodafone MMS (40567)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="67" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="67" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="070" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="70" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="70" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="70" carrier="IDEA MMS (40570)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="70" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="70" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="750" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="750" carrier="Vodafone MMS (405750)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="750" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="750" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="751" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="751" carrier="Vodafone MMS (405751)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="751" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="751" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="752" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="752" carrier="Vodafone MMS (405752)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="752" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="752" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="753" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="753" carrier="Vodafone MMS (405753)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="753" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="753" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="754" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="754" carrier="Vodafone MMS (405754)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="754" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="754" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="755" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="755" carrier="Vodafone MMS (405755)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="755" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="755" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="756" carrier="Vodafone MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="756" carrier="Vodafone MMS (405756)" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="756" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms"></apn>
+      <apn mcc="405" mnc="756" carrier="Vodafone_MMS" apn="portalnmms" mmsc="http://mms1.live.vodafone.in/mms/" mmsproxy="10.10.1.100" mmsport="9401" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="799" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="799" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="799" carrier="IDEA MMS (405799)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="799" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="799" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="800" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="800" carrier="Aircel MMS (405800)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="800" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="800" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="801" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="801" carrier="Aircel MMS (405801)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="801" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="405" mnc="801" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="802" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="802" carrier="Aircel MMS (405802)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="802" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="802" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="803" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="803" carrier="Aircel MMS (405803)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="803" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="405" mnc="803" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="804" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="804" carrier="Aircel MMS (405804)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="804" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="804" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="805" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="805" carrier="Aircel MMS (405805)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="805" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="805" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="806" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="806" carrier="Aircel MMS (405806)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="806" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="806" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="807" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="807" carrier="Aircel MMS (405807)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="807" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="807" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="808" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="808" carrier="Aircel MMS (405808)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="808" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="808" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="809" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="809" carrier="Aircel MMS (405809)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="809" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms"></apn>
+      <apn mcc="405" mnc="809" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://mmsc/mmrelay.app" mmsproxy="192.168.35.196" mmsport="8081" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="810" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="810" carrier="Aircel MMS (405810)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="810" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="810" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="811" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="811" carrier="Aircel MMS (405811)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="811" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="811" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="812" carrier="Aircel MMS" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.017.083.069" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="812" carrier="Aircel MMS (405812)" apn="aircelmms" mmsc="http://172.17.83.67/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="812" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="812" carrier="Aircel-MMS" apn="aircelmms" mmsc="http://10.50.1.166/servlets/mms" mmsproxy="172.17.83.69" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="813" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="813" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="814" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="814" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="815" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="815" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="816" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="816" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="817" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="817" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="818" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="818" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="819" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="819" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="820" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="820" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="821" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="821" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="822" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="822" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="823" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="823" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="823" carrier="Videocon MMS (405823)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="824" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="824" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="824" carrier="Videocon MMS (405824)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="825" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="825" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="825" carrier="Videocon MMS (405825)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="826" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="826" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="826" carrier="Videocon MMS (405826)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="827" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="827" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="827" carrier="Videocon MMS (405827)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="828" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="828" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="828" carrier="Videocon MMS (405828)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="829" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="829" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="829" carrier="Videocon MMS (405829)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="830" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="830" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="830" carrier="Videocon MMS (405830)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="831" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="831" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="831" carrier="Videocon MMS (405831)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="832" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="832" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="832" carrier="Videocon MMS (405832)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="833" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="833" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="833" carrier="Videocon MMS (405833)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="834" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="834" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="834" carrier="Videocon MMS (405834)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="835" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="835" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="835" carrier="Videocon MMS (405835)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="836" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="836" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="836" carrier="Videocon MMS (405836)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="837" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="837" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="837" carrier="Videocon MMS (405837)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="838" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="838" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="838" carrier="Videocon MMS (405838)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="839" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="839" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="839" carrier="Videocon MMS (405839)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="840" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="840" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="840" carrier="Videocon MMS (405840)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="841" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="841" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="841" carrier="Videocon MMS (405841)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="842" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="842" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="842" carrier="Videocon MMS (405842)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="843" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="843" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="843" carrier="Videocon MMS (405843)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="844" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="844" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="845" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="845" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="845" carrier="IDEA MMS (405845)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="845" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="845" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="846" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="846" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="846" carrier="IDEA MMS (405846)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="846" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="846" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="847" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="848" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="848" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="848" carrier="IDEA MMS (405848)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="848" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="848" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="849" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="849" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="849" carrier="IDEA MMS (405849)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="849" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="849" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="850" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="850" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="850" carrier="IDEA MMS (405850)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="850" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="850" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="851" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="852" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="852" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="852" carrier="IDEA MMS (405852)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="852" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="852" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="853" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="853" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="853" carrier="IDEA MMS (405853)" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="853" carrier="Idea MMS" apn="mmsc" mmsc="http://10.4.42.21:8002" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="853" carrier="Idea-MMS_Karnatak" apn="spicemms" mmsc="http://10.200.200.3:8514" proxy="10.200.200.3" port="8080"></apn>
+      <apn mcc="405" mnc="854" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="854" carrier="Loop MMS (405854)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="854" carrier="Loop MMS (405854)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="855" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="855" carrier="Loop MMS (405855)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="855" carrier="Loop MMS (405855)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="856" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="856" carrier="Loop MMS (405856)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="856" carrier="Loop MMS (405856)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="857" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="857" carrier="Loop MMS (405857)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="857" carrier="Loop MMS (405857)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="858" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="858" carrier="Loop MMS (405858)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="858" carrier="Loop MMS (405858)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="859" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="859" carrier="Loop MMS (405859)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="859" carrier="Loop MMS (405859)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="860" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="860" carrier="Loop MMS (405860)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="860" carrier="Loop MMS (405860)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="861" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="861" carrier="Loop MMS (405861)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="861" carrier="Loop MMS (405861)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="862" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="862" carrier="Loop MMS (405862)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="862" carrier="Loop MMS (405862)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="863" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="863" carrier="Loop MMS (405863)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="863" carrier="Loop MMS (405863)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="864" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="864" carrier="Loop MMS (405864)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="864" carrier="Loop MMS (405864)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="865" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="865" carrier="Loop MMS (405865)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="865" carrier="Loop MMS (405865)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="866" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="866" carrier="Loop MMS (405866)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="866" carrier="Loop MMS (405866)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="867" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="867" carrier="Loop MMS (405867)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="867" carrier="Loop MMS (405867)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="868" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="868" carrier="Loop MMS (405868)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="868" carrier="Loop MMS (405868)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="869" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="869" carrier="Loop MMS (405869)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="869" carrier="Loop MMS (405869)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="870" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="870" carrier="Loop MMS (405870)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="870" carrier="Loop MMS (405870)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="871" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="871" carrier="Loop MMS (405871)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="871" carrier="Loop MMS (405871)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="872" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="872" carrier="Loop MMS (405872)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="872" carrier="Loop MMS (405872)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="873" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="873" carrier="Loop MMS (405873)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="873" carrier="Loop MMS (405873)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="874" carrier="BPL MMS" apn="mizone" mmsc="http://mms.bplmobile.com:8080 " mmsproxy="010.000.000.010 " mmsport="9401"></apn>
+      <apn mcc="405" mnc="874" carrier="Loop MMS (405874)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="405" mnc="874" carrier="Loop MMS (405874)" apn="mizone" mmsc="http://mms.loopmobile.in:8080/" mmsproxy="10.0.0.10" mmsport="9401" type="mms" protocol="IP" roaming_protocol="IP" carrier_enabled="true"></apn>
+      <apn mcc="405" mnc="875" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="875" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="876" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="876" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="877" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="877" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="878" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="878" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="879" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="879" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="880" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="880" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="908" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="909" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="910" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="911" carrier="IDEA MMS" apn="mmsc" mmsc="http://10.4.42.21:8002/" mmsproxy="10.4.42.15" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="925" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="925" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="926" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="926" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="927" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="927" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="928" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="928" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="929" carrier="UNINOR MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.2.101" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="929" carrier="Uninor MMS" apn="uninor" mmsc="http://10.58.2.120" mmsproxy="10.58.10.59" mmsport="8080" type="mms"></apn>
+      <apn mcc="405" mnc="932" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms"></apn>
+      <apn mcc="405" mnc="932" carrier="Videocon MMS" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="405" mnc="932" carrier="Videocon MMS (405932)" apn="vgprs.com" mmsc="http://10.202.4.119:10021/mmsc/" mmsproxy="10.202.5.145" mmsport="8799" type="mms" authtype="0" protocol="IP" roaming_protocol="IP" carrier_enabled="TRUE"></apn>
+      <apn mcc="410" mnc="01" carrier="Mobilink MMS" apn="mms.mobilinkworld.com" mmsc="http://mms/" mmsproxy="172.25.20.12" mmsport="8080" type="mms" user="Mobilink" password="Mobilink"></apn>
+      <apn mcc="410" mnc="1" carrier="Mobilink MMS" apn="mms.mobilinkworld.com" mmsc="http://mms/" mmsproxy="172.25.20.12" mmsport="8080" type="mms" user="Mobilink" password="Mobilink" authtype="3"></apn>
+      <apn mcc="410" mnc="1" carrier="Mobilink MMS" apn="mms.mobilinkworld.com" mmsc="http://mms/" mmsproxy="172.25.20.12" mmsport="8080" type="mms" user="mobilink" password="mobilink" authtype="0"></apn>
+      <apn mcc="410" mnc="03" carrier="Ufone MMS" apn="Ufone.mms" mmsc="http://www.ufonemms.com:80/" mmsproxy="172.16.13.27" mmsport="8080" type="mms"></apn>
+      <apn mcc="410" mnc="3" carrier="Ufone MMS" apn="Ufone.mms" mmsc="http://www.ufonemms.com:80/" mmsproxy="172.16.13.27" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="410" mnc="3" carrier="Ufone MMS" apn="ufone.mms" mmsc="http://www.ufonemms.com:80/" mmsproxy="172.16.13.27" mmsport="9201" type="mms" user="ufone" password="ufone" authtype="0"></apn>
+      <apn mcc="410" mnc="04" carrier="ZONG MMS" apn="zongmms" mmsc="http://10.81.6.11:8080" mmsproxy="10.81.6.33" mmsport="8000" type="mms"></apn>
+      <apn mcc="410" mnc="4" carrier="Warid MMS" apn="mms.warid" mmsc="http://10.4.0.132/servlets/mms" mmsproxy="10.4.2.1" mmsport="9201" type="mms" authtype="0"></apn>
+      <apn mcc="410" mnc="4" carrier="ZONG MMS" apn="zongmms" mmsc="http://10.81.6.11:8080" mmsproxy="10.81.6.33" mmsport="8000" type="mms" authtype="0"></apn>
+      <apn mcc="410" mnc="06" carrier="Telenor MMS" apn="mms" mmsc="http://mmstelenor" mmsproxy="172.18.19.11" mmsport="8080" type="mms" user="Telenor" password="Telenor"></apn>
+      <apn mcc="410" mnc="6" carrier="Telenor MMS" apn="mms" mmsc="http://mmstelenor" mmsproxy="172.18.19.11" mmsport="8080" type="mms" user="Telenor" password="Telenor" authtype="3"></apn>
+      <apn mcc="410" mnc="6" carrier="Telenor MMS (410.06)" apn="mms" mmsc="http://mmstelenor" mmsproxy="172.18.19.11" mmsport="8080" type="mms" user="Telenor" password="Telenor" authtype="0"></apn>
+      <apn mcc="410" mnc="07" carrier="Warid MMS" apn="mms.warid" mmsc="http://10.4.0.132/servlets/MMS" mmsproxy="10.4.2.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="410" mnc="7" carrier="Warid MMS" apn="mms.warid" mmsc="http://10.4.0.132/servlets/MMS" mmsproxy="10.4.2.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="410" mnc="310" carrier="Consumer Cellular" apn="att.mvno" mmsc="http://mms.fido.ca" mmsproxy="mmsproxy.fido.ca" mmsport="80" type="default,mms,supl,hipri,fota" mvno_match_data="2AC9" mvno_type="gid" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="413" mnc="01" carrier="Mobitel MMS" apn="wapmms" mmsc="http://192.168.050.165" mmsproxy="192.168.050.163" mmsport="8080" type="mms"></apn>
+      <apn mcc="413" mnc="03" carrier="Etisalat MMS" apn="mms" mmsc="http://mms.etisalat.lk:8085" mmsproxy="192.168.104.004" mmsport="9401" type="mms"></apn>
+      <apn mcc="413" mnc="05" carrier="Airtel MMS SL" apn="AirtelLive" mmsc="http://mms.Airtel.lk" mmsproxy="10.200.184.086" mmsport="8080" type="mms"></apn>
+      <apn mcc="415" mnc="01" carrier="Alfa MMS" apn="mms.mic1.com.lb" mmsc="http://mms.mic1.com.lb" mmsproxy="192.168.23.51" mmsport="8080" type="mms" user="mic1" password="mic1"></apn>
+      <apn mcc="415" mnc="1" carrier="Alfa MMS" apn="mms.mic1.com.lb" mmsc="http://mms.mic1.com.lb" mmsproxy="192.168.23.51" mmsport="8080" type="mms" user="mic1" password="mic1" authtype="0"></apn>
+      <apn mcc="415" mnc="1" carrier="Alfa MMS" apn="mms.mic1.com.lb" mmsc="http://mms.mic1.com.lb" mmsproxy="192.168.23.51" mmsport="8080" type="mms" user="mic1" password="mic1" authtype="3"></apn>
+      <apn mcc="415" mnc="03" carrier="touch_MMS" apn="mms" mmsc="http://mms:8088/mms/" mmsproxy="192.168.4.103" mmsport="80" type="mms" user="touch"></apn>
+      <apn mcc="415" mnc="3" carrier="MTC touch MMS" apn="mms.mtctouch.com.lb" mmsc="http://mms:8088/mms/" mmsproxy="192.168.4.103" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="415" mnc="3" carrier="touch_MMS" apn="mms" mmsc="http://mms:8088/mms/" mmsproxy="192.168.4.103" mmsport="80" type="mms" user="touch" authtype="3"></apn>
+      <apn mcc="416" mnc="01" carrier="Zain JO MMS" apn="zain" mmsc="http://mms.jo.zain.com" mmsproxy="192.168.55.10" mmsport="80" type="mms" user="zain" password="zain" authtype="1"></apn>
+      <apn mcc="416" mnc="1" carrier="zain JO mms" apn="zain" mmsc="http://mms.jo.zain.com" mmsproxy="192.168.55.10" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="416" mnc="1" carrier="zain JO mms" apn="zain" mmsc="http://mms.jo.zain.com" mmsproxy="192.168.55.10" mmsport="80" type="mms" user="zain" password="zain" authtype="1"></apn>
+      <apn mcc="416" mnc="03" carrier="Umniah MMS" apn="mms" mmsc="http://mms.umniah.com/" mmsproxy="10.1.1.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="416" mnc="3" carrier="UMNIAH mms" apn="mms" mmsc="http://mms.umniah.com/" mmsproxy="10.1.1.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="416" mnc="3" carrier="UMNIAH mms" apn="mms" mmsc="http://mms.umniah.com/" mmsproxy="10.1.1.10" mmsport="8080" type="mms" authtype="0" server="http://mms.umniah.com/"></apn>
+      <apn mcc="416" mnc="77" carrier="Orange JO MMS" apn="mms.orange.jo" mmsc="http://172.16.1.96/servlets/mms" mmsproxy="172.16.1.2" mmsport="8080" type="mms" user="mmc" password="mmc" authtype="1" server="http://172.16.1.96/servlets/mms" proxy="172.16.1.2" port="8080"></apn>
+      <apn mcc="416" mnc="77" carrier="Orange MMS" apn="mms.orange.jo" mmsc="http://172.16.1.96/servlets/mms" mmsproxy="172.16.1.2" mmsport="8080" type="mms" user="mmc" password="mmc" authtype="1"></apn>
+      <apn mcc="416" mnc="770" carrier="Orange JO MMS" apn="mms.orange.jo" mmsc="http://172.16.1.96/servlets/mms" mmsproxy="172.16.1.2" mmsport="8080" type="mms" user="mmc" password="mmc" authtype="1" server="http://172.16.1.96/servlets/mms" proxy="172.16.1.2" port="8080"></apn>
+      <apn mcc="416" mnc="770" carrier="Orange MMS" apn="mms.orange.jo" mmsc="http://172.16.1.96/servlets/mms" mmsproxy="172.16.1.2" mmsport="8080" type="mms" user="mmc" password="mmc" authtype="1"></apn>
+      <apn mcc="417" mnc="01" carrier="Syriatel MMS" apn="mms.syriatel.com" mmsc="http://mymms.syriatel.com/" mmsproxy="172.20.5.6" mmsport="80" type="mms"></apn>
+      <apn mcc="417" mnc="02" carrier="MTN MMS" apn="mms" mmsc="http://mms/" mmsproxy="10.110.0.134" mmsport="8799" type="mms"></apn>
+      <apn mcc="418" mnc="05" carrier="Asiacell MMS" apn="wap.asiacell.com" mmsc="http://192.168.107.10:19090/was" mmsproxy="192.168.107.50" mmsport="8080" type="mms"></apn>
+      <apn mcc="418" mnc="5" carrier="Asiacell MMS" apn="wap.asiacell.com" mmsc="http://192.168.107.10:19090/was" mmsproxy="192.168.107.50" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="418" mnc="20" carrier="Zain-MMS" apn="MMS" mmsc="http://mms:8002/" mmsproxy="172.29.11.12" mmsport="8080" type="mms" user="atheer" password="atheer" authtype="1"></apn>
+      <apn mcc="418" mnc="30" carrier="Zain-MMS" apn="MMS" mmsc="http://mms:8002/" mmsproxy="172.29.11.12" mmsport="8080" type="mms" user="atheer" password="atheer" authtype="1"></apn>
+      <apn mcc="418" mnc="40" carrier="KOREK MMS" apn="mms.korek.com" mmsc="http://mms.korektel.com/mms/wapenc" mmsproxy="192.168.18.187" mmsport="8080" type="mms" user="korek" password="korek" authtype="1"></apn>
+      <apn mcc="419" mnc="02" carrier="MMS" apn="pps" mmsc="http://mms.zain" mmsproxy="176.0.0.65" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="419" mnc="2" carrier="MMS" apn="pps" mmsc="http://mms.zain" mmsproxy="176.0.0.65" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="419" mnc="2" carrier="Zain KW MMS" apn="pps" mmsc="http://176.0.0.21" mmsproxy="176.0.0.65" mmsport="8080" type="mms" user="annyway" password="online" authtype="0"></apn>
+      <apn mcc="419" mnc="03" carrier="Wataniya MMS" apn="mms.wataniya.com" mmsc="http://action.wataniya.com" mmsproxy="194.126.53.64" mmsport="8080" type="mms"></apn>
+      <apn mcc="419" mnc="03" carrier="Wataniya MMS" apn="mms.wataniya.com" mmsc="http://action.wataniya.com" mmsproxy="194.126.53.64" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="419" mnc="3" carrier="KT WATANIYA mms" apn="mms.wataniya.com" mmsc="http://action.wataniya.com" mmsproxy="194.126.53.64" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="419" mnc="3" carrier="Wataniya MMS" apn="mms.wataniya.com" mmsc="http://action.wataniya.com" mmsproxy="194.126.53.64" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="419" mnc="04" carrier="VIVA - KW" apn="viva" mmsc="http://172.16.128.80:38090/was" mmsproxy="172.16.128.228" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="419" mnc="04" carrier="VIVA MMS" apn="VIVA" mmsc="http://172.16.128.80:38090/was" mmsproxy="172.16.128.228" mmsport="8080" type="mms"></apn>
+      <apn mcc="419" mnc="4" carrier="VIVA - KW" apn="viva" mmsc="http://172.16.128.80:38090/was" mmsproxy="172.16.128.228" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="419" mnc="4" carrier="VIVA MMS" apn="VIVA" mmsc="http://172.16.128.80:38090/was" mmsproxy="172.16.128.228" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="01" carrier="STC MMS" apn="mms.net.sa" mmsc="http://mms.net.sa:8002/" mmsproxy="10.1.1.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="420" mnc="1" carrier="STC MMS" apn="mms.net.sa" mmsc="http://mms.net.sa:8002/" mmsproxy="10.1.1.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="1" carrier="STC mms" apn="mms.net.sa" mmsc="http://mms.net.sa:8002" mmsproxy="10.1.1.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="03" carrier="Mobily MMS Postpaid" apn="mms1" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms"></apn>
+      <apn mcc="420" mnc="03" carrier="Mobily MMS Prepaid" apn="mms2" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms"></apn>
+      <apn mcc="420" mnc="3" carrier="Mobily MMS Postpaid" apn="mms1" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="3" carrier="Mobily MMS Prepaid" apn="mms2" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="3" carrier="mobily-KSA mms" apn="mms1" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="3" carrier="mobily-KSA mms pre-paid" apn="mms2" mmsc="http://10.3.3.133:9090/was" mmsproxy="10.3.2.133" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="420" mnc="04" carrier="zain-mms" apn="zain" mmsc="http://10.122.200.12:8002" mmsproxy="10.122.200.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="420" mnc="04" carrier="zain-mms" apn="zainmms" mmsc="http://10.122.200.12:8002" mmsproxy="10.122.200.10" mmsport="8080" type="mms" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="420" mnc="4" carrier="Zain SA" apn="zain" mmsc="http://10.122.200.12:8002/" mmsproxy="10.122.200.10" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="420" mnc="4" carrier="zain-mms" apn="zain" mmsc="http://10.122.200.12:8002" mmsproxy="10.122.200.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="421" mnc="01" carrier="Sabafon MMS" apn="mms" mmsc="http://mms.sabafon.com/" mmsproxy="192.168.30.174" mmsport="8080" type="mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="421" mnc="1" carrier="Sabafon MMS" apn="mms" mmsc="http://mms.sabafon.com/" mmsproxy="192.168.30.174" mmsport="8080" type="mms" user="wap" password="wap" authtype="0"></apn>
+      <apn mcc="421" mnc="02" carrier="MTN MMS YE" apn="fast-mms" mmsc="http://192.168.97.1/mmsc" mmsproxy="192.168.97.1" mmsport="3130" type="mms" user="mms" authtype="0"></apn>
+      <apn mcc="421" mnc="2" carrier="MTN MMS YE" apn="fast-mms" mmsc="http://192.168.97.1/mmsc" mmsproxy="192.168.97.1" mmsport="3130" type="mms" user="mms" authtype="0"></apn>
+      <apn mcc="422" mnc="02" carrier="Oman Mobile MMS" apn="mms" mmsc="http://mmsc.omanmobile.om:10021/mmsc" mmsproxy="192.168.203.35" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="422" mnc="2" carrier="Oman Mobile MMS" apn="mms" mmsc="http://mmsc.omanmobile.om:10021/mmsc" mmsproxy="192.168.203.35" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="422" mnc="03" carrier="Nawras MMS" apn="mms.nawras.com.om" mmsc="http://10.128.240.16/servlets/mms" mmsproxy="10.128.240.19" mmsport="8080" type="mms" user="test" password="test" authtype="1"></apn>
+      <apn mcc="422" mnc="3" carrier="Nawras MMS" apn="mms.nawras.com.om" mmsc="http://10.128.240.16" mmsproxy="10.128.240.16" mmsport="9201" type="mms" user="test" password="test" authtype="0"></apn>
+      <apn mcc="424" mnc="02" carrier="Etisalat MMS" apn="etisalat" mmsc="http://mms/servlets/mms" mmsproxy="10.12.0.32" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="424" mnc="2" carrier="ETISALAT AE mms" apn="mms" mmsc="http://mms/servlets/mms" mmsproxy="10.12.0.30" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="424" mnc="2" carrier="Etisalat MMS" apn="etisalat" mmsc="http://mms/servlets/mms" mmsproxy="10.12.0.32" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="424" mnc="03" carrier="du MMS" apn="du" mmsc="http://mms.du.ae:8002" mmsproxy="10.19.18.4" mmsport="8080" type="mms"></apn>
+      <apn mcc="424" mnc="3" carrier="du" apn="du" mmsc="http://mms.du.ae" mmsproxy="10.19.18.4" mmsport="8080" type="default,mms" authtype="0" port="8080"></apn>
+      <apn mcc="424" mnc="3" carrier="du MMS" apn="du" mmsc="http://mms.du.ae:8002" mmsproxy="10.19.18.4" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="425" mnc="01" carrier="3G Portal" apn="uwap.orange.co.il" mmsc="http://192.168.220.15/servlets/mms" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="425" mnc="1" carrier="3G Portal" apn="uwap.orange.co.il" mmsc="http://192.168.220.15/servlets/mms" type="default,mms" authtype="0"></apn>
+      <apn mcc="425" mnc="1" carrier="3G Portal" apn="uwap.orange.co.il" mmsc="http://192.168.220.15/servlets/mms" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="425" mnc="02" carrier="Cellcom MMS" apn="mms" mmsc="http://mms.cellcom.co.il" mmsproxy="vwapm2.ain.co.il" mmsport="8080" type="mms"></apn>
+      <apn mcc="425" mnc="2" carrier="Cellcom MMS" apn="mms" mmsc="http://mms.cellcom.co.il" mmsproxy="vwapm2.ain.co.il" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="425" mnc="2" carrier="Cellcom_mms" apn="mms" mmsc="http://mms.cellcom.co.il" mmsproxy="172.31.29.38" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="425" mnc="03" carrier="Multimedia Pelephone" apn="mms.pelephone.net.il" mmsc="http://mmsu.pelephone.net.il" mmsproxy="10.170.252.104" mmsport="9093" type="mms" user="pcl@3g" password="pcl" authtype="3"></apn>
+      <apn mcc="425" mnc="3" carrier="Multimedia Pelephone" apn="mms.pelephone.net.il" mmsc="http://mmsu.pelephone.net.il" mmsproxy="10.170.9.54" mmsport="9093" type="mms" user="pcl@3g" password="pcl" authtype="0"></apn>
+      <apn mcc="425" mnc="05" carrier="Jawwal MMS" apn="mms" mmsc="http://mms.jawwal.ps/servlets/mms" mmsproxy="213.244.118.129" mmsport="8080" type="mms"></apn>
+      <apn mcc="425" mnc="5" carrier="Jawwal MMS" apn="mms" mmsc="http://mms.jawwal.ps/servlets/mms" mmsproxy="213.244.118.129" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="425" mnc="06" carrier="Wataniya_mms" apn="mms" mmsc="http://mms.wataniya.ps/servlets/mms" mmsproxy="10.100.129.111" mmsport="8080" type="mms"></apn>
+      <apn mcc="425" mnc="6" carrier="Wataniya_mms" apn="mms" mmsc="http://mms.wataniya.ps/servlets/mms" mmsproxy="10.100.129.111" mmsport="8080" type="mms"></apn>
+      <apn mcc="425" mnc="07" carrier="MMS HOT mobile" apn="mms.hotm" mmsc="http://mms.hotmobile.co.il" mmsproxy="80.246.131.99" mmsport="80" type="mms"></apn>
+      <apn mcc="425" mnc="7" carrier="MMS HOT mobile" apn="mms.hotm" mmsc="http://mms.hotmobile.co.il" mmsproxy="80.246.131.99" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="425" mnc="08" carrier="GolanTelecom MMS" apn="mms.golantelecom.net.il" mmsc="http://mmsc.golantelecom.co.il" mmsproxy="10.224.228.81" mmsport="80" type="mms"></apn>
+      <apn mcc="425" mnc="8" carrier="GolanTelecom MMS" apn="mms.golantelecom.net.il" mmsc="http://mmsc.golantelecom.co.il" mmsproxy="10.224.228.81" mmsport="80" type="mms"></apn>
+      <apn mcc="425" mnc="10" carrier="3G Portal" apn="uwap.orange.co.il" mmsc="http://192.168.220.15/servlets/mms" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="425" mnc="14" carrier="Alon Internet" apn="data.youphone.co.il" mmsc="http://192.168.220.15/servlets/mms" type="default,supl,mms"></apn>
+      <apn mcc="425" mnc="15" carrier="Home Cellular MMS" apn="hcmMMS" mmsc="http://82.166.164.229:9000/mmsc" mmsproxy="82.166.164.229" mmsport="8898" type="mms"></apn>
+      <apn mcc="425" mnc="16" carrier="Rami Levi Multimedia" apn="mms.pelephone.net.il" mmsc="http://mmsu.pelephone.net.il" mmsproxy="10.170.252.104" mmsport="9093" type="mms"></apn>
+      <apn mcc="426" mnc="01" carrier="Batelco MMS" apn="mms.batelco.com" mmsc="http://192.168.36.10/servlets/mms" mmsproxy="192.168.1.2" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="1" carrier="Batelco MMS" apn="mms.batelco.com" mmsc="http://192.168.36.10/servlets/mms" mmsproxy="192.168.1.2" type="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="1" carrier="Batelco MMS" apn="mms.batelco.com" mmsc="http://192.168.36.10/servlets/mms" mmsproxy="192.168.1.2" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="02" carrier="Zain BH MMS" apn="mms" mmsc="http://172.18.83.129:80/" mmsproxy="172.18.85.34" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="2" carrier="Zain BH MMS" apn="mms" mmsc="http://172.18.83.129" mmsproxy="172.18.85.34" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="04" carrier="VIVAMMS" apn="vivawap.bh" mmsc="http://mms.viva.com.bh:38090" mmsproxy="172.18.142.36" mmsport="8080" type="mms"></apn>
+      <apn mcc="426" mnc="4" carrier="VIVA MMS" apn="vivawap.bh" mmsc="http://mms.viva.com.bh:38090" mmsproxy="172.18.142.36" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="426" mnc="4" carrier="VIVAMMS" apn="vivawap.bh" mmsc="http://mms.viva.com.bh:38090" mmsproxy="172.18.142.36" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="427" mnc="01" carrier="Qtel MMS" apn="mms.qtel" mmsc="http://mmsr.qtelmms.qa" mmsproxy="10.23.8.3" mmsport="8080" type="mms" user="10" password="11" authtype="1"></apn>
+      <apn mcc="427" mnc="1" carrier="Qat-Qtel mms" apn="mms.qtel" mmsc="http://mmsr.qtelmms.qa" mmsproxy="10.23.8.3" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="427" mnc="02" carrier="VFQ MMS" apn="vodafone.com.qa" mmsc="http://mms.vodafone.com.qa/mmsc" mmsproxy="10.101.97.102" mmsport="80" type="mms"></apn>
+      <apn mcc="427" mnc="2" carrier="VFQ MMS" apn="vodafone.com.qa" mmsc="http://mms.vodafone.com.qa/mmsc" mmsproxy="10.101.97.102" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="427" mnc="2" carrier="Vodafone Qatar MMS" apn="Vodafone.com.qa" mmsc="http://mms.vodafone.com.qa/mmsc" mmsproxy="10.101.97.102" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="432" mnc="11" carrier="MCCI MMS" apn="mcinet" mmsc="http://192.168.193.134:38090/was" mmsproxy="192.168.194.73" mmsport="8080" type="mms"></apn>
+      <apn mcc="432" mnc="14" carrier="MCCI MMS" apn="MCI-GPRS" mmsc="http://192.168.193.134" mmsport="38090" type="mms"></apn>
+      <apn mcc="432" mnc="19" carrier="MCCI MMS" apn="MCI-GPRS" mmsc="http://192.168.193.134" mmsport="38090" type="mms"></apn>
+      <apn mcc="432" mnc="20" carrier="RighTel-MMS" apn="RighTel-WAP" mmsc="http://10.200.40.55:38090/was" mmsproxy="10.200.39.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="432" mnc="35" carrier="Irancell-MMS" apn="mtnirancell" mmsc="http://mms:8002" mmsproxy="10.131.26.138" mmsport="8080" type="mms"></apn>
+      <apn mcc="432" mnc="70" carrier="MCCI MMS" apn="mcinet" mmsc="http://192.168.193.134:38090/was" mmsproxy="192.168.194.73" mmsport="8080" type="mms"></apn>
+      <apn mcc="432" mnc="93" carrier="MCCI MMS" apn="MCI-GPRS" mmsc="http://192.168.193.134" mmsport="38090" type="mms"></apn>
+      <apn mcc="434" mnc="04" carrier="Beeline-UZB MMS" apn="mms.beeline.uz" mmsc="http://mms" mmsproxy="172.30.30.166" mmsport="8080" type="mms" user="beeline" password="beeline" authtype="1"></apn>
+      <apn mcc="434" mnc="4" carrier="Beeline-UZB MMS" apn="mms.beeline.uz" mmsc="http://mms" mmsproxy="172.30.30.166" mmsport="8080" type="mms" user="beeline" password="beeline" authtype="1"></apn>
+      <apn mcc="434" mnc="05" carrier="UCELL MMS" apn="mms" mmsc="http://mmsc:8002/" mmsproxy="10.64.164.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="434" mnc="5" carrier="UCELL MMS" apn="mms" mmsc="http://mmsc:8002/" mmsproxy="10.64.164.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="434" mnc="07" carrier="MTS-UZB MMS" apn="mms.mts.uz" mmsc="http://mmsc/was" mmsproxy="10.10.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="440" mnc="20" carrier="Application" apn="andoworld.softbank.ne.jp" mmsc="http://mms/" mmsproxy="andmms.softbank.ne.jp" mmsport="8080" type="default,mms,supl,hpri" authtype="0"></apn>
+      <apn mcc="440" mnc="20" carrier="Application" apn="plus.acs.jp" mmsc="http://mms-s" mmsproxy="andmms.plus.acs.ne.jp" mmsport="8080" type="default,mms,supl,hipri" user="ym" password="ym" authtype="2"></apn>
+      <apn mcc="440" mnc="20" carrier="Application" apn="plus.acs.jp" mmsc="http://mms-s" mmsproxy="andmms.plusacs.ne.jp" mmsport="8080" type="default,mms,supl" user="plusw6q9tattkmpk" password="msfbbam83bsdetxb" authtype="2"></apn>
+      <apn mcc="450" mnc="05" carrier="SKT 3G INTERNET" apn="web.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" server="*"></apn>
+      <apn mcc="450" mnc="05" carrier="SKT 3G Roaming" apn="roaming.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" server="*"></apn>
+      <apn mcc="450" mnc="05" carrier="SKT LTE INTERNET" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" server="*"></apn>
+      <apn mcc="450" mnc="05" carrier="SKT LTE INTERNET" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="ia,default,mms,supl,fota,cbs" server="*"></apn>
+      <apn mcc="450" mnc="05" carrier="SKT LTE Roaming" apn="lte-roaming.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" server="*"></apn>
+      <apn mcc="450" mnc="5" carrier="SKT 3G INTERNET" apn="web.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" authtype="0" server="*"></apn>
+      <apn mcc="450" mnc="5" carrier="SKT LTE INTERNET" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" authtype="0" server="*"></apn>
+      <apn mcc="450" mnc="5" carrier="SKT-Home" apn="lte.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms" authtype="0" server="*"></apn>
+      <apn mcc="450" mnc="5" carrier="SKT-Roaming" apn="roaming.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms" authtype="0" server="*"></apn>
+      <apn mcc="450" mnc="06" carrier="LG uplus" apn="internet.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" type="default,mms,supl,fota,cbs" protocol="IPV4V6"></apn>
+      <apn mcc="450" mnc="06" carrier="LG uplus IMS" apn="ims.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" type="ia,ims" protocol="IPV4V6"></apn>
+      <apn mcc="450" mnc="06" carrier="LG uplus LTE Roaming" apn="lte-roaming.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" authtype="0"></apn>
+      <apn mcc="450" mnc="06" carrier="LG uplus Roaming" apn="wroaming.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" authtype="0"></apn>
+      <apn mcc="450" mnc="6" carrier="LG uplus" apn="internet.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" type="default,mms,supl,fota,cbs" protocol="IPV4V6"></apn>
+      <apn mcc="450" mnc="6" carrier="LG uplus IMS" apn="ims.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" type="ia,ims" protocol="IPV4V6"></apn>
+      <apn mcc="450" mnc="6" carrier="LG uplus LTE Roaming" apn="lte-roaming.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" authtype="0"></apn>
+      <apn mcc="450" mnc="6" carrier="LG uplus Roaming" apn="wroaming.lguplus.co.kr" mmsc="http://omammsc.uplus.co.kr:9084" authtype="0"></apn>
+      <apn mcc="450" mnc="08" carrier="KT" apn="lte.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" server="*"></apn>
+      <apn mcc="450" mnc="08" carrier="KT 3G INTERNET" apn="alwayson-r6.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="default,mms,supl,fota,cbs" server="*" port="80"></apn>
+      <apn mcc="450" mnc="08" carrier="KT LTE INTERNET" apn="lte150.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="default,mms,supl,fota,cbs" server="*" port="80"></apn>
+      <apn mcc="450" mnc="08" carrier="KT LTE INTERNET" apn="lte150.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="ia,default,mms,supl,fota,cbs" server="*" port="80"></apn>
+      <apn mcc="450" mnc="8" carrier="KT" apn="lte.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="default,mms" authtype="0" server="*"></apn>
+      <apn mcc="450" mnc="8" carrier="KT 3G INTERNET" apn="alwayson-r6.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="default,mms,supl,fota,cbs" authtype="0" server="*" port="80"></apn>
+      <apn mcc="450" mnc="8" carrier="KT LTE INTERNET" apn="lte150.ktfwing.com" mmsc="http://mmsc.ktfwing.com:9082" type="default,mms,supl,fota,cbs" authtype="0" server="*" port="80"></apn>
+      <apn mcc="450" mnc="11" carrier="SKT 3G INTERNET" apn="web.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" type="default,mms,supl,fota,cbs" server="*"></apn>
+      <apn mcc="450" mnc="11" carrier="SKT 3G Roaming" apn="roaming.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" server="*"></apn>
+      <apn mcc="450" mnc="11" carrier="SKT LTE Roaming" apn="lte-roaming.sktelecom.com" mmsc="http://omms.nate.com:9082/oma_mms" mmsproxy="smart.nate.com" mmsport="9093" server="*"></apn>
+      <apn mcc="452" mnc="01" carrier="Mobi-gprs-mms" apn="m-i090" mmsc="http://203.162.21.114/mmsc" mmsproxy="203.162.21.114" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="452" mnc="1" carrier="Mobi MMS" apn="m-i090" mmsc="http://203.162.21.114/mmsc" mmsproxy="203.162.21.114" mmsport="9201" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="452" mnc="1" carrier="Mobi-gprs-mms" apn="m-i090" mmsc="http://203.162.21.114/mmsc" mmsproxy="203.162.21.114" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="452" mnc="02" carrier="Vina-gprs-mms" apn="m3-mms" mmsc="http://mms.vinaphone.com.vn" mmsproxy="10.1.10.46" mmsport="8000" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="452" mnc="2" carrier="Vina MMS" apn="m3-mms" mmsc="http://mms.vinaphone.com.vn" mmsproxy="10.1.10.46" mmsport="9201" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="452" mnc="2" carrier="Vina-gprs-mms" apn="m3-mms" mmsc="http://mms.vinaphone.com.vn" mmsproxy="10.1.10.46" mmsport="8000" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="452" mnc="04" carrier="Viettel-gprs-mms" apn="v-mms" mmsc="http://mms.viettelmobile.com.vn/mms/wapenc" mmsproxy="192.168.233.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="452" mnc="4" carrier="Viettel MMS" apn="v-mms" mmsc="http://mms.viettelmobile.com.vn/mms/wapenc" mmsproxy="192.168.233.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="4" carrier="Viettel-gprs-mms" apn="v-mms" mmsc="http://mms.viettelmobile.com.vn/mms/wapenc" mmsproxy="192.168.233.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="05" carrier="Vietnamobile_MMS" apn="mms" mmsc="http://10.10.128.58/servlets/mms" mmsproxy="10.10.128.44" mmsport="8080" type="mms"></apn>
+      <apn mcc="452" mnc="5" carrier="EVN MMS" apn="mms" mmsc="http://10.10.128.58/servlets/mms" mmsproxy="10.10.128.44" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="5" carrier="Vietnamobile_MMS" apn="mms" mmsc="http://10.10.128.58/servlets/mms" mmsproxy="10.10.128.44" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="07" carrier="Gmobile MMS" apn="mms" mmsc="http://mms" mmsproxy="10.16.70.199" mmsport="8080" type="mms" user="mms" password="mms" authtype="2"></apn>
+      <apn mcc="452" mnc="07" carrier="Gmobile-gprs-mms" apn="mms" mmsc="http://mms" mmsproxy="10.16.70.199" mmsport="8080" type="mms"></apn>
+      <apn mcc="452" mnc="7" carrier="Beeline MMS VN" apn="mms" mmsc="http://mms" mmsproxy="10.16.70.199" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="7" carrier="Gmobile-gprs-mms" apn="mms" mmsc="http://mms" mmsproxy="10.16.70.199" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="452" mnc="08" carrier="e-mms" apn="e-mms" mmsc="http://10.18.2.172:38090" mmsproxy="10.18.2.183" mmsport="8080" type="mms"></apn>
+      <apn mcc="452" mnc="8" carrier="e-mms" apn="e-mms" mmsc="http://10.18.2.172:38090" mmsproxy="10.18.2.183" mmsport="8080" type="mms"></apn>
+      <apn mcc="454" mnc="00" carrier="1O1O" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="00" carrier="NWMOBILE" apn="NWMOBILE" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.61" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="00" carrier="one2free" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="000" carrier="one2free" apn="hkcsl" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="002" carrier="one2free" apn="hkcsl" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="02" carrier="1O1O" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="02" carrier="NWMOBILE" apn="NWMOBILE" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.61" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="02" carrier="one2free" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="2" carrier="1O1O" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="2" carrier="NWMOBILE" apn="NWMOBILE" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.61" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="03" carrier="3" apn="mobile.three.com.hk" mmsc="http://mms.um.three.com.hk:10021/mmsc" mmsproxy="mms.three.com.hk" mmsport="8799" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="03" carrier="3 LTE" apn="mobile.lte.three.com.hk" mmsc="http://mms.um.three.com.hk:10021/mmsc" mmsproxy="mms.three.com.hk" mmsport="8799" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="004" carrier="3" apn="mobile.three.com.hk" mmsc="http://mms.um.three.com.hk:10021/mmsc" mmsproxy="mms.three.com.hk" mmsport="8799"></apn>
+      <apn mcc="454" mnc="04" carrier="3(2G) MMS" apn="mms-g.three.com.hk" mmsc="http://10.30.15.51:10021/mmsc" mmsproxy="10.30.15.53" mmsport="8080" type="mms"></apn>
+      <apn mcc="454" mnc="4" carrier="3(2G) MMS" apn="mms-g.three.com.hk" mmsc="http://10.30.15.51:10021/mmsc" mmsproxy="10.30.15.53" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="454" mnc="4" carrier="3-DB MMS" apn="mms-g.three.com.hk" mmsc="http://10.30.15.51:10021/mmsc" mmsproxy="10.30.15.53" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="454" mnc="06" carrier="SmarTone" apn="SmarTone" mmsc="http://mms.smartone.com/server" mmsproxy="10.9.9.9" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="10" carrier="one2free" apn="hkcsl" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="12" carrier="CMHK MMS" apn="cmhk" mmsc="http://mms.hk.chinamobile.com/mms" type="mms"></apn>
+      <apn mcc="454" mnc="12" carrier="CMHK MMS" apn="cmhk" mmsc="http://mms.hk.chinamobile.com/mms" type="mms" authtype="0"></apn>
+      <apn mcc="454" mnc="12" carrier="CMHK MMS" apn="peoples.mms" mmsc="http://mms.hk.chinamobile.com/mms" mmsproxy="172.31.31.36" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="454" mnc="13" carrier="CMHK MMS" apn="cmhk" mmsc="http://mms.hk.chinamobile.com/mms" type="mms"></apn>
+      <apn mcc="454" mnc="15" carrier="SmarTone" apn="SmarTone" mmsc="http://mms.smartone.com/server" mmsproxy="10.9.9.9" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="16" carrier="PCCW MMS" apn="pccwmms" mmsc="http://mmsc.mms.pccwmobile.com:8002/" mmsproxy="10.131.2.8" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="454" mnc="16" carrier="PCCW-HKT" apn="pccw" mmsc="http://3gmms.pccwmobile.com:8080/was" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="16" carrier="PCCW-HKT" apn="pccw" mmsc="http://mms.pccw-hkt.com:8080" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="17" carrier="SmarTone" apn="SmarTone" mmsc="http://mms.smartone.com/server" mmsproxy="10.9.9.9" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="18" carrier="1O1O" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="18" carrier="NWMOBILE" apn="NWMOBILE" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.61" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="18" carrier="one2free" apn="hkcsl" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="18" carrier="one2free" apn="mobile" mmsc="http://192.168.58.171:8002" mmsproxy="192.168.59.51" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="454" mnc="019" carrier="PCCW-HKT" apn="pccw" mmsc="http://mms.pccw-hkt.com:8080" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="19" carrier="PCCW-HKT" apn="pccw" mmsc="http://3gmms.pccwmobile.com:8080/was" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="020" carrier="PCCW-HKT" apn="pccw" mmsc="http://3gmms.pccwmobile.com:8080/was" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="20" carrier="PCCW-HKT" apn="pccw" mmsc="http://mms.pccw-hkt.com:8080" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="029" carrier="PCCW-HKT" apn="pccw" mmsc="http://3gmms.pccwmobile.com:8080/was" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="454" mnc="029" carrier="PCCW-HKT" apn="pccw" mmsc="http://mms.pccw-hkt.com:8080" mmsproxy="10.140.14.10" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="455" mnc="00" carrier="SmarTone Macau" apn="smartgprs" mmsc="http://momms.smartone.com/dmog/mo" mmsproxy="10.9.9.29" mmsport="8080" type="default,supl,mms" authtype="3"></apn>
+      <apn mcc="455" mnc="01" carrier="CTM (Prepaid)" apn="ctmprepaid" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="455" mnc="01" carrier="CTM MMS" apn="ctmmms" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="455" mnc="1" carrier="CTM (Prepaid)" apn="ctmprepaid" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="455" mnc="1" carrier="CTM MMS" apn="ctmmms" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="455" mnc="03" carrier="3 Macau" apn="mobile.three.com.mo" mmsc="http://mms.three.com.mo:10021/mmsc" mmsproxy="mms.three.com.mo" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="455" mnc="3" carrier="HutchisonMMS" apn="mms.hutchisonmacau.com" mmsc="http://10.30.15.51:10021/mmsc" mmsproxy="10.30.15.53" mmsport="9201" type="mms" user="hutchison" password="1234" authtype="3" proxy="10.30.3.151" port="9201"></apn>
+      <apn mcc="455" mnc="04" carrier="CTM (Prepaid)" apn="ctmprepaid" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="455" mnc="04" carrier="CTM MMS" apn="ctmmms" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="455" mnc="4" carrier="CTM (Prepaid)" apn="ctmprepaid" mmsc="http://mms.wap.ctm.net:8002" mmsproxy="192.168.99.3" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="455" mnc="05" carrier="3 Macau" apn="mobile.three.com.mo" mmsc="http://mms.three.com.mo:10021/mmsc" mmsproxy="mms.three.com.mo" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="460" mnc="0" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="0" carrier="移动彩信" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="00" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="01" carrier="中国联通 3g 彩信 (China Unicom)" apn="3gwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms"></apn>
+      <apn mcc="460" mnc="01" carrier="中国联通彩信 (China Unicom)" apn="uniwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms"></apn>
+      <apn mcc="460" mnc="01" carrier="联通2g彩信 (China Unicom)" apn="uniwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms"></apn>
+      <apn mcc="460" mnc="01" carrier="联通彩信 (China Unicom)" apn="3gwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms"></apn>
+      <apn mcc="460" mnc="1" carrier="2G联通彩信" apn="uniwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="1" carrier="3G联通彩信" apn="3gwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="1" carrier="联通2g彩信 (China Unicom)" apn="uniwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="1" carrier="联通彩信 (China Unicom)" apn="3gwap" mmsc="http://mmsc.myuni.com.cn" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="02" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="2" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="2" carrier="移动彩信" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="03" carrier="CTWAP" apn="ctwap" mmsc="http://mmsc.vnet.mobi" mmsproxy="10.0.0.200" mmsport="80" type="default,mms" proxy="10.0.0.200" port="80"></apn>
+      <apn mcc="460" mnc="07" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="7" carrier="中国移动彩信 (China Mobile)" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0" proxy="10.0.0.172" port="80"></apn>
+      <apn mcc="460" mnc="7" carrier="移动彩信" apn="cmwap" mmsc="http://mmsc.monternet.com" mmsproxy="10.0.0.172" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="460" mnc="12" carrier="CTWAP" apn="ctwap" mmsc="http://mmsc.vnet.mobi" mmsproxy="10.0.0.200" mmsport="80" type="default,mms" proxy="10.0.0.200" port="80"></apn>
+      <apn mcc="460" mnc="13" carrier="CTWAP" apn="ctwap" mmsc="http://mmsc.vnet.mobi" mmsproxy="10.0.0.200" mmsport="80" type="default,mms" proxy="10.0.0.200" port="80"></apn>
+      <apn mcc="466" mnc="01" carrier="遠傳電信(Far EasTone) (MMS)" apn="fetnet01" mmsc="http://mms" mmsproxy="210.241.199.199" mmsport="9201" type="mms"></apn>
+      <apn mcc="466" mnc="1" carrier="遠傳電信 MMS" apn="fetnet01" mmsc="http://mms/" mmsproxy="210.241.199.199" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="1" carrier="遠傳電信(Far EasTone) (MMS)" apn="fetnet01" mmsc="http://mms" mmsproxy="210.241.199.199" mmsport="9201" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="88" carrier="和信電訊(KGT-Online) (MMS)" apn="kgtmms" mmsc="http://mms.kgtmms.net.tw/mms/wapenc" mmsproxy="172.28.33.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="466" mnc="89" carrier="T Star-MMS" apn="internet" mmsc="http://mms.vibo.net.tw" mmsproxy="172.24.128.36" mmsport="8080" type="mms"></apn>
+      <apn mcc="466" mnc="89" carrier="威寶電信 MMS" apn="vibo" mmsc="http://mms/" mmsproxy="172.24.128.36" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="89" carrier="威寶電信(VIBO) (MMS)" apn="vibo" mmsc="http://mms" mmsproxy="172.24.128.36" mmsport="8080" type="mms"></apn>
+      <apn mcc="466" mnc="89" carrier="威寶電信(VIBO) (MMS)" apn="vibo" mmsc="http://mms" mmsproxy="172.24.128.36" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="92" carrier="中華電信 MMS" apn="emome" mmsc="http://mms.emome.net:8002" mmsproxy="10.1.1.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="92" carrier="中華電信(Chunghwa) (MMS)" apn="emome" mmsc="http://mms.emome.net:8002" mmsproxy="10.1.1.1" mmsport="8080" type="mms"></apn>
+      <apn mcc="466" mnc="92" carrier="中華電信(Chunghwa) (MMS)" apn="emome" mmsc="http://mms.emome.net:8002" mmsproxy="10.1.1.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="93" carrier="台湾大哥大 MMS" apn="mms" mmsc="http://mms.catch.net.tw/" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="93" carrier="台灣大哥大(TW Mobile) (MMS)" apn="MMS" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms"></apn>
+      <apn mcc="466" mnc="93" carrier="台灣大哥大(TW Mobile) (MMS)" apn="MMS" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="97" carrier="台湾大哥大 MMS" apn="mms" mmsc="http://mms.catch.net.tw/" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="97" carrier="台灣大哥大(TW Mobile) (MMS)" apn="MMS" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms"></apn>
+      <apn mcc="466" mnc="97" carrier="台灣大哥大(TW Mobile) (MMS)" apn="MMS" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="99" carrier="台湾大哥大 MMS" apn="mms" mmsc="http://mms.catch.net.tw/" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="466" mnc="99" carrier="台灣大哥大(TW Mobile) (MMS)" apn="mms" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms"></apn>
+      <apn mcc="466" mnc="99" carrier="台灣大哥大(TW Mobile) (MMS)" apn="mms" mmsc="http://mms.catch.net.tw" mmsproxy="10.1.1.2" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="470" mnc="01" carrier="GP-MMS" apn="gpmms" mmsc="http://mms.gpsurf.net/servlets/mms" mmsproxy="10.128.1.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="470" mnc="1" carrier="GP-MMS" apn="gpmms" mmsc="http://mms.gpsurf.net/servlets/mms" mmsproxy="10.128.1.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="502" mnc="10" carrier="DiGi MMS" apn="digimms" mmsc="http://mms.digi.com.my/servlets/mms" mmsproxy="203.92.128.160" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="502" mnc="12" carrier="Maxis" apn="unet" mmsc="http://172.16.74.100:10021/mmsc" mmsproxy="202.75.133.49" mmsport="80" type="default,mms" user="maxis" password="wap" authtype="0" proxy="202.75.133.49" port="80"></apn>
+      <apn mcc="502" mnc="12" carrier="Maxis Internet" apn="max4g" mmsc="http://172.16.74.100:10021/mmsc" mmsproxy="202.75.133.49" mmsport="80" type="default,supl,mms" user="maxis" password="wap" authtype="1"></apn>
+      <apn mcc="502" mnc="13" carrier="Celcom Internet" apn="celcom4g" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="502" mnc="16" carrier="DiGi MMS" apn="digimms" mmsc="http://mms.digi.com.my/servlets/mms" mmsproxy="203.92.128.160" mmsport="80" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="502" mnc="16" carrier="DiGi MMS" apn="digimms" mmsc="http://mms.digi.com.my/servlets/mms" mmsproxy="203.92.128.160" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="502" mnc="17" carrier="Maxis Internet" apn="max4g" mmsc="http://172.16.74.100:10021/mmsc" mmsproxy="202.75.133.49" mmsport="80" type="default,supl,mms" user="maxis" password="wap" authtype="1"></apn>
+      <apn mcc="502" mnc="18" carrier="U Mobile Internet" apn="my3g" mmsc="http://10.30.3.11/servlets/mms" mmsproxy="10.30.5.11" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="502" mnc="18" carrier="U Mobile Internet" apn="my3g" mmsc="http://10.30.3.11/servlets/mms" mmsproxy="10.30.5.11" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="502" mnc="18" carrier="umobile" apn="my3g" mmsc="http://10.30.3.11/servlets/mms" mmsproxy="10.30.5.11" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="502" mnc="19" carrier="Celcom" apn="celcom3G" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="502" mnc="19" carrier="Celcom Internet" apn="celcom4g" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="502" mnc="19" carrier="Celcom Internet" apn="celcom4g" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="502" mnc="142" carrier="Maxis Internet" apn="max4g" mmsc="http://172.16.74.100:10021/mmsc" mmsproxy="202.75.133.49" mmsport="80" type="default,supl,mms" user="maxis" password="wap" authtype="1"></apn>
+      <apn mcc="502" mnc="143" carrier="DiGi MMS" apn="digimms" mmsc="http://mms.digi.com.my/servlets/mms" mmsproxy="203.92.128.160" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="502" mnc="145" carrier="Celcom Internet" apn="celcom4g" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="502" mnc="146" carrier="DiGi MMS" apn="digimms" mmsc="http://mms.digi.com.my/servlets/mms" mmsproxy="203.92.128.160" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="502" mnc="147" carrier="Maxis Internet" apn="max4g" mmsc="http://172.16.74.100:10021/mmsc" mmsproxy="202.75.133.49" mmsport="80" type="default,supl,mms" user="maxis" password="wap" authtype="1"></apn>
+      <apn mcc="502" mnc="148" carrier="Celcom Internet" apn="celcom4g" mmsc="http://mms.celcom.net.my" mmsproxy="10.128.1.242" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="505" mnc="01" carrier="Telstra MMS" apn="telstra.mms" mmsc="http://mmsc.telstra.com:8002/" mmsproxy="10.1.1.180" mmsport="80" type="mms"></apn>
+      <apn mcc="505" mnc="1" carrier="Telstra MMS" apn="telstra.mms" mmsc="http://mmsc.telstra.com:8002" mmsproxy="10.1.1.180" mmsport="80" type="mms" authtype="0" protocol="IP"></apn>
+      <apn mcc="505" mnc="1" carrier="Telstra MMS" apn="telstra.mms" mmsc="http://mmsc.telstra.com:8002/" mmsproxy="10.1.1.180" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="505" mnc="02" carrier="Optus MMS" apn="mms" mmsc="http://mmsc.optus.com.au:8002/" mmsproxy="61.88.190.10" mmsport="8070" type="mms"></apn>
+      <apn mcc="505" mnc="02" carrier="Virgin MMS" apn="virginmms" mmsc="http://mms.virginvibe.com.au:8002" mmsproxy="202.139.83.152" mmsport="8070" type="mms" mvno_match_data="505029" mvno_type="imsi"></apn>
+      <apn mcc="505" mnc="2" carrier="Optus MMS" apn="mms" mmsc="http://mmsc.optus.com.au:8002/" mmsproxy="61.88.190.10" mmsport="8070" type="mms" authtype="0"></apn>
+      <apn mcc="505" mnc="2" carrier="Virgin MMS" apn="virginmms" mmsc="http://mms.virginvibe.com.au:8002" mmsproxy="202.139.83.152" mmsport="8070" type="mms" authtype="0" mvno_match_data="505029" mvno_type="imsi"></apn>
+      <apn mcc="505" mnc="2" carrier="Virgin MMS" apn="virginmms" mmsc="http://mms.virginvibe.com.au:8002/" mmsproxy="202.139.83.152" mmsport="8070" type="mms" authtype="0" mvno_match_data="virgin mobile" mvno_type="spn"></apn>
+      <apn mcc="505" mnc="03" carrier="Vodafone live!" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="505" mnc="3" carrier="Vodafone AU" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080" type="default,mms" authtype="0" protocol="IP"></apn>
+      <apn mcc="505" mnc="3" carrier="Vodafone live!" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="505" mnc="06" carrier="Planet 3" apn="3services" mmsc="http://mmsc.three.net.au:10021/mmsc" mmsproxy="10.176.57.25" mmsport="8799" authtype="0" protocol="IP"></apn>
+      <apn mcc="505" mnc="6" carrier="Planet 3" apn="3services" mmsc="http://mmsc.three.net.au:10021/mmsc" mmsproxy="10.176.57.25" mmsport="8799" authtype="0" protocol="IP"></apn>
+      <apn mcc="505" mnc="07" carrier="VF AU PXT" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080" type="mms"></apn>
+      <apn mcc="505" mnc="11" carrier="Telstra MMS" apn="Telstra.mms" mmsc="http://mmsc.telstra.com:8002" mmsproxy="10.1.1.180" mmsport="80" type="mms"></apn>
+      <apn mcc="505" mnc="12" carrier="3" apn="3services" mmsc="http://mmsc.three.net.au:10021/mmsc" mmsproxy="10.176.57.25" mmsport="8799" type="default,supl,mms"></apn>
+      <apn mcc="505" mnc="71" carrier="Telstra MMS" apn="Telstra.mms" mmsc="http://mmsc.telstra.com:8002" mmsproxy="10.1.1.180" mmsport="80" type="mms"></apn>
+      <apn mcc="505" mnc="72" carrier="Telstra MMS" apn="Telstra.mms" mmsc="http://mmsc.telstra.com:8002" mmsproxy="10.1.1.180" mmsport="80" type="mms"></apn>
+      <apn mcc="505" mnc="88" carrier="VF AU PXT" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080" type="mms"></apn>
+      <apn mcc="505" mnc="90" carrier="Optus MMS" apn="mms" mmsc="http://mmsc.optus.com.au:8002/" mmsproxy="61.88.190.10" mmsport="8070" type="mms"></apn>
+      <apn mcc="505" mnc="99" carrier="Vodafone Live!" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.au/pxtsend" mmsproxy="10.202.2.60" mmsport="8080"></apn>
+      <apn mcc="510" mnc="01" carrier="INDOSAT-GPRS" apn="indosatgprs" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="*" proxy="10.19.19.19" port="8080"></apn>
+      <apn mcc="510" mnc="01" carrier="Indosat MMS" apn="indosatmms" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="mms" user="indosat" password="indosat" authtype="1"></apn>
+      <apn mcc="510" mnc="1" carrier="Indosat MMS" apn="indosatmms" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="mms" user="indosat" password="indosat" authtype="1"></apn>
+      <apn mcc="510" mnc="1" carrier="Indosat MMS (01)" apn="indosatmms" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="mms" user="indosat" password="indosat" authtype="0"></apn>
+      <apn mcc="510" mnc="08" carrier="AXISmms" apn="AXISmms" mmsc="http://mmsc.axis" mmsproxy="10.8.3.8" mmsport="8080" type="mms" user="axis" password="123456" authtype="1"></apn>
+      <apn mcc="510" mnc="08" carrier="AXISwap" apn="AXIS" mmsc="http://mmsc.axis" mmsproxy="10.8.3.8" mmsport="8080" type="*" proxy="10.8.3.8" port="8080"></apn>
+      <apn mcc="510" mnc="8" carrier="AXIS MMS" apn="AXISmms" mmsc="http://mmsc.AXIS" mmsproxy="10.8.3.8" mmsport="8080" type="mms" user="AXIS" password="123456" authtype="0"></apn>
+      <apn mcc="510" mnc="10" carrier="TSEL-GPRS" apn="telkomsel" mmsc="http://mms.telkomsel.com" mmsproxy="10.1.89.150" mmsport="8000" type="*" proxy="10.1.89.130" port="8000"></apn>
+      <apn mcc="510" mnc="10" carrier="TSEL-MMS" apn="mms" mmsc="http://mms.telkomsel.com" mmsproxy="10.1.89.150" mmsport="8000" type="mms" user="wap" password="wap123" authtype="1"></apn>
+      <apn mcc="510" mnc="10" carrier="Telkomsel MMS" apn="mms" mmsc="http://mms.telkomsel.com" mmsproxy="10.1.89.150" mmsport="8000" type="mms" user="wap" password="wap123" authtype="0"></apn>
+      <apn mcc="510" mnc="11" carrier="XL MMS" apn="www.xlmms.net" mmsc="http://mmc.xl.net.id/servlets/mms" mmsproxy="202.152.240.50" mmsport="8080" type="mms" user="xlgprs" password="proxl" authtype="0" server="http://mmc.xl.net.id/servlets/mms"></apn>
+      <apn mcc="510" mnc="11" carrier="XL-GPRS" apn="www.xlgprs.net" mmsc="http://mmc.xl.net.id/servlets/mms" mmsproxy="202.152.240.050" mmsport="8080" type="*" proxy="202.152.240.050" port="8080"></apn>
+      <apn mcc="510" mnc="11" carrier="XL-MMS" apn="www.xlmms.net" mmsc="http://mmc.xl.net.id/servlets/mms" mmsproxy="202.152.240.50" mmsport="8080" type="mms" user="xlgprs" password="proxl" authtype="1"></apn>
+      <apn mcc="510" mnc="21" carrier="INDOSAT-GPRS" apn="indosatgprs" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="*" proxy="10.19.19.19" port="8080"></apn>
+      <apn mcc="510" mnc="21" carrier="Indosat MMS" apn="indosatmms" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="mms" user="indosat" password="indosat" authtype="1"></apn>
+      <apn mcc="510" mnc="21" carrier="Indosat MMS (21)" apn="indosatmms" mmsc="http://mmsc.indosat.com" mmsproxy="10.19.19.19" mmsport="8080" type="mms" user="indosat" password="indosat" authtype="0"></apn>
+      <apn mcc="510" mnc="89" carrier="3 MMS (510.89)" apn="3mms" mmsc="http://mms.three.co.id" mmsproxy="10.4.0.10" mmsport="8080" type="mms" user="3mms" password="3mms" authtype="0"></apn>
+      <apn mcc="510" mnc="89" carrier="3-GPRS" apn="3gprs" mmsc="http://mms.three.co.id" mmsproxy="10.4.0.10" mmsport="3128" type="*" proxy="10.4.0.10" port="3128"></apn>
+      <apn mcc="510" mnc="89" carrier="3MMS" apn="3mms" mmsc="http://mms.three.co.id" mmsproxy="10.4.0.10" mmsport="3128" type="mms" user="3mms" password="3mms" authtype="1"></apn>
+      <apn mcc="515" mnc="02" carrier="myGlobe MMS" apn="mms.globe.com.ph" mmsc="http://192.40.100.22:10021/mmsc" mmsproxy="203.177.42.214" mmsport="8080" type="mms"></apn>
+      <apn mcc="515" mnc="2" carrier="Globe MMS" apn="mms.globe.com.ph" mmsc="http://192.40.100.22:10021/mmsc" mmsproxy="203.177.42.214" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="515" mnc="2" carrier="myGlobe MMS" apn="mms.globe.com.ph" mmsc="http://192.40.100.22:10021/mmsc" mmsproxy="203.177.42.214" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="515" mnc="03" carrier="Smart MMS" apn="mms" mmsc="http://10.102.61.238:8002" mmsproxy="10.102.61.46" mmsport="8080" type="mms"></apn>
+      <apn mcc="515" mnc="3" carrier="SMART MMS" apn="mms" mmsc="http://10.102.61.238:8002" mmsproxy="10.102.61.46" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="515" mnc="05" carrier="SUN MMS" apn="mms" mmsc="http://mmscenter.suncellular.com.ph" mmsproxy="202.138.159.78" mmsport="8080" type="mms"></apn>
+      <apn mcc="515" mnc="5" carrier="SUN MMS" apn="mms" mmsc="http://mmscenter.suncellular.com.ph" mmsproxy="202.138.159.78" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="515" mnc="18" carrier="CURE MMS" apn="redmms" mmsc="http://10.102.61.193:8002/mmsc" mmsproxy="10.138.3.35" mmsport="8080" type="mms"></apn>
+      <apn mcc="515" mnc="18" carrier="Redmms" apn="real.globe.com.ph" mmsc="http://10.102.61.193:8002/mmsc" mmsproxy="10.138.3.35" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="0" carrier="CAT3G MMS" apn="catmms" mmsc="http://mms.cat3g.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="0" carrier="TRUE-H MMS" apn="hmms" mmsc="http://mms.trueh.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="3"></apn>
+      <apn mcc="520" mnc="00" carrier="CAT3G MMS" apn="catmms" mmsc="http://mms.cat3g.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="00" carrier="TRUE-H MMS" apn="hmms" mmsc="http://mms.trueh.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="1" mvno_match_data="01" mvno_type="gid"></apn>
+      <apn mcc="520" mnc="01" carrier="AIS MMS" apn="multimedia" mmsc="http://mms.mobilelife.co.th" mmsproxy="203.170.229.34" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="1" carrier="AIS MMS" apn="multimedia" mmsc="http://mms.mobilelife.co.th" mmsproxy="203.170.229.34" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="03" carrier="AIS MMS" apn="multimedia" mmsc="http://mms.mobilelife.co.th" mmsproxy="203.170.229.34" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="3" carrier="AIS 3G MMS" apn="mms" mmsc="http://mms.ais.co.th" mmsproxy="203.170.229.34" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="3" carrier="AIS MMS" apn="multimedia" mmsc="http://mms.mobilelife.co.th" mmsproxy="203.170.229.34" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="04" carrier="TRUE-H MMS" apn="hmms" mmsc="http://mms.trueh.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="1"></apn>
+      <apn mcc="520" mnc="4" carrier="TRUE-H MMS" apn="hmms" mmsc="http://mms.trueh.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="3"></apn>
+      <apn mcc="520" mnc="05" carrier="dtac MMS" apn="mms" mmsc="http://mms2.dtac.co.th:8002/" mmsproxy="10.10.10.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="5" carrier="dtac mms" apn="mms" mmsc="http://mms2.dtac.co.th:8002/" mmsproxy="10.10.10.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="15" carrier="TOT 3G MMS" apn="mms" mmsc="http://mms.tot3g.net:8002" mmsproxy="192.168.0.72" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="15" carrier="TOT 3G MMS" apn="mms" mmsc="http://mms.tot3g.net:8002" mmsproxy="192.168.0.72" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="18" carrier="dtac MMS" apn="mms" mmsc="http://mms.dtac.co.th:8002/" mmsproxy="10.10.10.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="18" carrier="dtac MMS" apn="mms" mmsc="http://mms.dtac.co.th:8002/" mmsproxy="10.10.10.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="18" carrier="dtac MMS" apn="mms" mmsc="http://mms.dtac.co.th:8002/" mmsproxy="203.155.200.133" mmsport="8080" type="mms"></apn>
+      <apn mcc="520" mnc="18" carrier="dtac MMS" apn="mms" mmsc="http://mms.dtac.co.th:8002/" mmsproxy="203.155.200.133" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="520" mnc="99" carrier="TRUE MMS" apn="hmms" mmsc="http://mms.truelife.com:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="1"></apn>
+      <apn mcc="520" mnc="99" carrier="True MMS" apn="mms" mmsc="http://mms.trueworld.net:8002/" mmsproxy="10.4.7.39" mmsport="8080" type="mms" user="true" password="true" authtype="3"></apn>
+      <apn mcc="525" mnc="01" carrier="SingTel (PostPaid)" apn="e-ideas" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="525" mnc="01" carrier="SingTel (PrePaid)" apn="hicard" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="525" mnc="1" carrier="SingTel (PostPaid)" apn="e-ideas" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="525" mnc="1" carrier="SingTel (PrePaid)" apn="hicard" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms" authtype="0"></apn>
+      <apn mcc="525" mnc="1" carrier="SingTel MMS" apn="hicard" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="525" mnc="02" carrier="SingTel (PostPaid)" apn="e-ideas" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="525" mnc="02" carrier="SingTel (PrePaid)" apn="hicard" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="525" mnc="2" carrier="SingTel (PostPaid)" apn="e-ideas" mmsc="http://mms.singtel.com:10021/mmsc" mmsproxy="165.21.42.84" mmsport="8080" type="default,supl,mms"></apn>
+      <apn mcc="525" mnc="03" carrier="M1 MMS(3G)" apn="miworld" mmsc="http://mmsgw:8002" mmsproxy="172.16.14.10" mmsport="8080" type="mms" user="65" password="user123" authtype="1"></apn>
+      <apn mcc="525" mnc="3" carrier="M1 MMS" apn="miworld" mmsc="http://mmsgw:8002/" mmsproxy="172.16.14.10" mmsport="8080" type="mms" user="65" password="user123" authtype="3"></apn>
+      <apn mcc="525" mnc="3" carrier="M1 MMS(3G)" apn="miworld" mmsc="http://mmsgw:8002" mmsproxy="172.16.14.10" mmsport="8080" type="mms" user="65" password="user123" authtype="1"></apn>
+      <apn mcc="525" mnc="04" carrier="M1 MMS(3G)" apn="miworld" mmsc="http://mmsgw:8002" mmsproxy="172.16.14.10" mmsport="8080" type="mms" user="65" password="user123" authtype="1"></apn>
+      <apn mcc="525" mnc="05" carrier="SH MMS Postpaid" apn="shmms" mmsc="http://mms.starhubgee.com.sg:8002/" mmsproxy="10.12.1.80" mmsport="80" type="mms"></apn>
+      <apn mcc="525" mnc="5" carrier="SH MMS Postpaid" apn="shmms" mmsc="http://mms.starhubgee.com.sg:8002/" mmsproxy="10.12.1.80" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="525" mnc="5" carrier="StarHub MMS" apn="shmms" mmsc="http://mms.starhubgee.com.sg:8002/" mmsproxy="10.12.1.80" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="530" mnc="01" carrier="VFNZ Gateway" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.nz/pxtsend" mmsproxy="172.30.38.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="530" mnc="1" carrier="VFNZ Gateway" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.nz/pxtsend" mmsproxy="172.30.38.3" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="530" mnc="1" carrier="VFNZ PXT" apn="live.vodafone.com" mmsc="http://pxt.vodafone.net.nz/pxtsend" mmsproxy="172.30.38.3" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="530" mnc="05" carrier="TelecomMMS" apn="wap.telecom.co.nz" mmsc="http://lsmmsc.xtra.co.nz" mmsproxy="210.55.11.73" mmsport="80" type="mms"></apn>
+      <apn mcc="530" mnc="5" carrier="TelecomMMS" apn="wap.telecom.co.nz" mmsc="http://lsmmsc.xtra.co.nz" mmsproxy="210.55.11.73" mmsport="80" type="mms" authtype="0"></apn>
+      <apn mcc="530" mnc="24" carrier="2Degrees MMS" apn="mms" mmsc="http://mms.2degreesmobile.net.nz:48090" mmsproxy="118.148.1.118" mmsport="8080" type="mms"></apn>
+      <apn mcc="530" mnc="24" carrier="2degrees MMS" apn="mms" mmsc="http://mms.2degreesmobile.net.nz:48090" mmsproxy="118.148.1.118" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="537" mnc="03" carrier="PNG MMS" apn="wap.digicelpng.com" mmsc="http://mms.digicelpng.com:8990" mmsproxy="10.149.83.116" mmsport="8080" type="mms"></apn>
+      <apn mcc="537" mnc="03" carrier="Papua New Guinea:Digicel:Modem" apn="wap.digicel.com.pg" mmsc="http://wapdigicel.com" type="dun" authtype="1" proxy="10.149.122.12" port="8080"></apn>
+      <apn mcc="537" mnc="3" carrier="PNG MMS" apn="wap.digicelpng.com" mmsc="http://mms.digicelpng.com:8990" mmsproxy="10.149.83.116" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="537" mnc="3" carrier="Papua New Guinea:Digicel:Mms" apn="wap.digicel.com.pg" mmsc="http://mmc.digicel.com.pg/servlets/mms" mmsproxy="10.149.122.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="539" mnc="88" carrier="Tonga:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="539" mnc="88" carrier="Tonga:Digicel:Modem" apn="wap" mmsc="http://wapdigicel.com" type="dun" authtype="1" proxy="172.16.7.12" port="8080"></apn>
+      <apn mcc="541" mnc="05" carrier="Vanatu:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="541" mnc="05" carrier="Vanatu:Digicel:Modem" apn="wap" mmsc="http://wapdigicel.com" type="dun" authtype="1" proxy="172.16.7.12" port="8080"></apn>
+      <apn mcc="541" mnc="5" carrier="Vanatu:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="542" mnc="02" carrier="Fiji:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="542" mnc="02" carrier="Fiji:Digicel:Modem" apn="wap" mmsc="http://wapdigicel.com" type="dun" authtype="1" proxy="172.16.7.12" port="8080"></apn>
+      <apn mcc="542" mnc="2" carrier="Fiji:Digicel:Mms" apn="wap" mmsc="http://mms.digicelgroup.com" mmsproxy="172.16.7.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="602" mnc="01" carrier="Mobinil MMS" apn="mobinilmms" mmsc="http://10.7.13.24:8002" mmsproxy="62.241.155.45" mmsport="8080" type="mms"></apn>
+      <apn mcc="602" mnc="1" carrier="Mobinil MMS" apn="mobinilmms" mmsc="http://10.7.13.24:8002" mmsproxy="62.241.155.45" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="602" mnc="02" carrier="Vodafone MMS" apn="mms.vodafone.com.eg" mmsc="http://mms.vodafone.com.eg/servlets/mms" mmsproxy="163.121.178.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="602" mnc="2" carrier="vodafone EG mms" apn="mms.Vodafone.com.eg" mmsc="http://mms.vodafone.com.eg/servlets/mms" mmsproxy="163.121.178.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="602" mnc="03" carrier="Etisalat MMS" apn="etisalat" mmsc="http://10.71.131.7:38090" mmsproxy="10.71.130.29" mmsport="8080" type="mms"></apn>
+      <apn mcc="602" mnc="3" carrier="Etisalat MMS" apn="etisalat" mmsc="http://10.71.131.7:38090" mmsproxy="10.71.130.29" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="602" mnc="3" carrier="etisalat EG" apn="etisalat" mmsc="http://10.71.131.7:38090" mmsproxy="10.71.130.29" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="603" mnc="01" carrier="Mobilis mms" apn="mms" mmsc="http://172.25.49.9/servlets/mms" mmsproxy="172.25.49.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="603" mnc="1" carrier="Mobilis mms" apn="mms" mmsc="http://172.25.49.9/servlets/mms" mmsproxy="172.25.49.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="603" mnc="02" carrier="djezzy.mms" apn="djezzy.mms" mmsc="http://172.24.97.152:6021/mmsc" mmsproxy="172.24.97.158" mmsport="8799" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="603" mnc="2" carrier="Djezzy MMS" apn="djezzy.mms" mmsc="http://172.24.97.152.10021/mmsc" mmsproxy="172.24.97.158" mmsport="9201" type="mms" authtype="0"></apn>
+      <apn mcc="603" mnc="2" carrier="djezzy.mms" apn="djezzy.mms" mmsc="http://172.24.97.152:6021/mmsc" mmsproxy="172.24.97.158" mmsport="8799" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="603" mnc="03" carrier="nedjmamms" apn="nedjmamms" mmsc="http://10.10.111.1" mmsproxy="192.168.52.3" mmsport="3128" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="603" mnc="3" carrier="Nedjma MMS" apn="nedjmamms" mmsc="http://10.10.111.1" mmsproxy="192.168.52.3" mmsport="9201" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="603" mnc="3" carrier="nedjmamms" apn="nedjmamms" mmsc="http://10.10.111.1" mmsproxy="192.168.52.3" mmsport="3128" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="604" mnc="0" carrier="GPRS MMS" apn="mms.meditel.ma" mmsc="http://mms.meditel.ma:8088/mms" mmsproxy="10.8.8.9" mmsport="8080" type="mms" user="MEDIMMS" password="MEDIMMS" authtype="1"></apn>
+      <apn mcc="604" mnc="0" carrier="Meditel MMS" apn="mms.meditel.ma" mmsc="http://mms.meditel.ma:8088/mms" mmsproxy="10.8.8.9" mmsport="8080" type="mms" user="MEDIMMS" password="MEDIMMS" authtype="0"></apn>
+      <apn mcc="604" mnc="00" carrier="GPRS MMS" apn="mms.meditel.ma" mmsc="http://mms.meditel.ma:8088/mms" mmsproxy="10.8.8.9" mmsport="8080" type="mms" user="MEDIMMS" password="MEDIMMS" authtype="1"></apn>
+      <apn mcc="604" mnc="01" carrier="MMS IAM" apn="mmsiam" mmsc="http://mms:8002/" mmsproxy="10.16.35.50" mmsport="8080" type="mms"></apn>
+      <apn mcc="604" mnc="1" carrier="MMS IAM" apn="mmsiam" mmsc="http://mms:8002/" mmsproxy="10.16.35.50" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="604" mnc="02" carrier="MMS" apn="mms.wana.ma" mmsc="http://mms.wana.ma:38090" mmsproxy="10.86.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="604" mnc="2" carrier="MMS" apn="mms.wana.ma" mmsc="http://mms.wana.ma:38090" mmsproxy="10.86.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="605" mnc="01" carrier="MMS Orange" apn="mms.otun" mmsc="http://mms.orange.tn" mmsproxy="10.12.1.52" mmsport="8080" type="mms"></apn>
+      <apn mcc="605" mnc="1" carrier="MMS Orange" apn="mms.otun" mmsc="http://mms.orange.tn" mmsproxy="10.12.1.52" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="605" mnc="1" carrier="Orange TUN MMS" apn="mms.otun" mmsc="https://mms.orange.tn" mmsproxy="10.12.1.52" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="605" mnc="02" carrier="Tunisie Telecom MMS" apn="mms.tn" mmsc="http://192.168.0.3:19090/was" mmsproxy="192.168.0.2" mmsport="8080" type="mms" user="mms@tt1" password="mms" authtype="1"></apn>
+      <apn mcc="605" mnc="2" carrier="Tunisie Telecom MMS" apn="mms.tn" mmsc="http://192.168.0.3:19090/was" mmsproxy="192.168.0.2" mmsport="8080" type="mms" user="mms@tt1" password="mms" authtype="1"></apn>
+      <apn mcc="605" mnc="2" carrier="Tuntel MMS" apn="mms.tn" mmsc="http://mms/" mmsproxy="213.150.186.106" mmsport="9201" type="mms" user="mms@tt1" password="mms" authtype="0"></apn>
+      <apn mcc="605" mnc="03" carrier="MMS Tunisiana" apn="mms.tunisiana.com" mmsc="http://mmsc.tunisiana.com" mmsproxy="10.3.2.100" mmsport="80" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="605" mnc="3" carrier="Tunisiana MMS" apn="mms.tunisiana.com" mmsc="http://mmsc.tunisiana.com" mmsproxy="10.3.2.100" mmsport="9201" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="606" mnc="0" carrier="Libyana MMS" apn="mms" mmsc="http://62.240.62.180:80" mmsproxy="192.168.8.148" mmsport="8000" type="mms" authtype="0"></apn>
+      <apn mcc="606" mnc="00" carrier="Libyana MMS" apn="mms" mmsc="http://62.240.62.180:80" mmsproxy="192.168.8.148" mmsport="8000" type="mms" authtype="0"></apn>
+      <apn mcc="608" mnc="01" carrier="Orange MMS SN" apn="mms" mmsc="http://mmsalize/servlets/mms" mmsproxy="172.16.30.9" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="608" mnc="1" carrier="Orange MMS SN" apn="mms" mmsc="http://mmsalize/servlets/mms" mmsproxy="172.16.30.9" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="608" mnc="1" carrier="Orange SN MMS" apn="mms" mmsc="http://mmsalize/servlets/mms" mmsproxy="172.16.30.9" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="610" mnc="02" carrier="Orange ML MMS" apn="mms" mmsc="http://10.109.6.2/servlets/mms" mmsproxy="10.109.4.35" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="610" mnc="2" carrier="Orange ML MMS" apn="mms" mmsc="http://10.109.6.2/servlets/mms" mmsproxy="10.109.4.35" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="610" mnc="2" carrier="Orange ML MMS" apn="mms" mmsc="http://10.109.6.2/servlets/mms" mmsproxy="10.109.4.35" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="612" mnc="03" carrier="Omms CI" apn="orangecimms" mmsc="http://172.20.6.1/servlets/mms" mmsproxy="172.20.4.33" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="612" mnc="3" carrier="Omms CI" apn="orangecimms" mmsc="http://172.20.6.1/servlets/mms" mmsproxy="172.20.4.33" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="612" mnc="3" carrier="Orange CI MMS" apn="orangecimms" mmsc="http://172.20.6.1/servlets/mms" mmsproxy="172.20.4.33" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="614" mnc="04" carrier="Orange MMS" apn="orange.mms" mmsc="http://10.10.10.35:38090/was" mmsproxy="10.10.10.36" mmsport="8080" type="mms" user="orange" password="orange"></apn>
+      <apn mcc="614" mnc="4" carrier="Orange MMS" apn="orange.mms" mmsc="http://10.10.10.35:38090/was" mmsproxy="10.10.10.36" mmsport="8080" type="mms" user="orange" password="orange" authtype="3"></apn>
+      <apn mcc="614" mnc="4" carrier="Orange NE MMS" apn="orange.mms" mmsc="http://10.10.35:38090/was" mmsproxy="10.10.10.36" mmsport="8080" type="mms" user="orange" password="orange" authtype="0"></apn>
+      <apn mcc="617" mnc="01" carrier="Orange MMS" apn="orangemms" mmsc="http://10.2.1.20:8514" mmsproxy="10.2.1.20" mmsport="8080" type="mms" user="mmsc" password="mmsc"></apn>
+      <apn mcc="617" mnc="1" carrier="Orange MMS" apn="orangemms" mmsc="http://10.2.1.20:8514" mmsproxy="10.2.1.20" mmsport="8080" type="mms" user="mmsc" password="mmsc" authtype="3"></apn>
+      <apn mcc="617" mnc="1" carrier="Orange MU MMS" apn="orangemms" mmsc="http://1.2.1.20:8514" mmsproxy="10.2.1.20:8080" type="mms" user="mmsc" password="mmsc" authtype="0"></apn>
+      <apn mcc="620" mnc="0" carrier="Glo mms" apn="glo mms" mmsc="http://mms.gloworld.com/mms" mmsproxy="10.161.85.4" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="01" carrier="MTN MMS" apn="mtn mms" mmsc="http://172.17.3.7" mmsproxy="172.17.3.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="1" carrier="MTN MMS" apn="mtn mms" mmsc="http://172.17.3.7" mmsproxy="172.17.3.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="02" carrier="Vodafone_mms" apn="mms" mmsc="http://mms.vodaphone.com.gh/mms" mmsproxy="172.24.97.1" mmsport="9201" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="2" carrier="Vodafone_mms" apn="mms" mmsc="http://mms.vodaphone.com.gh/mms" mmsproxy="172.24.97.1" mmsport="9201" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="03" carrier="Tigo mms" apn="mms.tigo.com.gh" mmsc="http://mms/" mmsproxy="10.4.1.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="3" carrier="Tigo mms" apn="mms.tigo.com.gh" mmsc="http://mms/" mmsproxy="10.4.1.7" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="06" carrier="Airtel mms" apn="mms/airtel mms" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="620" mnc="6" carrier="Airtel mms" apn="mms/airtel mms" mmsc="http://100.1.201.171:10021/mmsc" mmsproxy="100.1.201.172" mmsport="8799" type="mms" authtype="0"></apn>
+      <apn mcc="621" mnc="20" carrier="Airtel MMS" apn="mms.ng.zain.com" mmsc="http://10.210.3.239:9800/mm1" mmsproxy="172.18.254.5" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="621" mnc="20" carrier="Zain NG MMS" apn="mms.ng.zain.com" mmsc="http://172.23.1.12/wapenc" mmsproxy="172.18.254.5" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="621" mnc="30" carrier="MTN MMS" apn="web.gprs.mtnnigeria.net" mmsc="http://10.199.212.8/servlets/mms" mmsproxy="10.199.212.2" type="mms"></apn>
+      <apn mcc="621" mnc="30" carrier="MTN MMS" apn="web.gprs.mtnnigeria.net" mmsc="http://10.199.212.8/servlets/mms" mmsproxy="10.199.212.2" type="mms" authtype="0"></apn>
+      <apn mcc="621" mnc="30" carrier="MTN NG Internet" apn="web.gprs.mtnnigeria.net" mmsc="http://10.199.212.8/servlets/mms" mmsproxy="10.199.212.2" mmsport="8080" type="default,mms" user="web" password="web" authtype="0"></apn>
+      <apn mcc="621" mnc="50" carrier="Glo MMS" apn="glomms" mmsc="http://mms.gloworld.com/mmsc" mmsproxy="10.100.114.144" mmsport="3130" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="621" mnc="50" carrier="Glo MMS" apn="glomms" mmsc="http://mms.gloworld.com/mmsc" mmsproxy="10.100.82.4" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="621" mnc="60" carrier="Etisalat Internet" apn="etisalat" mmsc="http://10.71.170.30:38090/was" mmsproxy="10.71.170.5" mmsport="8080" type="default,mms" authtype="0"></apn>
+      <apn mcc="621" mnc="60" carrier="etisalat MMS" apn="etisalat" mmsc="http://10.71.170.30:38090/was" type="mms"></apn>
+      <apn mcc="621" mnc="60" carrier="etisalat MMS" apn="etisalat" mmsc="http://10.71.170.30:38090/was" type="mms" authtype="0"></apn>
+      <apn mcc="624" mnc="02" carrier="Orange CM" apn="orangecmgprs" mmsc="http://mms.orange.cm" mmsproxy="192.168.122.101" mmsport="8080" type="default,mms" user="orange" password="orange" proxy="192.168.122.101" port="8080"></apn>
+      <apn mcc="624" mnc="2" carrier="Orange CM" apn="orangecmgprs" mmsc="http://mms.orange.cm" mmsproxy="192.168.122.101" mmsport="8080" type="default,mms" user="orange" password="orange" authtype="0"></apn>
+      <apn mcc="624" mnc="2" carrier="Orange CM" apn="orangecmgprs" mmsc="http://mms.orange.cm" mmsproxy="192.168.122.101" mmsport="8080" type="default,mms" user="orange" password="orange" authtype="3" proxy="192.168.122.101" port="8080"></apn>
+      <apn mcc="627" mnc="01" carrier="Orange GQ MMS" apn="orangemms" mmsc="http://192.168.17.34/servlets/mms" mmsproxy="192.168.17.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="627" mnc="1" carrier="Orange GQ MMS" apn="orangemms" mmsc="http://192.168.17.34/servlets/mms" mmsproxy="192.168.17.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="630" mnc="01" carrier="Vodacom MMS" apn="vodalive" mmsc="http://172.24.97.1/mmsc" mmsproxy="172.24.97.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="630" mnc="1" carrier="Vodacom MMS" apn="vodalive" mmsc="http://172.24.97.1/mmsc" mmsproxy="172.24.97.1" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="639" mnc="02" carrier="safaricom mms" apn="safaricom" mmsc="http://mms.gprs.safaricom.com" mmsproxy="172.22.2.38" mmsport="8080" type="mms" user="saf" password="data" authtype="1"></apn>
+      <apn mcc="639" mnc="2" carrier="Safaricom Internet" apn="safaricom" mmsc="http://mms.gprs.safaricom.com" mmsproxy="172.22.2.38" mmsport="8080" type="default,mms" user="saf" password="data" authtype="0" proxy="172.22.2.38" port="8080"></apn>
+      <apn mcc="639" mnc="2" carrier="safaricom mms" apn="safaricom" mmsc="http://mms.gprs.safaricom.com" mmsproxy="172.22.2.38" mmsport="8080" type="mms" user="saf" password="data" authtype="1"></apn>
+      <apn mcc="639" mnc="03" carrier="Airtel mms" apn="mms" mmsc="http://mms.ke.airtel.com:8002" mmsproxy="172.30.9.8" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="639" mnc="03" carrier="mms" apn="ke.celtel.com" mmsc="http://mms.ke.celtel.com/servlets/mms" mmsproxy="172.30.8.50" mmsport="8080" type="mms"></apn>
+      <apn mcc="639" mnc="3" carrier="Airtel mms" apn="mms" mmsc="http://mms.ke.airtel.com:8002" mmsproxy="172.30.9.8" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="639" mnc="05" carrier="Yu Internet" apn="Internet" mmsc="http://10.4.16.22/servlets/mms" mmsproxy="10.4.16.6" mmsport="8080" type="default,supl,mms" proxy="10.4.16.6" port="8080"></apn>
+      <apn mcc="639" mnc="05" carrier="Yu mms" apn="Yu" mmsc="http://10.4.16.22/servlets/mms" mmsproxy="10.4.16.6" mmsport="8080" type="mms"></apn>
+      <apn mcc="639" mnc="5" carrier="Yu Internet" apn="Internet" mmsc="http://10.4.16.22/servlets/mms" mmsproxy="10.4.16.6" mmsport="8080" type="default,supl,mms" proxy="10.4.16.6" port="8080"></apn>
+      <apn mcc="639" mnc="5" carrier="Yu mms" apn="Yu" mmsc="http://10.4.16.22/servlets/mms" mmsproxy="10.4.16.6" mmsport="8080" type="mms"></apn>
+      <apn mcc="639" mnc="07" carrier="Orange MMS" apn="mms.orange.co.ke" mmsc="http://10.36.16.5/servlets/mms" mmsproxy="10.36.17.130" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="639" mnc="7" carrier="Orange KE MMS" apn="mms.orange.co.ke" mmsc="http://10.36.16.5/servlets/mms" mmsproxy="10.36.16.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="640" mnc="04" carrier="Vodacom MMS" apn="mms" mmsc="http://10.154.0.12/mms/" type="mms"></apn>
+      <apn mcc="640" mnc="4" carrier="Vodacom MMS" apn="mms" mmsc="http://10.154.0.12/mms/" type="mms"></apn>
+      <apn mcc="641" mnc="14" carrier="Orange MMS" apn="orangemms" mmsc="http://mms/" type="mms"></apn>
+      <apn mcc="641" mnc="14" carrier="Orange MMS" apn="orangemms" mmsc="http://mms/" type="mms" authtype="0"></apn>
+      <apn mcc="646" mnc="02" carrier="Orange MG MMS" apn="orangemms" mmsc="http://10.152.10.70.38090" mmsproxy="10.150.0.115" mmsport="8080" type="mms" user="mms" password="orange"></apn>
+      <apn mcc="646" mnc="2" carrier="Orange MG MMS" apn="orangemms" mmsc="http://10.152.10.70.38090" mmsproxy="10.150.0.115" mmsport="8080" type="mms" user="mms" password="orange" authtype="3"></apn>
+      <apn mcc="646" mnc="2" carrier="Orange MG MMS" apn="orangemms" mmsc="http://10.152.10.70:38090" mmsproxy="10.150.0.115" mmsport="8080" type="mms" user="mms" password="orange" authtype="0"></apn>
+      <apn mcc="647" mnc="00" carrier="Orange MMS Réunion" apn="orangerun.acte" mmsc="http://mms.orange.re" mmsproxy="192.168.10.200" mmsport="8080" type="mms" user="orange" password="orange"></apn>
+      <apn mcc="647" mnc="02" carrier="OnlyMMS" apn="onlymms" mmsc="http://10.4.85.50:8514" mmsproxy="10.4.85.50" mmsport="8080" type="mms" user="only" password="only" authtype="1"></apn>
+      <apn mcc="647" mnc="10" carrier="Coriolis MMS" apn="mmscoriolis" mmsc="http://mmscoriolis" mmsproxy="10.143.156.6" mmsport="8080" type="mms" mvno_match_data="12" mvno_type="gid"></apn>
+      <apn mcc="647" mnc="10" carrier="MMS" apn="mmssfr" mmsc="http://mms" mmsproxy="10.0.224.145" mmsport="8080" type="mms" user="mms" password="mms"></apn>
+      <apn mcc="647" mnc="10" carrier="MMS" apn="mmssfr" mmsc="http://mms" mmsproxy="10.0.224.145" mmsport="8080" type="mms" user="mms" password="mms" authtype="3"></apn>
+      <apn mcc="647" mnc="10" carrier="SRR MMS" apn="mmssfr" mmsc="http://mms" mmsproxy="10.0.224.145" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="651" mnc="01" carrier="VCL MMS GPRS" apn="mms" mmsc="http://mmsc.vodacom4me.co.ls" mmsproxy="10.113.63.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="651" mnc="1" carrier="VCL MMS GPRS" apn="mms" mmsc="http://mmsc.vodacom4me.co.ls" mmsproxy="10.113.63.11" mmsport="8080" type="mms"></apn>
+      <apn mcc="652" mnc="02" carrier="Orange BW MMS" apn="mms.orange.co.bw" mmsc="http://10.0.0.242/servlets/mms" mmsproxy="10.0.0.226" mmsport="8080" type="mms"></apn>
+      <apn mcc="652" mnc="2" carrier="Orange BW MMS" apn="mms.orange.co.bw" mmsc="http://10.0.0.242/servlets/mms" mmsproxy="10.0.0.226" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="01" carrier="MMS.Vodacom" apn="lte.vodacom.za" mmsc="http://mmsc.vodacom4me.co.za" mmsproxy="196.6.128.13" mmsport="8080" type="mms"></apn>
+      <apn mcc="655" mnc="01" carrier="MMS.Vodacom" apn="mms.vodacom.net" mmsc="http://mmsc.vodacom4me.co.za" mmsproxy="196.6.128.13" mmsport="8080" type="mms"></apn>
+      <apn mcc="655" mnc="1" carrier="MMS.Vodacom" apn="lte.vodacom.za" mmsc="http://mmsc.vodacom4me.co.za" mmsproxy="196.6.128.13" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="1" carrier="MMS.Vodacom" apn="mms.vodacom.net" mmsc="http://mmsc.vodacom4me.co.za" mmsproxy="196.6.128.13" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="1" carrier="Vlive! MMS" apn="mms.vodacom.net" mmsc="http://mmsc.vodacom4me.co.za" mmsproxy="196.6.128.13" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="02" carrier="Telkom Mobile MMS" apn="mms" mmsc="http://mms.8ta.com:38090/was" mmsproxy="41.151.254.162" mmsport="8080" type="mms"></apn>
+      <apn mcc="655" mnc="2" carrier="8.ta MMS" apn="mms" mmsc="http://mms.8ta.com:38090/was" mmsproxy="41.151.254.162" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="2" carrier="Telkom Mobile MMS" apn="mms" mmsc="http://mms.8ta.com:38090/was" mmsproxy="41.151.254.162" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="07" carrier="Cell C MMS" apn="mms" mmsc="http://mms.cmobile.co.za/" mmsproxy="196.31.116.250" mmsport="8080" type="mms"></apn>
+      <apn mcc="655" mnc="07" carrier="Redbull MMS" apn="mms" mmsc="http://mms.cmobile.co.za/" mmsproxy="196.31.116.250" mmsport="8080" type="mms" mvno_match_data="6550713" mvno_type="imsi"></apn>
+      <apn mcc="655" mnc="07" carrier="Virgin_MMS_1" apn="vmms" mmsc="http://mms.virginmobile.co.za" mmsproxy="196.31.116.242" mmsport="8080" type="mms" mvno_match_data="6550710" mvno_type="imsi"></apn>
+      <apn mcc="655" mnc="07" carrier="Virgin_MMS_2" apn="vmms" mmsc="http://mms.virginmobile.co.za" mmsproxy="196.31.116.242" mmsport="9201" type="mms" mvno_match_data="6550710" mvno_type="imsi"></apn>
+      <apn mcc="655" mnc="7" carrier="Cell C MMS" apn="mms" mmsc="http://mms.cmobile.co.za/" mmsproxy="196.31.116.250" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="7" carrier="Cell C mms" apn="mms" mmsc="http://mms.cmobile.co.za" mmsproxy="196.31.116.250" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="655" mnc="7" carrier="Virgin MMS" apn="vmms" mmsc="http://mms.virginmobile.co.za" mmsproxy="196.31.116.242" mmsport="8080" type="mms" authtype="1" mvno_match_data="Virgin" mvno_type="spn"></apn>
+      <apn mcc="655" mnc="7" carrier="Virgin_MMS_1" apn="vmms" mmsc="http://mms.virginmobile.co.za" mmsproxy="196.31.116.242" mmsport="8080" type="mms" authtype="0" mvno_match_data="6550710" mvno_type="imsi"></apn>
+      <apn mcc="655" mnc="7" carrier="Virgin_MMS_2" apn="vmms" mmsc="http://mms.virginmobile.co.za" mmsproxy="196.31.116.242" mmsport="9201" type="mms" authtype="0" mvno_match_data="6550710" mvno_type="imsi"></apn>
+      <apn mcc="655" mnc="10" carrier="MTN MMS" apn="myMTN" mmsc="http://mms.mtn.co.za/mms/wapenc" mmsproxy="196.11.240.241" mmsport="8080" type="mms" user="mtnmms" password="mtnmms" authtype="0"></apn>
+      <apn mcc="655" mnc="10" carrier="MTN MMS" apn="myMTN" mmsc="http://mms.mtn.co.za/mms/wapenc" mmsproxy="196.11.240.241" mmsport="8080" type="mms" user="mtnmms" password="mtnmms" authtype="1"></apn>
+      <apn mcc="704" mnc="01" carrier="MMS CLARO" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms"></apn>
+      <apn mcc="704" mnc="1" carrier="Guatemala:Claro:MMS" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="704" mnc="1" carrier="MMS CLARO" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="704" mnc="02" carrier="MMS TIGO" apn="mms.tigo.gt" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms"></apn>
+      <apn mcc="704" mnc="2" carrier="Guatemala:Tigo:Mms" apn="mms.tigo.gt" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="1"></apn>
+      <apn mcc="704" mnc="2" carrier="MMS TIGO" apn="mms.tigo.gt" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="0"></apn>
+      <apn mcc="704" mnc="03" carrier="Movistar MMS" apn="mms.movistar.gt" mmsc="http://mms.movistar.gt" mmsproxy="10.12.22.1" mmsport="80" type="mms" user="movistargt" password="movistargt" authtype="1"></apn>
+      <apn mcc="704" mnc="3" carrier="Guatemala:Movistar:MMS" apn="mms.movistar.gt" mmsc="http://mms.movistar.gt" mmsproxy="10.12.22.1" mmsport="80" type="mms" user="movistargt" password="movistargt" authtype="1"></apn>
+      <apn mcc="704" mnc="3" carrier="Movistar MMS" apn="mms.movistar.gt" mmsc="http://mms.movistar.gt" mmsproxy="10.12.22.1" mmsport="80" type="mms" user="movistargt" password="movistargt" authtype="1"></apn>
+      <apn mcc="704" mnc="030" carrier="Movistar MMS" apn="mms.movistar.gt" mmsc="http://mms.movistar.gt" mmsproxy="10.12.22.1" mmsport="80" type="mms" user="movistargt" password="movistargt" authtype="1"></apn>
+      <apn mcc="706" mnc="01" carrier="MMS CLARO" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms"></apn>
+      <apn mcc="706" mnc="1" carrier="El Salvador:Claro:MMS" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="706" mnc="1" carrier="MMS CLARO" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="706" mnc="02" carrier="MMS" apn="wap.digicelsv.com" mmsc="http://mmc.digiceljamaica.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="8080" type="mms"></apn>
+      <apn mcc="706" mnc="2" carrier="El Salvador:Digicel:Mms" apn="wap.digicelsv.com" mmsc="http://172.26.5.132/servlets/mms" mmsproxy="172.26.5.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="706" mnc="2" carrier="MMS" apn="wap.digicelsv.com" mmsc="http://mmc.digiceljamaica.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="706" mnc="03" carrier="MMS Tigo" apn="mms.tigo.sv" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms"></apn>
+      <apn mcc="706" mnc="3" carrier="El Salvador:Tigo:Mms" apn="mms.tigo.sv" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="1"></apn>
+      <apn mcc="706" mnc="3" carrier="MMS Tigo" apn="mms.tigo.sv" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="0"></apn>
+      <apn mcc="706" mnc="04" carrier="Movistar MMS" apn="mms.movistar.sv" mmsc="http://mms.movistar.sv" mmsproxy="10.12.20.1" mmsport="80" type="mms" user="movistarsv" password="movistarsv" authtype="1"></apn>
+      <apn mcc="706" mnc="4" carrier="El Salvador:Movistar:MMS" apn="mms.movistar.sv" mmsc="http://mms.movistar.sv" mmsproxy="10.12.20.1" mmsport="80" type="mms" user="movistarsv" password="movistarsv" authtype="1"></apn>
+      <apn mcc="706" mnc="4" carrier="Movistar MMS" apn="mms.movistar.sv" mmsc="http://mms.movistar.sv" mmsproxy="10.12.20.1" mmsport="80" type="mms" user="movistarsv" password="movistarsv" authtype="1"></apn>
+      <apn mcc="706" mnc="040" carrier="Movistar MMS" apn="mms.movistar.sv" mmsc="http://mms.movistar.sv" mmsproxy="10.12.20.1" mmsport="80" type="mms" user="movistarsv" password="movistarsv" authtype="1"></apn>
+      <apn mcc="708" mnc="00" carrier="MMS Claro" apn="mms.ideasclaro" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="708" mnc="001" carrier="MMS Claro" apn="mms.ideasclaro" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms"></apn>
+      <apn mcc="708" mnc="1" carrier="Honduras:Claro:MMS" apn="mms.megatel.hn" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mmsmegatel" password="mmsmegatel" authtype="1"></apn>
+      <apn mcc="708" mnc="1" carrier="MMS Claro" apn="mms.ideasclaro" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="708" mnc="02" carrier="MMS TIGO" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms"></apn>
+      <apn mcc="708" mnc="2" carrier="Honduras:Tigo:Mms" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="1"></apn>
+      <apn mcc="708" mnc="2" carrier="MMS TIGO" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="0"></apn>
+      <apn mcc="708" mnc="04" carrier="Honduras:Digicel:Mms" apn="wap.digicelhn.com" mmsc="http://mms.digicelsv.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="708" mnc="04" carrier="Honduras:Digicel:Modem" apn="wap.digicelhn.com" mmsc="http://www.digicelive.com" type="dun" authtype="1" proxy="172.26.5.12" port="8080"></apn>
+      <apn mcc="708" mnc="4" carrier="Honduras:Digicel:Mms" apn="wap.digicelhn.com" mmsc="http://mms.digicelsv.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="708" mnc="4" carrier="Honduras:Digicel:Modem" apn="wap.digicelhn.com" mmsc="http://www.digicelive.com" type="dun" authtype="1" proxy="172.26.5.12" port="8080"></apn>
+      <apn mcc="708" mnc="020" carrier="MMS TIGO" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms"></apn>
+      <apn mcc="708" mnc="20" carrier="Honduras:Tigo: Mms" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="1"></apn>
+      <apn mcc="708" mnc="20" carrier="MMS TIGO" apn="mms.tigo.hn" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" authtype="0"></apn>
+      <apn mcc="708" mnc="040" carrier="Honduras:Digicel:Mms:2" apn="wap.digicelhn.com" mmsc="http://mms.digicelsv.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="708" mnc="40" carrier="Honduras:Digicel:Mms:2" apn="wap.digicelhn.com" mmsc="http://mms.digicelsv.com/servlets/mms" mmsproxy="172.26.5.12" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="710" mnc="21" carrier="Enitel MMS" apn="mms.indeasalo.ni" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="710" mnc="21" carrier="Nicaragua:Enitel:MMS" apn="mms.emovil" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mmsemovil" password="mmsemovil" authtype="1"></apn>
+      <apn mcc="710" mnc="30" carrier="Movistar MMS" apn="mms.movistar.ni" mmsc="http://mms.movistar.ni" mmsproxy="10.12.23.1" mmsport="80" type="mms" user="movistarni" password="movistarni" authtype="1"></apn>
+      <apn mcc="710" mnc="73" carrier="Enitel MMS" apn="mms.indeasalo.ni" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="710" mnc="73" carrier="Nicaragua:Alo:MMS" apn="mms.ideasalo.ni" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="710" mnc="300" carrier="Movistar MMS" apn="mms.movistar.ni" mmsc="http://mms.movistar.ni" mmsproxy="10.12.23.1" mmsport="80" type="mms" user="movistarni" password="movistarni" authtype="1"></apn>
+      <apn mcc="710" mnc="300" carrier="Nicaragua:Movistar:MMS" apn="mms.movistar.ni" mmsc="http://mms.movistar.ni" mmsproxy="10.12.23.1" mmsport="80" type="mms" user="movistarni" password="movistarni" authtype="1"></apn>
+      <apn mcc="710" mnc="730" carrier="Enitel MMS" apn="mms.indeasalo.ni" mmsc="http://10.6.32.27/servlets/mms" mmsproxy="10.6.32.2" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="712" mnc="01" carrier="Costar Rica:Kolbi:Modem" apn="kolbi" mmsc="http://mimundokolbi.ice.cr" mmsport="8080" type="dun" authtype="1"></apn>
+      <apn mcc="712" mnc="01" carrier="Kolbi Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="01" carrier="Kolbi_Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="1" carrier="Costar Rica:Kolbi:Internet" apn="kolbi" mmsc="http://mimundokolbi.ice.cr" mmsport="8080" type="default" authtype="1"></apn>
+      <apn mcc="712" mnc="1" carrier="Costar Rica:Kolbi:MMS" apn="mmscelular" mmsc="http://mmsice" mmsproxy="172.27.10.4" mmsport="8080" type="mms" authtype="1" port="8080"></apn>
+      <apn mcc="712" mnc="1" carrier="Kolbi_Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="712" mnc="02" carrier="Kolbi Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="02" carrier="Kolbi_Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="2" carrier="Kolbi_Multimedia" apn="kolbimundo" mmsc="http://mmsice" mmsproxy="10.184.202.24" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="03" carrier="MMS CLARO CR" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms"></apn>
+      <apn mcc="712" mnc="3" carrier="Costa Rica:Claro:Internet" apn="internet.ideasclaro" mmsc="http://wap.ideasclaro.com" type="default" authtype="1" port="8080"></apn>
+      <apn mcc="712" mnc="3" carrier="Costa Rica:Claro:MMS" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="712" mnc="3" carrier="MMS CLARO CR" apn="mms.ideasclaro" mmsc="http://mms.ideasclaro.com:8002" mmsproxy="216.230.133.66" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="712" mnc="04" carrier="Movistar MMS" apn="mms.movistar.cr" mmsc="http://mms.movistar.cr" mmsproxy="10.221.79.83" mmsport="80" type="mms" user="movistarcr" password="movistarcr" authtype="1"></apn>
+      <apn mcc="712" mnc="4" carrier="Costa Rica:Movistar:Internet" apn="internet.movistar.cr" mmsc="http://www.movistar.co.cr" type="default" user="movistarcr" password="movistarcr" authtype="1"></apn>
+      <apn mcc="712" mnc="4" carrier="Costa Rica:Movistar:MMS" apn="mms.movistar.cr" mmsc="http://mms.movistar.cr" mmsproxy="10.221.79.83" mmsport="80" type="mms" user="movistarcr" password="movistarcr" authtype="1"></apn>
+      <apn mcc="712" mnc="4" carrier="Movistar MMS" apn="mms.movistar.cr" mmsc="http://mms.movistar.cr" mmsproxy="10.221.79.83" mmsport="80" type="mms" user="movistarcr" password="movistarcr" authtype="1"></apn>
+      <apn mcc="712" mnc="019" carrier="MMS Tuyo" apn="tm7mms" mmsc="http://mmsc.tuyomovil.com:1981" mmsproxy="10.186.181.5" mmsport="3128" type="mms"></apn>
+      <apn mcc="712" mnc="19" carrier="MMS Tuyo" apn="tm7mms" mmsc="http://mmsc.tuyomovil.com:1981" mmsproxy="10.186.181.5" mmsport="3128" type="mms"></apn>
+      <apn mcc="712" mnc="190" carrier="MMS Tuyo" apn="tm7mms" mmsc="http://mmsc.tuyomovil.com:1981" mmsproxy="10.186.181.5" mmsport="3128" type="mms"></apn>
+      <apn mcc="714" mnc="01" carrier="MMS" apn="apn02.cwpanama.com.pa" mmsc="http://mms.zonamovil.com.pa" mmsproxy="172.25.3.5" mmsport="8080" type="mms"></apn>
+      <apn mcc="714" mnc="1" carrier="MMS" apn="apn02.cwpanama.com.pa" mmsc="http://mms.zonamovil.com.pa" mmsproxy="172.25.3.5" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="714" mnc="1" carrier="Panama:CW:Internet" apn="apn01.cwpanama.com.pa" mmsc="http://wap.masmovil.com.pa" type="default" authtype="1"></apn>
+      <apn mcc="714" mnc="1" carrier="Panama:CW:MMS" apn="apn02.cwpanama.com.pa" mmsc="http://mms.zonamovil.com.pa" mmsproxy="172.25.3.5" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="714" mnc="02" carrier="Movistar MMS" apn="mms.movistar.pa" mmsc="http://mms.movistar.pa" mmsproxy="10.12.21.1" mmsport="80" type="mms" user="movistarpamms" password="movistarpa" authtype="1"></apn>
+      <apn mcc="714" mnc="2" carrier="Movistar MMS" apn="mms.movistar.pa" mmsc="http://mms.movistar.pa" mmsproxy="10.12.21.1" mmsport="80" type="mms" user="movistarpamms" password="movistarpa" authtype="1"></apn>
+      <apn mcc="714" mnc="03" carrier="MMS Claro" apn="mms.claro.com.pa" mmsc="http://www.claro.com.pa/mms/" mmsproxy="10.240.3.129" mmsport="8799" type="mms" user="CLAROMMS" password="CLAROMMS" authtype="1"></apn>
+      <apn mcc="714" mnc="3" carrier="MMS Claro" apn="mms.claro.com.pa" mmsc="http://www.claro.com.pa/mms/" mmsproxy="10.240.3.129" mmsport="8799" type="mms" user="CLAROMMS" password="CLAROMMS" authtype="1"></apn>
+      <apn mcc="714" mnc="3" carrier="Panama:Claro:MMS" apn="mms.claro.com.pa" mmsc="http://www.claro.com.pa/mms/" mmsproxy="10.240.3.129" mmsport="8799" type="mms" user="CLAROMMS" password="CLAROMMS" authtype="1"></apn>
+      <apn mcc="714" mnc="04" carrier="MMS" apn="wap.digicelpanama.com" mmsc="http://mmc.digicelpanama.com/servlets/mms" mmsproxy="172.27.99.99" mmsport="8080" type="mms"></apn>
+      <apn mcc="714" mnc="4" carrier="MMS" apn="wap.digicelpanama.com" mmsc="http://mmc.digicelpanama.com/servlets/mms" mmsproxy="172.27.99.99" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="714" mnc="4" carrier="Panama:Digicel:Mms" apn="wap.digicelpanama.com" mmsc="http://mmc.digicelpanama.com/servlets/mms" mmsproxy="172.27.99.99" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="714" mnc="020" carrier="Movistar MMS" apn="mms.movistar.pa" mmsc="http://mms.movistar.pa" mmsproxy="10.12.21.1" mmsport="80" type="mms" user="movistarpamms" password="movistarpa" authtype="1"></apn>
+      <apn mcc="714" mnc="20" carrier="Movistar MMS" apn="mms.movistar.pa" mmsc="http://mms.movistar.pa" mmsproxy="10.12.21.1" mmsport="80" type="mms" user="movistarpamms" password="movistarpa" authtype="1"></apn>
+      <apn mcc="714" mnc="20" carrier="Panama:Movistar:MMS" apn="mms.movistar.pa" mmsc="http://mms.movistar.pa" mmsproxy="10.12.21.1" mmsport="80" type="mms" user="movistarpamms" password="movistarpa" authtype="1"></apn>
+      <apn mcc="714" mnc="040" carrier="Panama:Digicel:Mms:2" apn="wap.digicelpanama.com" mmsc="http://mmc.digicelpanama.com/servlets/mms" mmsproxy="172.27.99.99" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="714" mnc="40" carrier="Panama:Digicel:Mms:2" apn="wap.digicelpanama.com" mmsc="http://mmc.digicelpanama.com/servlets/mms" mmsproxy="172.27.99.99" mmsport="9201" type="mms" authtype="1"></apn>
+      <apn mcc="716" mnc="06" carrier="Movistar MMS" apn="mms.movistar.pe" mmsc="http://mmsc.telefonicamovistar.com.pe:8088/mms/" mmsproxy="200.4.196.118" mmsport="8080" type="mms" user="movistar@mms" password="movistar" authtype="1"></apn>
+      <apn mcc="716" mnc="6" carrier="Movistar MMS" apn="mms.movistar.pe" mmsc="http://mmsc.telefonicamovistar.com.pe:8088/mms/" mmsproxy="200.4.196.118" mmsport="8080" type="mms" user="movistar@mms" password="movistar" authtype="1"></apn>
+      <apn mcc="716" mnc="10" carrier="CLARO MMS" apn="mms.claro.pe" mmsc="http://claro/servlets/mms" mmsproxy="192.168.231.30" mmsport="80" type="mms" user="claro" password="claro" authtype="1"></apn>
+      <apn mcc="716" mnc="15" carrier="Bitel - MMS" apn="bitel-mms" mmsc="http://181.176.241.99:8080" mmsproxy="10.121.144.3" mmsport="8000" type="mms" authtype="1" protocol="IP" roaming_protocol="IP"></apn>
+      <apn mcc="716" mnc="17" carrier="Entel MMS" apn="mms.entel.pe" mmsc="http://mms.entel.pe" mmsproxy="10.0.215.74" mmsport="8080" type="mms" authtype="0" protocol="IP"></apn>
+      <apn mcc="716" mnc="17" carrier="Nextel MMS" apn="mms.nextel.com.pe" mmsc="http://mms.nextel.pe" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="722" mnc="01" carrier="Quam_MMS" apn="mms.movil" mmsc="http://mms.quam.com.ar" mmsproxy="200.68.32.239" mmsport="9090" type="mms" user="mms" password="mms" authtype="1" mvno_match_data="CELULAR" mvno_type="spn"></apn>
+      <apn mcc="722" mnc="01" carrier="Quam_MMS" apn="mms.movil" mmsc="http://mms.quam.com.ar" mmsproxy="200.68.32.239" mmsport="9090" type="mms" user="mms" password="mms" authtype="1" mvno_match_data="QUAM" mvno_type="spn"></apn>
+      <apn mcc="722" mnc="07" carrier="Movistar MMS" apn="mms.gprs.unifon.com.ar" mmsc="http://mms.movistar.com.ar" mmsproxy="200.68.32.239" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="722" mnc="7" carrier="Argentina:Movistar:MMS" apn="mms.gprs.unifon.com.ar" mmsc="http://mms.movistar.com.ar" mmsproxy="200.68.32.239" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="722" mnc="31" carrier="Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,supl,dun,mms"></apn>
+      <apn mcc="722" mnc="31" carrier="Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,supl,mms"></apn>
+      <apn mcc="722" mnc="34" carrier="Argentina:Personal:MMS" apn="mms" mmsc="http://mms.personal.com" mmsproxy="172.25.7.31" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="722" mnc="34" carrier="Personal MMS" apn="mms" mmsc="http://mms.personal.com" mmsproxy="172.25.7.31" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="722" mnc="36" carrier="Argentina:Nuestro:MMS" apn="mms.nuestro.com.ar" mmsc="http://mms.nuestro.com.ar" mmsproxy="172.16.0.20" mmsport="8080" type="mms" user="mms" authtype="0"></apn>
+      <apn mcc="722" mnc="310" carrier="Argentina:Claro:Internet Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,mms" authtype="0"></apn>
+      <apn mcc="722" mnc="310" carrier="Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,supl,dun,mms"></apn>
+      <apn mcc="722" mnc="310" carrier="Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,supl,dun,mms" authtype="0"></apn>
+      <apn mcc="722" mnc="310" carrier="Claro AR" apn="igprs.claro.com.ar" mmsc="http://mms.claro.com.ar" type="default,supl,mms"></apn>
+      <apn mcc="722" mnc="340" carrier="Argentina:Personal :MMS" apn="mms" mmsc="http://mms.personal.com" mmsproxy="172.25.7.31" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="722" mnc="341" carrier="Argentina:Personal: MMS" apn="mms" mmsc="http://mms.personal.com" mmsproxy="172.25.7.31" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="722" mnc="341" carrier="Personal MMS" apn="mms" mmsc="http://mms.personal.com" mmsproxy="172.25.7.31" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="724" mnc="01" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="02" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="2" carrier="TIM CONNECT" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,dun,mms" user="tim" password="tim" authtype="1"></apn>
+      <apn mcc="724" mnc="2" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="03" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="3" carrier="TIM CONNECT" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,dun,mms" user="tim" password="tim" authtype="1"></apn>
+      <apn mcc="724" mnc="3" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="04" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="4" carrier="TIM CONNECT" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,dun,mms" user="tim" password="tim" authtype="1"></apn>
+      <apn mcc="724" mnc="4" carrier="TIM Connect" apn="timbrasil.br" mmsc="http://mms.tim.br" mmsproxy="200.179.66.242" mmsport="8080" type="default,supl,mms" user="tim" password="tim" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="05" carrier="Claro Foto" apn="mms.claro.com.br" mmsc="http://mms.claro.com.br" mmsproxy="200.169.126.10" mmsport="8799" type="mms" user="claro" password="claro" authtype="1"></apn>
+      <apn mcc="724" mnc="5" carrier="Claro Foto" apn="mms.claro.com.br" mmsc="http://mms.claro.com.br" mmsproxy="200.169.126.10" mmsport="8799" type="mms" user="claro" password="claro" authtype="1"></apn>
+      <apn mcc="724" mnc="06" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="6" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="6" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="07" carrier="SCTL MMS" apn="mms.sercomtel.com.br" mmsc="http://mms.claro.com.br" mmsproxy="200.169.126.10" mmsport="8799" type="mms" user="sercomtel" password="sercomtel"></apn>
+      <apn mcc="724" mnc="10" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="10" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="11" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="11" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="015" carrier="Sercomtel" apn="mms.sercomtel.com.br" mmsc="http://mms.claro.com.br" mmsproxy="200.169.126.10" mmsport="8799" type="mms" authtype="1"></apn>
+      <apn mcc="724" mnc="15" carrier="Sercomtel:MMS" apn="mms.sercomtel.com.br" mmsc="http://mms.claro.com.br" mmsproxy="200.169.126.10" mmsport="8799" type="mms" user="sercomtel" password="sercomtel" authtype="1"></apn>
+      <apn mcc="724" mnc="16" carrier="MMS GPRS" apn="mmsgprs.oi.com.br" mmsc="http://200.222.42.204:8002" mmsproxy="192.168.10.50" mmsport="3128" type="mms" user="oimms" password="oioioi" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="16" carrier="Oi:MMS:3" apn="mmsgprs.oi.com.br" mmsc="http://200.222.42.204:8002" mmsproxy="192.168.10.50" mmsport="3128" type="mms" user="oimms" password="oioioi" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="19" carrier="MMS Telemig" apn="mmsgprs.telemigcelular.com.br" mmsc="http://mms.telemigcelular.com.br" mmsproxy="200.192.230.142" mmsport="8080" type="mms" user="celular" password="celular"></apn>
+      <apn mcc="724" mnc="19" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="23" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="23" carrier="Vivo MMS" apn="mms.vivo.com.br" mmsc="http://termnat.vivomms.com.br:8088/mms" mmsproxy="200.142.130.104" mmsport="80" type="mms" user="vivo" password="vivo" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="24" carrier="Oi:MMS:2" apn="mmsgprs.oi.com.br" mmsc="http://200.222.42.204:8002" mmsproxy="192.168.10.50" mmsport="3128" type="mms" user="oimms" password="oioioi" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="31" carrier="MMS GPRS" apn="mmsgprs.oi.com.br" mmsc="http://200.222.42.204:8002" mmsproxy="192.168.10.50" mmsport="3128" type="mms" user="oimms" password="oioioi" authtype="1" protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="31" carrier="Oi:MMS:1" apn="mmsgprs.oi.com.br" mmsc="http://200.222.42.204:8002" mmsproxy="192.168.10.50" mmsport="3128" type="mms" user="oimms" password="oioioi" authtype="1" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="724" mnc="032" carrier="CTBC" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="724" mnc="32" carrier="CTBC:MMS:1" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="mms" user="CTBC" password="1212" authtype="1"></apn>
+      <apn mcc="724" mnc="033" carrier="CTBC" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="724" mnc="33" carrier="CTBC:MMS:2" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="mms" user="CTBC" password="1212" authtype="1"></apn>
+      <apn mcc="724" mnc="034" carrier="CTBC" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="default,supl,mms" authtype="1"></apn>
+      <apn mcc="724" mnc="34" carrier="CTBC:MMS:3" apn="mms.ctbc.br" mmsc="http://mms.ctbccelular.com.br/was" mmsproxy="172.29.7.70" mmsport="8080" type="mms" user="CTBC" password="1212" authtype="1"></apn>
+      <apn mcc="724" mnc="039" carrier="Nextel" apn="mms.nextel3g.net.br" mmsc="http://3gmms.nextel3g.net.br" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="724" mnc="39" carrier="Nextel MMS" apn="mms.nextel3g.net.br" mmsc="http://3gmms.nextel3g.net.br" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="724" mnc="39" carrier="Nextel MMS" apn="mms.nextel3g.net.br" mmsc="http://3gmms.nextel3g.net.br" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0" protocol="IPV4V6" roaming_protocol="IPV4V6"></apn>
+      <apn mcc="730" mnc="01" carrier="MMS Entel" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="730" mnc="1" carrier="Chile:Entel:MMS Entel PCS:1" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="730" mnc="1" carrier="MMS Entel" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="730" mnc="02" carrier="Movistar MMS" apn="mms.tmovil.cl" mmsc="http://mms.movistar.cl" mmsproxy="172.17.8.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="730" mnc="2" carrier="Movistar MMS" apn="mms.tmovil.cl" mmsc="http://mms.movistar.cl" mmsproxy="172.17.8.10" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="730" mnc="03" carrier="MMS Claro" apn="mms.clarochile.cl" mmsc="http://mms.clarochile.cl" mmsproxy="172.23.200.200" mmsport="8080" type="mms" user="clarochile" password="clarochile" authtype="1"></apn>
+      <apn mcc="730" mnc="3" carrier="Chile:Claro:MMS" apn="mms.clarochile.cl" mmsc="http://mms.clarochile.cl" mmsproxy="172.23.200.200" mmsport="8080" type="mms" user="clarochile" password="clarochile" authtype="1"></apn>
+      <apn mcc="730" mnc="3" carrier="MMS Claro" apn="mms.clarochile.cl" mmsc="http://mms.clarochile.cl" mmsproxy="172.23.200.200" mmsport="8080" type="mms" user="clarochile" password="clarochile" authtype="1"></apn>
+      <apn mcc="730" mnc="08" carrier="MMS" apn="mms.vtr.com" mmsc="http://192.168.94.162:19090/was" mmsproxy="192.168.94.210" mmsport="9028" type="mms" user="mms" authtype="0"></apn>
+      <apn mcc="730" mnc="8" carrier="MMS" apn="mms.vtr.com" mmsc="http://192.168.94.162:19090/was" mmsproxy="192.168.94.210" mmsport="9028" type="mms" user="mms" authtype="0"></apn>
+      <apn mcc="730" mnc="09" carrier="MMS Nextel" apn="mms.nextelmovil.cl" mmsc="http://3gmms.nextelmovil.cl" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="730" mnc="9" carrier="Nextel MMS" apn="mms.nextelmovil.cl" mmsc="http://3gmms.nextelmovil.cl" mmsproxy="129.192.129.104" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="730" mnc="10" carrier="Chile:Entel:MMS Entel PCS:2" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="730" mnc="10" carrier="MMS Entel" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="730" mnc="10" carrier="MMS Entel PCS" apn="mms.entelpcs.cl" mmsc="http://mmsc.entelpcs.cl" mmsproxy="10.99.0.10" mmsport="8080" type="mms" user="entelpcs" password="entelpcs" authtype="1"></apn>
+      <apn mcc="732" mnc="12" carrier="Movistar MMS" apn="mms.movistar.com.co" mmsc="http://mms.movistar.com.co" mmsproxy="192.168.222.7" mmsport="9001" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="732" mnc="101" carrier="Colombia:Comcel:MMS" apn="mms.comcel.com.co" mmsc="http://www.comcel.com.co/mms/" mmsproxy="198.228.90.225" mmsport="8799" type="mms" user="COMCELMMS" password="COMCELMMS" authtype="1"></apn>
+      <apn mcc="732" mnc="101" carrier="MMS Comcel 3GSM" apn="mms.comcel.com.co" mmsc="http://www.comcel.com.co/mms/" mmsproxy="198.228.90.225" mmsport="8799" type="mms" user="COMCELMMS" password="COMCELMMS" authtype="1"></apn>
+      <apn mcc="732" mnc="103" carrier="TIGO Multimedia" apn="mms.colombiamovil.com.co" mmsc="http://mms.ola.com.co" mmsproxy="190.102.206.48" mmsport="8080" type="mms" user="mms-cm1900" password="mms-cm1900" authtype="1"></apn>
+      <apn mcc="732" mnc="111" carrier="TIGO Multimedia" apn="mms.colombiamovil.com.co" mmsc="http://mms.ola.com.co" mmsproxy="190.102.206.48" mmsport="8080" type="mms" user="mms-cm1900" password="mms-cm1900" authtype="1"></apn>
+      <apn mcc="732" mnc="123" carrier="Movistar MMS" apn="mms.movistar.com.co" mmsc="http://mms.movistar.com.co" mmsproxy="192.168.222.7" mmsport="9001" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="734" mnc="01" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="734" mnc="1" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="734" mnc="1" carrier="Venezuela:Digitel:MMS:1" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="734" mnc="02" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="734" mnc="2" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="734" mnc="2" carrier="Venezuela:Digitel:MMS:2" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="734" mnc="03" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms"></apn>
+      <apn mcc="734" mnc="3" carrier="MMS" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="734" mnc="3" carrier="Venezuela:Digitel:MMS:3" apn="expresate.digitel.ve" mmsc="http://mms.412.com.ve/servlets/mms" mmsproxy="10.99.0.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="734" mnc="04" carrier="Movistar MMS" apn="mms.movistar.ve" mmsc="http://mms.movistar.com.ve:8088/mms" mmsproxy="200.35.64.73" mmsport="9001" type="mms"></apn>
+      <apn mcc="734" mnc="4" carrier="Movistar MMS" apn="mms.movistar.ve" mmsc="http://mms.movistar.com.ve:8088/mms" mmsproxy="200.35.64.73" mmsport="9001" type="mms" authtype="0"></apn>
+      <apn mcc="734" mnc="4" carrier="Venezuela:Movistar:MMS" apn="mms.movistar.ve" mmsc="http://mms.movistar.com.ve:8088/mms" mmsproxy="200.35.64.73" mmsport="9001" type="mms" authtype="1"></apn>
+      <apn mcc="734" mnc="06" carrier="MMS" apn="mm.movilnet.com.ve" mmsc="http://mms2.movilnet.com.ve/servlets/mms" mmsproxy="192.168.16.12" mmsport="8080" type="mms"></apn>
+      <apn mcc="734" mnc="6" carrier="MMS" apn="mm.movilnet.com.ve" mmsc="http://mms2.movilnet.com.ve/servlets/mms" mmsproxy="192.168.16.12" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="734" mnc="6" carrier="Venezuela:Movilnet:MMS" apn="mm.movilnet.com.ve" mmsc="http://mms2.movilnet.com.ve/servlets/mms" mmsproxy="192.168.16.12" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="736" mnc="01" carrier="VIVAMMS" apn="mms.nuevatel.com" mmsc="http://mmsgw.nuevatel.com:1981" mmsproxy="192.168.101.4" mmsport="3128" type="mms" authtype="1"></apn>
+      <apn mcc="736" mnc="1" carrier="VIVAMMS" apn="mms.nuevatel.com" mmsc="http://mmsgw.nuevatel.com:1981" mmsproxy="192.168.101.4" mmsport="3128" type="mms" authtype="1"></apn>
+      <apn mcc="736" mnc="02" carrier="ENTEL MMS GPRS" apn="mms.movil.com.bo" mmsc="http://mms.movil.com.bo/servlets/mms" mmsproxy="172.27.7.10" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="736" mnc="03" carrier="MMSTIGO" apn="mms.tigo.bo" mmsc="http://mms" mmsproxy="172.25.100.8" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="738" mnc="01" carrier="Guyana:Digicel:Mms" apn="wap.digicelgy.com" mmsc="http://mmc.digicelgy.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="738" mnc="01" carrier="Guyana:Digicel:Modem" apn="wap.digicelgy.com" mmsc="http://www.digicelive.com" type="dun" user="wap" password="wap" authtype="1" proxy="172.20.6.12" port="8080"></apn>
+      <apn mcc="738" mnc="1" carrier="Guyana:Digicel:Mms" apn="wap.digicelgy.com" mmsc="http://mmc.digicelgy.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="740" mnc="0" carrier="Ecuador:Movistar:MMS" apn="mms.movistar.com.ec" mmsc="http://mms.movistar.com.ec:8088/mms/" mmsproxy="10.3.5.50" mmsport="9001" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="740" mnc="00" carrier="Movistar MMS" apn="mms.movistar.com.ec" mmsc="http://mms.movistar.com.ec:8088/mms/" mmsproxy="10.3.5.50" mmsport="9001" type="mms" user="movistar" password="movistar" authtype="1"></apn>
+      <apn mcc="740" mnc="01" carrier="MMS Claro" apn="mms.claro.com.ec" mmsc="http://iesmms.porta.com.ec/" mmsproxy="216.250.208.94" mmsport="8799" type="mms" user="portamms" password="portamms2003" authtype="1"></apn>
+      <apn mcc="740" mnc="1" carrier="Ecuador:Claro:MMS" apn="mms.claro.com.ec" mmsc="http://iesmms.porta.com.ec" mmsproxy="216.250.208.94" mmsport="8799" type="mms" user="portamms" password="portamms2003" authtype="1"></apn>
+      <apn mcc="740" mnc="1" carrier="MMS Claro" apn="mms.claro.com.ec" mmsc="http://iesmms.porta.com.ec/" mmsproxy="216.250.208.94" mmsport="8799" type="mms" user="portamms" password="portamms2003" authtype="1"></apn>
+      <apn mcc="740" mnc="02" carrier="CNT MMS" apn="mms.alegro.net.ec" mmsc="http://mms.alegro.net.ec/mms/" mmsproxy="10.4.85.3" mmsport="8080" type="mms"></apn>
+      <apn mcc="740" mnc="2" carrier="CNT MMS" apn="mms.alegro.net.ec" mmsc="http://mms.alegro.net.ec/mms/" mmsproxy="10.4.85.3" mmsport="8080" type="mms" authtype="0"></apn>
+      <apn mcc="740" mnc="2" carrier="Ecuador:Alegro:Internet" apn="wap.alegro.net.ec" mmsc="www.alegro.com.ec/alegrowap/default.aspx" mmsproxy="10.4.85.3" type="default" authtype="1" port="8080"></apn>
+      <apn mcc="740" mnc="2" carrier="Ecuador:Alegro:Mms" apn="mms.alegro.net.ec" mmsc="http://mms.alegro.com.ec" mmsproxy="10.4.85.3" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="740" mnc="010" carrier="MMS Claro" apn="mms.claro.com.ec" mmsc="http://iesmms.porta.com.ec/" mmsproxy="216.250.208.94" mmsport="8799" type="mms" user="portamms" password="portamms2003" authtype="1"></apn>
+      <apn mcc="744" mnc="01" carrier="Paraguay:Voxx:Modem" apn="vox.wap" mmsc="http://www.vox.com.py/" mmsproxy="172.24.97.29" type="dun" authtype="1" port="8080"></apn>
+      <apn mcc="744" mnc="01" carrier="VOX MMS" apn="vox.mms" mmsc="http://mms.vox.com.py/mmsc" mmsproxy="172.24.97.29" mmsport="8080" type="mms" user="vox" password="vox" authtype="1"></apn>
+      <apn mcc="744" mnc="1" carrier="Paraguay:Voxx:Mms" apn="vox.mms" mmsc="http://srvvirtual.vox.com.py/mmsc" mmsproxy="172.24.97.29" mmsport="8080" type="mms" authtype="1"></apn>
+      <apn mcc="744" mnc="1" carrier="VOX MMS" apn="vox.mms" mmsc="http://mms.vox.com.py/mmsc" mmsproxy="172.24.97.29" mmsport="8080" type="mms" user="vox" password="vox" authtype="1"></apn>
+      <apn mcc="744" mnc="02" carrier="MMS GPRS PY" apn="mms.ctimovil.com.py" mmsc="http://mms.ctimovil.com.py" mmsproxy="170.51.255.240" mmsport="8080" type="mms" user="ctimms" password="ctimms999" authtype="1"></apn>
+      <apn mcc="744" mnc="2" carrier="Paraguay:Claro:Internet Claro PY" apn="igprs.claro.com.py" mmsc="http://mms.claro.com.py" type="default,mms" authtype="0"></apn>
+      <apn mcc="744" mnc="04" carrier="MMS Tigo" apn="mms.tigo.py" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" user="tigo" password="tigo" authtype="1"></apn>
+      <apn mcc="744" mnc="4" carrier="Paraguay:Tigo:MMS TIGO" apn="mms.tigo.py" mmsc="http://mms" mmsproxy="10.16.17.12" mmsport="8888" type="mms" user="tigo" password="tigo" authtype="1"></apn>
+      <apn mcc="744" mnc="05" carrier="Personal MMS Py" apn="mms" mmsc="http://mms" mmsproxy="172.16.192.7" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="744" mnc="5" carrier="Paraguay:Personal:MMS Personal" apn="mms" mmsc="http://mms" mmsproxy="172.16.192.7" mmsport="8080" type="mms" user="mms" password="mms" authtype="0"></apn>
+      <apn mcc="744" mnc="5" carrier="Personal MMS Py" apn="mms" mmsc="http://mms" mmsproxy="172.16.192.7" mmsport="8080" type="mms" user="mms" password="mms" authtype="1"></apn>
+      <apn mcc="746" mnc="03" carrier="Suriname:Digicel:Mms" apn="wap.digicelsr.com" mmsc="http://mmc.digicelsr.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="746" mnc="03" carrier="Suriname:Digicel:Modem" apn="wap.digicelsr.com" mmsc="http://wapdigicel.com" type="dun" user="wap" password="wap" authtype="1" proxy="172.20.6.12" port="8080"></apn>
+      <apn mcc="746" mnc="3" carrier="Suriname:Digicel:Mms" apn="wap.digicelsr.com" mmsc="http://mmc.digicelsr.com/servlets/mms" mmsproxy="172.20.6.12" mmsport="9201" type="mms" user="wap" password="wap" authtype="1"></apn>
+      <apn mcc="746" mnc="3" carrier="Suriname:Digicel:Modem" apn="wap.digicelsr.com" mmsc="http://wapdigicel.com" type="dun" user="wap" password="wap" authtype="1" proxy="172.20.6.12" port="8080"></apn>
+      <apn mcc="748" mnc="01" carrier="mmsANCEL" apn="mms" mmsc="http://mmsc.mms.ancelutil.com.uy" mmsproxy="200.40.246.2" mmsport="3128" type="mms" authtype="1"></apn>
+      <apn mcc="748" mnc="1" carrier="Uruguay:Ancel:MMS" apn="mms" mmsc="http://mmsc.mms.ancelutil.com.uy" mmsproxy="200.40.246.2" mmsport="3128" type="mms" authtype="0"></apn>
+      <apn mcc="748" mnc="1" carrier="mmsANCEL" apn="mms" mmsc="http://mmsc.mms.ancelutil.com.uy" mmsproxy="200.40.246.2" mmsport="3128" type="mms" authtype="1"></apn>
+      <apn mcc="748" mnc="07" carrier="Movistar MMS" apn="apnmms.movistar.com.uy" mmsc="http://mmsc.movistar.com.uy" mmsproxy="10.0.2.29" mmsport="8080" type="mms" user="mmsuy" password="mmsuy" authtype="1"></apn>
+      <apn mcc="748" mnc="7" carrier="Uruguay:Movistar:MMS" apn="apnmms.movistar.com.uy" mmsc="http://mmsc.movistar.com.uy" mmsproxy="10.0.2.29" mmsport="8080" type="mms" user="mmsuy" password="mmsuy" authtype="0"></apn>
+      <apn mcc="748" mnc="10" carrier="MMS GPRS UY" apn="mms.ctimovil.com.uy" mmsc="http://mms.ctimovil.com.uy" mmsproxy="170.51.255.240" mmsport="8080" type="mms" user="ctimms" password="ctimms999" authtype="1"></apn>
+      <apn mcc="748" mnc="10" carrier="Uruguay:Claro:Internet Claro UY" apn="igprs.claro.com.uy" mmsc="http://mms.claro.com.uy" type="default,mms" authtype="0"></apn>
+  </apns>
diff --git a/res/xml/mms_config.xml b/res/xml/mms_config.xml
new file mode 100644
index 0000000..e5a9338
--- /dev/null
+++ b/res/xml/mms_config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Version History
+        version 1 - initial version.
+        version 2 - added recipientLimit.
+        version 3 - added min/max recycler values.
+        version 4 - added sms to mms text threshold.
+-->
+
+<mms_config version="4">
+    <!-- Flag indicating whether MMS should be enabled -->
+    <bool name="enabledMMS">true</bool>
+
+    <!-- Maximum message size in bytes for a MMS message -->
+    <int name="maxMessageSize">307200</int>
+
+    <!-- Maximum height for an attached image -->
+    <int name="maxImageHeight">480</int>
+
+    <!-- Maximum width for an attached image -->
+    <int name="maxImageWidth">640</int>
+
+    <!-- Maximum number of recipients allowed per message. Use a value of -1
+         to indicate no limit. -->
+    <int name="recipientLimit">-1</int>
+
+    <!-- If true, The text message over 160 characters will be sent in multi part.
+         If false, The text message over 160 characters will be sent
+         via multi media message. -->
+    <bool name="enableMultipartSMS">true</bool>
+
+    <!-- If enableMultipartSMS is true and smsToMmsTextThreshold > 1, then multi-part SMS messages
+         will be converted into a single mms message. For example, if the mms_config.xml file
+         specifies <int name="smsToMmsTextThreshold">7</int>, then on the 8th sms segment, the
+         message will be converted to an mms. -->
+    <int name="smsToMmsTextThreshold">-1</int>
+
+    <!-- Maximum length for message text. Use a value of -1
+         to indicate default value -->
+    <int name="maxMessageTextSize">-1</int>
+
+    <!-- UAProf parameter tag name -->
+    <!-- this is default to "x-wap-profile". Override if necessary. Optional -->
+    <!--
+    <string name="uaProfTagName">x-wap-profile</string>
+    -->
+
+    <!-- Reference for additional http parameters used in MMS http request.
+         Parameters are seperated by '|'. Optional.
+    -->
+    <!--
+    <string name="httpParams">
+        x-up-calling-line-id: ##LINE1##|x-carrier-magic: http://magic.google.com
+    </string>
+    -->
+
+    <!-- Suffix to the NAI header (encoded together with base64) -->
+    <!--
+    <string name="naiSuffix"></string>
+    -->
+</mms_config>
diff --git a/res/xml/preferences_application.xml b/res/xml/preferences_application.xml
new file mode 100644
index 0000000..7a18d09
--- /dev/null
+++ b/res/xml/preferences_application.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- Preference screen definition for Bugle's application-wide settings -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--  KLP+ only -->
+    <PreferenceScreen
+        android:key="@string/sms_disabled_pref_key"
+        android:title="@string/sms_disabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.provider.Telephony.ACTION_CHANGE_DEFAULT">
+            <extra android:name="package" android:value="com.android.messaging" />
+        </intent>
+    </PreferenceScreen>
+    <PreferenceScreen
+        android:key="@string/sms_enabled_pref_key"
+        android:title="@string/sms_enabled_pref_title"
+        android:persistent="false">
+        <intent
+            android:action="android.settings.WIRELESS_SETTINGS">
+        </intent>
+    </PreferenceScreen>
+
+    <CheckBoxPreference
+        android:key="@string/send_sound_pref_key"
+        android:title="@string/send_sound_pref_title"
+        android:defaultValue="@bool/send_sound_pref_default"
+        android:persistent="true" />
+
+    <CheckBoxPreference
+        android:key="@string/notifications_enabled_pref_key"
+        android:title="@string/notifications_enabled_pref_title"
+        android:defaultValue="@bool/notifications_enabled_pref_default"
+        android:persistent="true"
+        android:disableDependentsState="false" />
+
+    <RingtonePreference
+        android:key="@string/notification_sound_pref_key"
+        android:title="@string/notification_sound_pref_title"
+        android:ringtoneType="notification"
+        android:showSilent="true"
+        android:showDefault="true"
+        android:persistent="true"
+        android:defaultValue=""
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <CheckBoxPreference
+        android:key="@string/notification_vibration_pref_key"
+        android:title="@string/notification_vibrate_pref_title"
+        android:defaultValue="@bool/notification_vibration_pref_default"
+        android:persistent="true"
+        android:dependency="@string/notifications_enabled_pref_key" />
+
+    <PreferenceScreen
+            android:key="@string/advanced_pref_key"
+            android:title="@string/advanced_settings" />
+
+    <PreferenceCategory
+        android:key="@string/debug_pref_key"
+        android:title="@string/debug_category_pref_title">
+
+        <CheckBoxPreference
+            android:key="@string/dump_sms_pref_key"
+            android:title="@string/dump_sms_pref_title"
+            android:summary="@string/dump_sms_pref_summary"
+            android:defaultValue="@bool/dump_sms_pref_default" />
+
+        <CheckBoxPreference
+            android:key="@string/dump_mms_pref_key"
+            android:title="@string/dump_mms_pref_title"
+            android:summary="@string/dump_mms_pref_summary"
+            android:defaultValue="@bool/dump_mms_pref_default" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/preferences_per_subscription.xml b/res/xml/preferences_per_subscription.xml
new file mode 100644
index 0000000..5e00086
--- /dev/null
+++ b/res/xml/preferences_per_subscription.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<!-- Preference screen definition for Bugle's subscription-specific settings -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <PreferenceCategory
+        android:key="@string/mms_messaging_category_pref_key"
+        android:title="@string/mms_messaging_category_pref_title">
+
+        <Preference
+            android:title="@string/group_mms_pref_title"
+            android:key="@string/group_mms_pref_key"/>
+
+        <com.android.messaging.ui.appsettings.PhoneNumberPreference
+            android:key="@string/mms_phone_number_pref_key"
+            android:title="@string/mms_phone_number_pref_title" />
+
+        <CheckBoxPreference
+            android:key="@string/auto_retrieve_mms_pref_key"
+            android:title="@string/auto_retrieve_mms_pref_title"
+            android:summary="@string/auto_retrieve_mms_pref_summary"
+            android:defaultValue="@bool/auto_retrieve_mms_pref_default" />
+
+        <CheckBoxPreference
+            android:key="@string/auto_retrieve_mms_when_roaming_pref_key"
+            android:dependency="@string/auto_retrieve_mms_pref_key"
+            android:title="@string/auto_retrieve_mms_when_roaming_pref_title"
+            android:summary="@string/auto_retrieve_mms_when_roaming_pref_summary"
+            android:defaultValue="@bool/auto_retrieve_mms_when_roaming_pref_default" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="@string/advanced_category_pref_key"
+        android:title="@string/advanced_category_pref_title">
+
+        <CheckBoxPreference
+            android:key="@string/delivery_reports_pref_key"
+            android:title="@string/delivery_reports_pref_title"
+            android:summary="@string/delivery_reports_pref_summary"
+            android:defaultValue="@bool/delivery_reports_pref_default" />
+
+        <Preference
+            android:key="@string/wireless_alerts_key"
+            android:title="@string/wireless_alerts_title"/>
+
+        <PreferenceScreen
+            android:key="@string/sms_apns_key"
+            android:title="@string/sms_apns_title" />
+
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml/widget_conversation.xml b/res/xml/widget_conversation.xml
new file mode 100644
index 0000000..d1a573b
--- /dev/null
+++ b/res/xml/widget_conversation.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minResizeWidth="110dp"
+    android:minResizeHeight="110dp"
+    android:minWidth="180dp"
+    android:minHeight="180dp"
+    android:updatePeriodMillis="0"
+    android:initialLayout="@layout/widget_conversation"
+    android:resizeMode="horizontal|vertical"
+    android:widgetCategory="home_screen|keyguard"
+    android:previewImage="@drawable/messenger_widget_conversation_preview"
+    android:configure="com.android.messaging.ui.WidgetPickConversationActivity">
+</appwidget-provider>
diff --git a/res/xml/widget_conversation_list.xml b/res/xml/widget_conversation_list.xml
new file mode 100644
index 0000000..b294acb
--- /dev/null
+++ b/res/xml/widget_conversation_list.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minResizeWidth="110dp"
+    android:minResizeHeight="110dp"
+    android:minWidth="250dp"
+    android:minHeight="180dp"
+    android:updatePeriodMillis="0"
+    android:initialLayout="@layout/widget_conversation_list"
+    android:resizeMode="horizontal|vertical"
+    android:previewImage="@drawable/messenger_widget_preview"
+    android:widgetCategory="home_screen|keyguard">
+</appwidget-provider>
diff --git a/src/android/support/v7/mms/ApnException.java b/src/android/support/v7/mms/ApnException.java
new file mode 100644
index 0000000..322260a
--- /dev/null
+++ b/src/android/support/v7/mms/ApnException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+/**
+ * APN exception
+ */
+public class ApnException extends Exception {
+
+    public ApnException() {
+        super();
+    }
+
+    public ApnException(String message) {
+        super(message);
+    }
+
+    public ApnException(Throwable cause) {
+        super(cause);
+    }
+
+    public ApnException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/android/support/v7/mms/ApnSettingsLoader.java b/src/android/support/v7/mms/ApnSettingsLoader.java
new file mode 100644
index 0000000..9ccfc06
--- /dev/null
+++ b/src/android/support/v7/mms/ApnSettingsLoader.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import java.util.List;
+
+/**
+ * Interface for loading APNs for default SMS SIM
+ */
+public interface ApnSettingsLoader {
+    /**
+     * Interface to represent the minimal information MMS lib needs from an APN
+     */
+    interface Apn {
+        /**
+         * Get the MMSC URL string
+         *
+         * @return MMSC URL
+         */
+        String getMmsc();
+
+        /**
+         * Get the MMS proxy host address
+         *
+         * @return MMS proxy
+         */
+        String getMmsProxy();
+
+        /**
+         * Get the MMS proxy host port
+         *
+         * @return the port of MMS proxy
+         */
+        int getMmsProxyPort();
+
+        /**
+         * Flag the APN as a successful APN to use
+         */
+        void setSuccess();
+    }
+
+    /**
+     * Get a list possible APN matching the subId and APN name
+     *
+     * @param apnName the APN name
+     * @return a list of possible APNs
+     */
+    List<Apn> get(String apnName);
+}
diff --git a/src/android/support/v7/mms/ApnsXmlParser.java b/src/android/support/v7/mms/ApnsXmlParser.java
new file mode 100644
index 0000000..2d63136
--- /dev/null
+++ b/src/android/support/v7/mms/ApnsXmlParser.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.ContentValues;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Parser for built-in XML resource file for APN list
+ */
+class ApnsXmlParser extends MmsXmlResourceParser {
+    interface ApnProcessor {
+        void process(ContentValues apnValues);
+    }
+
+    private static final String TAG_APNS = "apns";
+    private static final String TAG_APN = "apn";
+
+    private final ApnProcessor mApnProcessor;
+
+    private final ContentValues mValues = new ContentValues();
+
+    ApnsXmlParser(final XmlPullParser parser, final ApnProcessor apnProcessor) {
+        super(parser);
+        mApnProcessor = apnProcessor;
+    }
+
+    // Parse one APN
+    @Override
+    protected void parseRecord() throws IOException, XmlPullParserException {
+        if (TAG_APN.equals(mInputParser.getName())) {
+            mValues.clear();
+            // Collect all the attributes
+            for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
+                final String key = mInputParser.getAttributeName(i);
+                if (key != null) {
+                    mValues.put(key, mInputParser.getAttributeValue(i));
+                }
+            }
+            // We are done parsing one APN, call the handler
+            if (mApnProcessor != null) {
+                mApnProcessor.process(mValues);
+            }
+        }
+        // We are at the end tag
+        if (mInputParser.next() != XmlPullParser.END_TAG) {
+            throw new XmlPullParserException("Expecting end tag @" + xmlParserDebugContext());
+        }
+    }
+
+    @Override
+    protected String getRootTag() {
+        return TAG_APNS;
+    }
+}
diff --git a/src/android/support/v7/mms/CarrierConfigValuesLoader.java b/src/android/support/v7/mms/CarrierConfigValuesLoader.java
new file mode 100644
index 0000000..1cb5226
--- /dev/null
+++ b/src/android/support/v7/mms/CarrierConfigValuesLoader.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.os.Bundle;
+
+/**
+ * Loader for carrier dependent configuration values
+ */
+public interface CarrierConfigValuesLoader {
+    /**
+     * Get the carrier config values in a bundle
+     *
+     * @param subId the associated subscription ID for the carrier configuration
+     * @return a bundle of all the values
+     */
+    Bundle get(int subId);
+
+    // Configuration keys and default values
+
+    /** Boolean value: if MMS is enabled */
+    public static final String CONFIG_ENABLED_MMS = "enabledMMS";
+    public static final boolean CONFIG_ENABLED_MMS_DEFAULT = true;
+    /**
+     * Boolean value: if transaction ID should be appended to
+     * the download URL of a single segment WAP push message
+     */
+    public static final String CONFIG_ENABLED_TRANS_ID = "enabledTransID";
+    public static final boolean CONFIG_ENABLED_TRANS_ID_DEFAULT = false;
+    /**
+     * Boolean value: if acknowledge or notify response to a download
+     * should be sent to the WAP push message's download URL
+     */
+    public static final String CONFIG_ENABLED_NOTIFY_WAP_MMSC = "enabledNotifyWapMMSC";
+    public static final boolean CONFIG_ENABLED_NOTIFY_WAP_MMSC_DEFAULT = false;
+    /**
+     * Boolean value: if phone number alias can be used
+     */
+    public static final String CONFIG_ALIAS_ENABLED = "aliasEnabled";
+    public static final boolean CONFIG_ALIAS_ENABLED_DEFAULT = false;
+    /**
+     * Boolean value: if audio is allowed in attachment
+     */
+    public static final String CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
+    public static final boolean CONFIG_ALLOW_ATTACH_AUDIO_DEFAULT = true;
+    /**
+     * Boolean value: if true, long sms messages are always sent as multi-part sms
+     * messages, with no checked limit on the number of segments. If false, then
+     * as soon as the user types a message longer than a single segment (i.e. 140 chars),
+     * the message will turn into and be sent as an mms message or separate,
+     * independent SMS messages (dependent on CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES flag).
+     * This feature exists for carriers that don't support multi-part sms.
+     */
+    public static final String CONFIG_ENABLE_MULTIPART_SMS = "enableMultipartSMS";
+    public static final boolean CONFIG_ENABLE_MULTIPART_SMS_DEFAULT = true;
+    /**
+     * Boolean value: if SMS delivery report is supported
+     */
+    public static final String CONFIG_ENABLE_SMS_DELIVERY_REPORTS = "enableSMSDeliveryReports";
+    public static final boolean CONFIG_ENABLE_SMS_DELIVERY_REPORTS_DEFAULT = true;
+    /**
+     * Boolean value: if group MMS is supported
+     */
+    public static final String CONFIG_ENABLE_GROUP_MMS = "enableGroupMms";
+    public static final boolean CONFIG_ENABLE_GROUP_MMS_DEFAULT = true;
+    /**
+     * Boolean value: if the content_disposition field of an MMS part should be parsed
+     * Check wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21. Most carriers support it except some.
+     */
+    public static final String CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION =
+            "supportMmsContentDisposition";
+    public static final boolean CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION_DEFAULT = true;
+    /**
+     * Boolean value: if the sms app should support a link to the system settings
+     * where amber alerts are configured.
+     */
+    public static final String CONFIG_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
+    public static final boolean CONFIG_CELL_BROADCAST_APP_LINKS_DEFAULT = true;
+    /**
+     * Boolean value: if multipart SMS should be sent as separate SMS messages
+     */
+    public static final String CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES =
+            "sendMultipartSmsAsSeparateMessages";
+    public static final boolean CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_DEFAULT = false;
+    /**
+     * Boolean value: if MMS read report is supported
+     */
+    public static final String CONFIG_ENABLE_MMS_READ_REPORTS = "enableMMSReadReports";
+    public static final boolean CONFIG_ENABLE_MMS_READ_REPORTS_DEFAULT = false;
+    /**
+     * Boolean value: if MMS delivery report is supported
+     */
+    public static final String CONFIG_ENABLE_MMS_DELIVERY_REPORTS = "enableMMSDeliveryReports";
+    public static final boolean CONFIG_ENABLE_MMS_DELIVERY_REPORTS_DEFAULT = false;
+    /**
+     * Boolean value: if "charset" value is supported in the "Content-Type" HTTP header
+     */
+    public static final String CONFIG_SUPPORT_HTTP_CHARSET_HEADER = "supportHttpCharsetHeader";
+    public static final boolean CONFIG_SUPPORT_HTTP_CHARSET_HEADER_DEFAULT = false;
+    /**
+     * Integer value: maximal MMS message size in bytes
+     */
+    public static final String CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize";
+    public static final int CONFIG_MAX_MESSAGE_SIZE_DEFAULT = 300 * 1024;
+    /**
+     * Integer value: maximal MMS image height in pixels
+     */
+    public static final String CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight";
+    public static final int CONFIG_MAX_IMAGE_HEIGHT_DEFAULT = 480;
+    /**
+     * Integer value: maximal MMS image width in pixels
+     */
+    public static final String CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth";
+    public static final int CONFIG_MAX_IMAGE_WIDTH_DEFAULT = 640;
+    /**
+     * Integer value: limit on recipient list of an MMS message
+     */
+    public static final String CONFIG_RECIPIENT_LIMIT = "recipientLimit";
+    public static final int CONFIG_RECIPIENT_LIMIT_DEFAULT = Integer.MAX_VALUE;
+    /**
+     * Integer value: HTTP socket timeout in milliseconds for MMS
+     */
+    public static final String CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
+    public static final int CONFIG_HTTP_SOCKET_TIMEOUT_DEFAULT = 60 * 1000;
+    /**
+     * Integer value: minimal number of characters of an alias
+     */
+    public static final String CONFIG_ALIAS_MIN_CHARS = "aliasMinChars";
+    public static final int CONFIG_ALIAS_MIN_CHARS_DEFAULT = 2;
+    /**
+     * Integer value: maximal number of characters of an alias
+     */
+    public static final String CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars";
+    public static final int CONFIG_ALIAS_MAX_CHARS_DEFAULT = 48;
+    /**
+     * Integer value: the threshold of number of SMS parts when an multipart SMS will be
+     * converted into an MMS, e.g. if this is "4", when an multipart SMS message has 5
+     * parts, then it will be sent as MMS message instead. "-1" indicates no such conversion
+     * can happen.
+     */
+    public static final String CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
+    public static final int CONFIG_SMS_TO_MMS_TEXT_THRESHOLD_DEFAULT = -1;
+    /**
+     * Integer value: the threshold of SMS length when it will be converted into an MMS.
+     * "-1" indicates no such conversion can happen.
+     */
+    public static final String CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD =
+            "smsToMmsTextLengthThreshold";
+    public static final int CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_DEFAULT = -1;
+    /**
+     * Integer value: maximal length in bytes of SMS message
+     */
+    public static final String CONFIG_MAX_MESSAGE_TEXT_SIZE = "maxMessageTextSize";
+    public static final int CONFIG_MAX_MESSAGE_TEXT_SIZE_DEFAULT = -1;
+    /**
+     * Integer value: maximum number of characters allowed for mms subject
+     */
+    public static final String CONFIG_MAX_SUBJECT_LENGTH = "maxSubjectLength";
+    public static final int CONFIG_MAX_SUBJECT_LENGTH_DEFAULT = 40;
+    /**
+     * String value: name for the user agent profile HTTP header
+     */
+    public static final String CONFIG_UA_PROF_TAG_NAME = "uaProfTagName";
+    public static final String CONFIG_UA_PROF_TAG_NAME_DEFAULT = "x-wap-profile";
+    /**
+     * String value: additional HTTP headers for MMS HTTP requests.
+     * The format is
+     * header_1:header_value_1|header_2:header_value_2|...
+     * Each value can contain macros.
+     */
+    public static final String CONFIG_HTTP_PARAMS = "httpParams";
+    public static final String CONFIG_HTTP_PARAMS_DEFAULT = null;
+    /**
+     * String value: number of email gateway
+     */
+    public static final String CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
+    public static final String CONFIG_EMAIL_GATEWAY_NUMBER_DEFAULT = null;
+    /**
+     * String value: suffix for the NAI HTTP header value, e.g. ":pcs"
+     * (NAI is used as authentication in HTTP headers for some carriers)
+     */
+    public static final String CONFIG_NAI_SUFFIX = "naiSuffix";
+    public static final String CONFIG_NAI_SUFFIX_DEFAULT = null;
+    /**
+     * String value: Url for user agent profile
+     */
+    public static final String CONFIG_UA_PROF_URL = "uaProfUrl";
+    public static final String CONFIG_UA_PROF_URL_DEFAULT = null;
+    /**
+     * String value: user agent
+     */
+    public static final String CONFIG_USER_AGENT = "userAgent";
+    public static final String CONFIG_USER_AGENT_DEFAULT = null;
+}
diff --git a/src/android/support/v7/mms/CarrierConfigXmlParser.java b/src/android/support/v7/mms/CarrierConfigXmlParser.java
new file mode 100644
index 0000000..2e95d52
--- /dev/null
+++ b/src/android/support/v7/mms/CarrierConfigXmlParser.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * XML parser for carrier config (i.e. mms_config)
+ */
+class CarrierConfigXmlParser extends MmsXmlResourceParser {
+    interface KeyValueProcessor {
+        void process(String type, String key, String value);
+    }
+
+    private static final String TAG_MMS_CONFIG = "mms_config";
+
+    private final KeyValueProcessor mKeyValueProcessor;
+
+    CarrierConfigXmlParser(final XmlPullParser parser, final KeyValueProcessor keyValueProcessor) {
+        super(parser);
+        mKeyValueProcessor = keyValueProcessor;
+    }
+
+    // Parse one key/value
+    @Override
+    protected void parseRecord() throws IOException, XmlPullParserException {
+        final String key = mInputParser.getAttributeValue(null, "name");
+        // We are at the start tag, the name of the tag is the type
+        // e.g. <int name="key">value</int>
+        final String type = mInputParser.getName();
+        int nextEvent = mInputParser.next();
+        String value = null;
+        if (nextEvent == XmlPullParser.TEXT) {
+            value = mInputParser.getText();
+            nextEvent = mInputParser.next();
+        }
+        if (nextEvent != XmlPullParser.END_TAG) {
+            throw new XmlPullParserException("Expecting end tag @" + xmlParserDebugContext());
+        }
+        // We are done parsing one mms_config key/value, call the handler
+        if (mKeyValueProcessor != null) {
+            mKeyValueProcessor.process(type, key, value);
+        }
+    }
+
+    @Override
+    protected String getRootTag() {
+        return TAG_MMS_CONFIG;
+    }
+
+}
diff --git a/src/android/support/v7/mms/DefaultApnSettingsLoader.java b/src/android/support/v7/mms/DefaultApnSettingsLoader.java
new file mode 100644
index 0000000..a4bd647
--- /dev/null
+++ b/src/android/support/v7/mms/DefaultApnSettingsLoader.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.Telephony;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.messaging.R;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Default implementation of APN settings loader
+ */
+class DefaultApnSettingsLoader implements ApnSettingsLoader {
+    /**
+     * The base implementation of an APN
+     */
+    private static class BaseApn implements Apn {
+        /**
+         * Create a base APN from parameters
+         *
+         * @param typesIn the APN type field
+         * @param mmscIn the APN mmsc field
+         * @param proxyIn the APN mmsproxy field
+         * @param portIn the APN mmsport field
+         * @return an instance of base APN, or null if any of the parameter is invalid
+         */
+        public static BaseApn from(final String typesIn, final String mmscIn, final String proxyIn,
+                final String portIn) {
+            if (!isValidApnType(trimWithNullCheck(typesIn), APN_TYPE_MMS)) {
+                return null;
+            }
+            String mmsc = trimWithNullCheck(mmscIn);
+            if (TextUtils.isEmpty(mmsc)) {
+                return null;
+            }
+            mmsc = trimV4AddrZeros(mmsc);
+            try {
+                new URI(mmsc);
+            } catch (final URISyntaxException e) {
+                return null;
+            }
+            String mmsProxy = trimWithNullCheck(proxyIn);
+            int mmsProxyPort = 80;
+            if (!TextUtils.isEmpty(mmsProxy)) {
+                mmsProxy = trimV4AddrZeros(mmsProxy);
+                final String portString = trimWithNullCheck(portIn);
+                if (portString != null) {
+                    try {
+                        mmsProxyPort = Integer.parseInt(portString);
+                    } catch (final NumberFormatException e) {
+                        // Ignore, just use 80 to try
+                    }
+                }
+            }
+            return new BaseApn(mmsc, mmsProxy, mmsProxyPort);
+        }
+
+        private final String mMmsc;
+        private final String mMmsProxy;
+        private final int mMmsProxyPort;
+
+        public BaseApn(final String mmsc, final String proxy, final int port) {
+            mMmsc = mmsc;
+            mMmsProxy = proxy;
+            mMmsProxyPort = port;
+        }
+
+        @Override
+        public String getMmsc() {
+            return mMmsc;
+        }
+
+        @Override
+        public String getMmsProxy() {
+            return mMmsProxy;
+        }
+
+        @Override
+        public int getMmsProxyPort() {
+            return mMmsProxyPort;
+        }
+
+        @Override
+        public void setSuccess() {
+            // Do nothing
+        }
+
+        public boolean equals(final BaseApn other) {
+            return TextUtils.equals(mMmsc, other.getMmsc()) &&
+                    TextUtils.equals(mMmsProxy, other.getMmsProxy()) &&
+                    mMmsProxyPort == other.getMmsProxyPort();
+        }
+    }
+
+    /**
+     * An in-memory implementation of an APN. These APNs are organized into an in-memory list.
+     * The order of the list can be changed by the setSuccess method.
+     */
+    private static class MemoryApn implements Apn {
+        /**
+         * Create an in-memory APN loaded from resources
+         *
+         * @param apns the in-memory APN list
+         * @param typesIn the APN type field
+         * @param mmscIn the APN mmsc field
+         * @param proxyIn the APN mmsproxy field
+         * @param portIn the APN mmsport field
+         * @return an in-memory APN instance, null if there is invalid parameter
+         */
+        public static MemoryApn from(final List<Apn> apns, final String typesIn,
+                final String mmscIn, final String proxyIn, final String portIn) {
+            if (apns == null) {
+                return null;
+            }
+            final BaseApn base = BaseApn.from(typesIn, mmscIn, proxyIn, portIn);
+            if (base == null) {
+                return null;
+            }
+            for (final Apn apn : apns) {
+                if (apn instanceof MemoryApn && ((MemoryApn) apn).equals(base)) {
+                    return null;
+                }
+            }
+            return new MemoryApn(apns, base);
+        }
+
+        private final List<Apn> mApns;
+        private final BaseApn mBase;
+
+        public MemoryApn(final List<Apn> apns, final BaseApn base) {
+            mApns = apns;
+            mBase = base;
+        }
+
+        @Override
+        public String getMmsc() {
+            return mBase.getMmsc();
+        }
+
+        @Override
+        public String getMmsProxy() {
+            return mBase.getMmsProxy();
+        }
+
+        @Override
+        public int getMmsProxyPort() {
+            return mBase.getMmsProxyPort();
+        }
+
+        @Override
+        public void setSuccess() {
+            // If this is being marked as a successful APN, move it to the top of the list so
+            // next time it will be tried first
+            boolean moved = false;
+            synchronized (mApns) {
+                if (mApns.get(0) != this) {
+                    mApns.remove(this);
+                    mApns.add(0, this);
+                    moved = true;
+                }
+            }
+            if (moved) {
+                Log.d(MmsService.TAG, "Set APN ["
+                        + "MMSC=" + getMmsc() + ", "
+                        + "PROXY=" + getMmsProxy() + ", "
+                        + "PORT=" + getMmsProxyPort() + "] to be first");
+            }
+        }
+
+        public boolean equals(final BaseApn other) {
+            if (other == null) {
+                return false;
+            }
+            return mBase.equals(other);
+        }
+    }
+
+    /**
+     * APN_TYPE_ALL is a special type to indicate that this APN entry can
+     * service all data connections.
+     */
+    public static final String APN_TYPE_ALL = "*";
+    /** APN type for MMS traffic */
+    public static final String APN_TYPE_MMS = "mms";
+
+    private static final String[] APN_PROJECTION = {
+            Telephony.Carriers.TYPE,
+            Telephony.Carriers.MMSC,
+            Telephony.Carriers.MMSPROXY,
+            Telephony.Carriers.MMSPORT,
+    };
+    private static final int COLUMN_TYPE         = 0;
+    private static final int COLUMN_MMSC         = 1;
+    private static final int COLUMN_MMSPROXY     = 2;
+    private static final int COLUMN_MMSPORT      = 3;
+
+    private static final String APN_MCC = "mcc";
+    private static final String APN_MNC = "mnc";
+    private static final String APN_APN = "apn";
+    private static final String APN_TYPE = "type";
+    private static final String APN_MMSC = "mmsc";
+    private static final String APN_MMSPROXY = "mmsproxy";
+    private static final String APN_MMSPORT = "mmsport";
+
+    private final Context mContext;
+
+    // Cached APNs for subIds
+    private final SparseArray<List<Apn>> mApnsCache;
+
+    DefaultApnSettingsLoader(final Context context) {
+        mContext = context;
+        mApnsCache = new SparseArray<>();
+    }
+
+    @Override
+    public List<Apn> get(final String apnName) {
+        final int subId = Utils.getEffectiveSubscriptionId(MmsManager.DEFAULT_SUB_ID);
+        List<Apn> apns;
+        boolean didLoad = false;
+        synchronized (this) {
+            apns = mApnsCache.get(subId);
+            if (apns == null) {
+                apns = new ArrayList<>();
+                mApnsCache.put(subId, apns);
+                loadLocked(subId, apnName, apns);
+                didLoad = true;
+            }
+        }
+        if (didLoad) {
+            Log.i(MmsService.TAG, "Loaded " + apns.size() + " APNs");
+        }
+        return apns;
+    }
+
+    private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
+        // Try system APN table first
+        loadFromSystem(subId, apnName, apns);
+        if (apns.size() > 0) {
+            return;
+        }
+        // Try loading from apns.xml in resources
+        loadFromResources(subId, apnName, apns);
+        if (apns.size() > 0) {
+            return;
+        }
+        // Try resources but without APN name
+        loadFromResources(subId, null/*apnName*/, apns);
+    }
+
+    /**
+     * Load matching APNs from telephony provider.
+     * We try different combinations of the query to work around some platform quirks.
+     *
+     * @param subId the SIM subId
+     * @param apnName the APN name to match
+     * @param apns the list used to return results
+     */
+    private void loadFromSystem(final int subId, final String apnName, final List<Apn> apns) {
+        Uri uri;
+        if (Utils.supportMSim() && subId != MmsManager.DEFAULT_SUB_ID) {
+            uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId);
+        } else {
+            uri = Telephony.Carriers.CONTENT_URI;
+        }
+        Cursor cursor = null;
+        try {
+            for (; ; ) {
+                // Try different combinations of queries. Some would work on some platforms.
+                // So we query each combination until we find one returns non-empty result.
+                cursor = querySystem(uri, true/*checkCurrent*/, apnName);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, false/*checkCurrent*/, apnName);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, true/*checkCurrent*/, null/*apnName*/);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, false/*checkCurrent*/, null/*apnName*/);
+                break;
+            }
+        } catch (final SecurityException e) {
+            // Can't access platform APN table, return directly
+            return;
+        }
+        if (cursor == null) {
+            return;
+        }
+        try {
+            if (cursor.moveToFirst()) {
+                final Apn apn = BaseApn.from(
+                        cursor.getString(COLUMN_TYPE),
+                        cursor.getString(COLUMN_MMSC),
+                        cursor.getString(COLUMN_MMSPROXY),
+                        cursor.getString(COLUMN_MMSPORT));
+                if (apn != null) {
+                    apns.add(apn);
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Query system APN table
+     *
+     * @param uri The APN query URL to use
+     * @param checkCurrent If add "CURRENT IS NOT NULL" condition
+     * @param apnName The optional APN name for query condition
+     * @return A cursor of the query result. If a cursor is returned as not null, it is
+     *         guaranteed to contain at least one row.
+     */
+    private Cursor querySystem(final Uri uri, final boolean checkCurrent, String apnName) {
+        Log.i(MmsService.TAG, "Loading APNs from system, "
+                + "checkCurrent=" + checkCurrent + " apnName=" + apnName);
+        final StringBuilder selectionBuilder = new StringBuilder();
+        String[] selectionArgs = null;
+        if (checkCurrent) {
+            selectionBuilder.append(Telephony.Carriers.CURRENT).append(" IS NOT NULL");
+        }
+        apnName = trimWithNullCheck(apnName);
+        if (!TextUtils.isEmpty(apnName)) {
+            if (selectionBuilder.length() > 0) {
+                selectionBuilder.append(" AND ");
+            }
+            selectionBuilder.append(Telephony.Carriers.APN).append("=?");
+            selectionArgs = new String[] { apnName };
+        }
+        try {
+            final Cursor cursor = mContext.getContentResolver().query(
+                    uri,
+                    APN_PROJECTION,
+                    selectionBuilder.toString(),
+                    selectionArgs,
+                    null/*sortOrder*/);
+            if (cursor == null || cursor.getCount() < 1) {
+                if (cursor != null) {
+                    cursor.close();
+                }
+                Log.w(MmsService.TAG, "Query " + uri + " with apn " + apnName + " and "
+                        + (checkCurrent ? "checking CURRENT" : "not checking CURRENT")
+                        + " returned empty");
+                return null;
+            }
+            return cursor;
+        } catch (final SQLiteException e) {
+            Log.w(MmsService.TAG, "APN table query exception: " + e);
+        } catch (final SecurityException e) {
+            Log.w(MmsService.TAG, "Platform restricts APN table access: " + e);
+            throw e;
+        }
+        return null;
+    }
+
+    /**
+     * Find matching APNs using builtin APN list resource
+     *
+     * @param subId the SIM subId
+     * @param apnName the APN name to match
+     * @param apns the list for returning results
+     */
+    private void loadFromResources(final int subId, final String apnName, final List<Apn> apns) {
+        Log.i(MmsService.TAG, "Loading APNs from resources, apnName=" + apnName);
+        final int[] mccMnc = Utils.getMccMnc(mContext, subId);
+        if (mccMnc[0] == 0) {
+            Log.w(MmsService.TAG, "Can not get valid mcc/mnc from system");
+            return;
+        }
+        // MCC/MNC is good, loading/querying APNs from XML
+        XmlResourceParser xml = null;
+        try {
+            xml = mContext.getResources().getXml(R.xml.apns);
+            new ApnsXmlParser(xml, new ApnsXmlParser.ApnProcessor() {
+                @Override
+                public void process(ContentValues apnValues) {
+                    final String mcc = trimWithNullCheck(apnValues.getAsString(APN_MCC));
+                    final String mnc = trimWithNullCheck(apnValues.getAsString(APN_MNC));
+                    final String apn = trimWithNullCheck(apnValues.getAsString(APN_APN));
+                    try {
+                        if (mccMnc[0] == Integer.parseInt(mcc) &&
+                                mccMnc[1] == Integer.parseInt(mnc) &&
+                                (TextUtils.isEmpty(apnName) || apnName.equalsIgnoreCase(apn))) {
+                            final String type = apnValues.getAsString(APN_TYPE);
+                            final String mmsc = apnValues.getAsString(APN_MMSC);
+                            final String mmsproxy = apnValues.getAsString(APN_MMSPROXY);
+                            final String mmsport = apnValues.getAsString(APN_MMSPORT);
+                            final Apn newApn = MemoryApn.from(apns, type, mmsc, mmsproxy, mmsport);
+                            if (newApn != null) {
+                                apns.add(newApn);
+                            }
+                        }
+                    } catch (final NumberFormatException e) {
+                        // Ignore
+                    }
+                }
+            }).parse();
+        } catch (final Resources.NotFoundException e) {
+            Log.w(MmsService.TAG, "Can not get apns.xml " + e);
+        } finally {
+            if (xml != null) {
+                xml.close();
+            }
+        }
+    }
+
+    private static String trimWithNullCheck(final String value) {
+        return value != null ? value.trim() : null;
+    }
+
+    /**
+     * Trim leading zeros from IPv4 address strings
+     * Our base libraries will interpret that as octel..
+     * Must leave non v4 addresses and host names alone.
+     * For example, 192.168.000.010 -> 192.168.0.10
+     *
+     * @param addr a string representing an ip addr
+     * @return a string propertly trimmed
+     */
+    private static String trimV4AddrZeros(final String addr) {
+        if (addr == null) {
+            return null;
+        }
+        final String[] octets = addr.split("\\.");
+        if (octets.length != 4) {
+            return addr;
+        }
+        final StringBuilder builder = new StringBuilder(16);
+        String result = null;
+        for (int i = 0; i < 4; i++) {
+            try {
+                if (octets[i].length() > 3) {
+                    return addr;
+                }
+                builder.append(Integer.parseInt(octets[i]));
+            } catch (final NumberFormatException e) {
+                return addr;
+            }
+            if (i < 3) {
+                builder.append('.');
+            }
+        }
+        result = builder.toString();
+        return result;
+    }
+
+    /**
+     * Check if the APN contains the APN type we want
+     *
+     * @param types The string encodes a list of supported types
+     * @param requestType The type we want
+     * @return true if the input types string contains the requestType
+     */
+    public static boolean isValidApnType(final String types, final String requestType) {
+        // If APN type is unspecified, assume APN_TYPE_ALL.
+        if (TextUtils.isEmpty(types)) {
+            return true;
+        }
+        for (final String t : types.split(",")) {
+            if (t.equals(requestType) || t.equals(APN_TYPE_ALL)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/android/support/v7/mms/DefaultCarrierConfigValuesLoader.java b/src/android/support/v7/mms/DefaultCarrierConfigValuesLoader.java
new file mode 100644
index 0000000..1a45338
--- /dev/null
+++ b/src/android/support/v7/mms/DefaultCarrierConfigValuesLoader.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.messaging.R;
+
+/**
+ * The default implementation of loader for carrier config values
+ */
+class DefaultCarrierConfigValuesLoader implements CarrierConfigValuesLoader {
+    /*
+     * Key types
+     */
+    public static final String KEY_TYPE_INT = "int";
+    public static final String KEY_TYPE_BOOL = "bool";
+    public static final String KEY_TYPE_STRING = "string";
+
+    private final Context mContext;
+
+    // Cached values for subIds
+    private final SparseArray<Bundle> mValuesCache;
+
+    DefaultCarrierConfigValuesLoader(final Context context) {
+        mContext = context;
+        mValuesCache = new SparseArray<>();
+    }
+
+    @Override
+    public Bundle get(int subId) {
+        subId = Utils.getEffectiveSubscriptionId(subId);
+        Bundle values;
+        boolean didLoad = false;
+        synchronized (this) {
+            values = mValuesCache.get(subId);
+            if (values == null) {
+                values = new Bundle();
+                mValuesCache.put(subId, values);
+                loadLocked(subId, values);
+                didLoad = true;
+            }
+        }
+        if (didLoad) {
+            Log.i(MmsService.TAG, "Carrier configs loaded: " + values);
+        }
+        return values;
+    }
+
+    private void loadLocked(final int subId, final Bundle values) {
+        // For K and earlier, load from resources
+        loadFromResources(subId, values);
+        if (Utils.hasMmsApi()) {
+            // For L and later, also load from system MMS service
+            loadFromSystem(subId, values);
+        }
+    }
+
+    /**
+     * Load from system, using MMS API
+     *
+     * @param subId which SIM to load for
+     * @param values the result to add to
+     */
+    private static void loadFromSystem(final int subId, final Bundle values) {
+        try {
+            final Bundle systemValues = Utils.getSmsManager(subId).getCarrierConfigValues();
+            if (systemValues != null) {
+                values.putAll(systemValues);
+            }
+        } catch (final Exception e) {
+            Log.w(MmsService.TAG, "Calling system getCarrierConfigValues exception", e);
+        }
+    }
+
+    private void loadFromResources(final int subId, final Bundle values) {
+        // Get a subscription-dependent context for loading the mms_config.xml
+        final Context subContext = Utils.getSubDepContext(mContext, subId);
+        XmlResourceParser xml = null;
+        try {
+            xml = subContext.getResources().getXml(R.xml.mms_config);
+            new CarrierConfigXmlParser(xml, new CarrierConfigXmlParser.KeyValueProcessor() {
+                @Override
+                public void process(String type, String key, String value) {
+                    try {
+                        if (KEY_TYPE_INT.equals(type)) {
+                            values.putInt(key, Integer.parseInt(value));
+                        } else if (KEY_TYPE_BOOL.equals(type)) {
+                            values.putBoolean(key, Boolean.parseBoolean(value));
+                        } else if (KEY_TYPE_STRING.equals(type)) {
+                            values.putString(key, value);
+                        }
+                    } catch (final NumberFormatException e) {
+                        Log.w(MmsService.TAG, "Load carrier value from resources: "
+                                + "invalid " + key + "," + value + "," + type);
+                    }
+                }
+            }).parse();
+        } catch (final Resources.NotFoundException e) {
+            Log.w(MmsService.TAG, "Can not get mms_config.xml");
+        } finally {
+            if (xml != null) {
+                xml.close();
+            }
+        }
+    }
+}
diff --git a/src/android/support/v7/mms/DefaultUserAgentInfoLoader.java b/src/android/support/v7/mms/DefaultUserAgentInfoLoader.java
new file mode 100644
index 0000000..e6191ce
--- /dev/null
+++ b/src/android/support/v7/mms/DefaultUserAgentInfoLoader.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * The default implementation of loader of UA and UAProfUrl
+ */
+class DefaultUserAgentInfoLoader implements UserAgentInfoLoader {
+    // Default values to be used as user agent info
+    private static final String DEFAULT_USER_AGENT = "Android MmsLib/1.0";
+    private static final String DEFAULT_UA_PROF_URL =
+            "http://www.gstatic.com/android/sms/mms_ua_profile.xml";
+
+    private Context mContext;
+    private boolean mLoaded;
+
+    private String mUserAgent;
+    private String mUAProfUrl;
+
+    DefaultUserAgentInfoLoader(final Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public String getUserAgent() {
+        load();
+        return mUserAgent;
+    }
+
+    @Override
+    public String getUAProfUrl() {
+        load();
+        return mUAProfUrl;
+    }
+
+    private void load() {
+        if (mLoaded) {
+            return;
+        }
+        boolean didLoad = false;
+        synchronized (this) {
+            if (!mLoaded) {
+                loadLocked();
+                mLoaded = true;
+                didLoad = true;
+            }
+        }
+        if (didLoad) {
+            Log.i(MmsService.TAG, "Loaded user agent info: "
+                    + "UA=" + mUserAgent + ", UAProfUrl=" + mUAProfUrl);
+        }
+    }
+
+    private void loadLocked() {
+        if (Utils.hasUserAgentApi()) {
+            // load the MMS User agent and UaProfUrl from TelephonyManager APIs
+            final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
+                    Context.TELEPHONY_SERVICE);
+            mUserAgent = telephonyManager.getMmsUserAgent();
+            mUAProfUrl = telephonyManager.getMmsUAProfUrl();
+        }
+        if (TextUtils.isEmpty(mUserAgent)) {
+            mUserAgent = DEFAULT_USER_AGENT;
+        }
+        if (TextUtils.isEmpty(mUAProfUrl)) {
+            mUAProfUrl = DEFAULT_UA_PROF_URL;
+        }
+    }
+}
diff --git a/src/android/support/v7/mms/DownloadRequest.java b/src/android/support/v7/mms/DownloadRequest.java
new file mode 100644
index 0000000..5db01f8
--- /dev/null
+++ b/src/android/support/v7/mms/DownloadRequest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Request to download an MMS
+ */
+class DownloadRequest extends MmsRequest {
+
+    DownloadRequest(final String locationUrl, final Uri pduUri,
+            final PendingIntent sentIntent) {
+        super(locationUrl, pduUri, sentIntent);
+    }
+
+    @Override
+    protected boolean loadRequest(final Context context, final Bundle mmsConfig) {
+        // No need to load PDU from app. Always true.
+        return true;
+    }
+
+    @Override
+    protected boolean transferResponse(Context context, Intent fillIn, byte[] response) {
+        return writePduToContentUri(context, mPduUri, response);
+    }
+
+    @Override
+    protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettingsLoader.Apn apn,
+            Bundle mmsConfig, String userAgent, String uaProfUrl) throws MmsHttpException {
+        final MmsHttpClient httpClient = netMgr.getHttpClient();
+        return httpClient.execute(getHttpRequestUrl(apn), null/*pdu*/, MmsHttpClient.METHOD_GET,
+                !TextUtils.isEmpty(apn.getMmsProxy()), apn.getMmsProxy(), apn.getMmsProxyPort(),
+                mmsConfig, userAgent, uaProfUrl);
+
+    }
+
+    @Override
+    protected String getHttpRequestUrl(final ApnSettingsLoader.Apn apn) {
+        return mLocationUrl;
+    }
+
+    /**
+     * Write pdu bytes to content provider uri
+     *
+     * @param contentUri content provider uri to which bytes should be written
+     * @param pdu Bytes to write
+     * @return true if all bytes successfully written else false
+     */
+    public boolean writePduToContentUri(final Context context, final Uri contentUri,
+            final byte[] pdu) {
+        if (contentUri == null || pdu == null) {
+            return false;
+        }
+        final Callable<Boolean> copyDownloadedPduToOutput = new Callable<Boolean>() {
+            public Boolean call() {
+                ParcelFileDescriptor.AutoCloseOutputStream outStream = null;
+                try {
+                    final ContentResolver cr = context.getContentResolver();
+                    final ParcelFileDescriptor pduFd = cr.openFileDescriptor(contentUri, "w");
+                    outStream = new ParcelFileDescriptor.AutoCloseOutputStream(pduFd);
+                    outStream.write(pdu);
+                    return true;
+                } catch (IOException e) {
+                    Log.e(MmsService.TAG, "Writing PDU to downloader: IO exception", e);
+                    return false;
+                } finally {
+                    if (outStream != null) {
+                        try {
+                            outStream.close();
+                        } catch (IOException ex) {
+                            // Ignore
+                        }
+                    }
+                }
+            }
+        };
+        final Future<Boolean> pendingResult =
+                mPduTransferExecutor.submit(copyDownloadedPduToOutput);
+        try {
+            return pendingResult.get(TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            // Typically a timeout occurred - cancel task
+            pendingResult.cancel(true);
+        }
+        return false;
+    }
+
+    public static final Parcelable.Creator<DownloadRequest> CREATOR
+            = new Parcelable.Creator<DownloadRequest>() {
+        public DownloadRequest createFromParcel(Parcel in) {
+            return new DownloadRequest(in);
+        }
+
+        public DownloadRequest[] newArray(int size) {
+            return new DownloadRequest[size];
+        }
+    };
+
+    private DownloadRequest(Parcel in) {
+        super(in);
+    }
+}
diff --git a/src/android/support/v7/mms/MmsHttpClient.java b/src/android/support/v7/mms/MmsHttpClient.java
new file mode 100644
index 0000000..241e4b8
--- /dev/null
+++ b/src/android/support/v7/mms/MmsHttpClient.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * MMS HTTP client for sending and downloading MMS messages
+ */
+public class MmsHttpClient {
+    static final String METHOD_POST = "POST";
+    static final String METHOD_GET = "GET";
+
+    private static final String HEADER_CONTENT_TYPE = "Content-Type";
+    private static final String HEADER_ACCEPT = "Accept";
+    private static final String HEADER_ACCEPT_LANGUAGE = "Accept-Language";
+    private static final String HEADER_USER_AGENT = "User-Agent";
+
+    // The "Accept" header value
+    private static final String HEADER_VALUE_ACCEPT =
+            "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic";
+    // The "Content-Type" header value
+    private static final String HEADER_VALUE_CONTENT_TYPE_WITH_CHARSET =
+            "application/vnd.wap.mms-message; charset=utf-8";
+    private static final String HEADER_VALUE_CONTENT_TYPE_WITHOUT_CHARSET =
+            "application/vnd.wap.mms-message";
+
+    /*
+     * Macro names
+     */
+    // The raw phone number
+    private static final String MACRO_LINE1 = "LINE1";
+    // The phone number without country code
+    private static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE";
+    // NAI (Network Access Identifier)
+    private static final String MACRO_NAI = "NAI";
+
+    // The possible NAI system property name
+    private static final String NAI_PROPERTY = "persist.radio.cdma.nai";
+
+    private final Context mContext;
+    private final TelephonyManager mTelephonyManager;
+
+    /**
+     * Constructor
+     *
+     * @param context The Context object
+     */
+    MmsHttpClient(Context context) {
+        mContext = context;
+        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    /**
+     * Execute an MMS HTTP request, either a POST (sending) or a GET (downloading)
+     *
+     * @param urlString The request URL, for sending it is usually the MMSC, and for downloading
+     *                  it is the message URL
+     * @param pdu For POST (sending) only, the PDU to send
+     * @param method HTTP method, POST for sending and GET for downloading
+     * @param isProxySet Is there a proxy for the MMSC
+     * @param proxyHost The proxy host
+     * @param proxyPort The proxy port
+     * @param mmsConfig The MMS config to use
+     * @param userAgent The user agent header value
+     * @param uaProfUrl The UA Prof URL header value
+     * @return The HTTP response body
+     * @throws MmsHttpException For any failures
+     */
+    public byte[] execute(String urlString, byte[] pdu, String method, boolean isProxySet,
+            String proxyHost, int proxyPort, Bundle mmsConfig, String userAgent, String uaProfUrl)
+            throws MmsHttpException {
+        Log.d(MmsService.TAG, "HTTP: " + method + " " + Utils.redactUrlForNonVerbose(urlString)
+                + (isProxySet ? (", proxy=" + proxyHost + ":" + proxyPort) : "")
+                + ", PDU size=" + (pdu != null ? pdu.length : 0));
+        checkMethod(method);
+        HttpURLConnection connection = null;
+        try {
+            Proxy proxy = Proxy.NO_PROXY;
+            if (isProxySet) {
+                proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
+            }
+            final URL url = new URL(urlString);
+            // Now get the connection
+            connection = (HttpURLConnection) url.openConnection(proxy);
+            connection.setDoInput(true);
+            connection.setConnectTimeout(
+                    mmsConfig.getInt(CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT,
+                            CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT_DEFAULT));
+            // ------- COMMON HEADERS ---------
+            // Header: Accept
+            connection.setRequestProperty(HEADER_ACCEPT, HEADER_VALUE_ACCEPT);
+            // Header: Accept-Language
+            connection.setRequestProperty(
+                    HEADER_ACCEPT_LANGUAGE, getCurrentAcceptLanguage(Locale.getDefault()));
+            // Header: User-Agent
+            Log.i(MmsService.TAG, "HTTP: User-Agent=" + userAgent);
+            connection.setRequestProperty(HEADER_USER_AGENT, userAgent);
+            // Header: x-wap-profile
+            final String uaProfUrlTagName = mmsConfig.getString(
+                    CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME,
+                    CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME_DEFAULT);
+            if (uaProfUrl != null) {
+                Log.i(MmsService.TAG, "HTTP: UaProfUrl=" + uaProfUrl);
+                connection.setRequestProperty(uaProfUrlTagName, uaProfUrl);
+            }
+            // Add extra headers specified by mms_config.xml's httpparams
+            addExtraHeaders(connection, mmsConfig);
+            // Different stuff for GET and POST
+            if (METHOD_POST.equals(method)) {
+                if (pdu == null || pdu.length < 1) {
+                    Log.e(MmsService.TAG, "HTTP: empty pdu");
+                    throw new MmsHttpException(0/*statusCode*/, "Sending empty PDU");
+                }
+                connection.setDoOutput(true);
+                connection.setRequestMethod(METHOD_POST);
+                if (mmsConfig.getBoolean(
+                        CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
+                        CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER_DEFAULT)) {
+                    connection.setRequestProperty(HEADER_CONTENT_TYPE,
+                            HEADER_VALUE_CONTENT_TYPE_WITH_CHARSET);
+                } else {
+                    connection.setRequestProperty(HEADER_CONTENT_TYPE,
+                            HEADER_VALUE_CONTENT_TYPE_WITHOUT_CHARSET);
+                }
+                if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
+                    logHttpHeaders(connection.getRequestProperties());
+                }
+                connection.setFixedLengthStreamingMode(pdu.length);
+                // Sending request body
+                final OutputStream out =
+                        new BufferedOutputStream(connection.getOutputStream());
+                out.write(pdu);
+                out.flush();
+                out.close();
+            } else if (METHOD_GET.equals(method)) {
+                if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
+                    logHttpHeaders(connection.getRequestProperties());
+                }
+                connection.setRequestMethod(METHOD_GET);
+            }
+            // Get response
+            final int responseCode = connection.getResponseCode();
+            final String responseMessage = connection.getResponseMessage();
+            Log.d(MmsService.TAG, "HTTP: " + responseCode + " " + responseMessage);
+            if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
+                logHttpHeaders(connection.getHeaderFields());
+            }
+            if (responseCode / 100 != 2) {
+                throw new MmsHttpException(responseCode, responseMessage);
+            }
+            final InputStream in = new BufferedInputStream(connection.getInputStream());
+            final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+            final byte[] buf = new byte[4096];
+            int count = 0;
+            while ((count = in.read(buf)) > 0) {
+                byteOut.write(buf, 0, count);
+            }
+            in.close();
+            final byte[] responseBody = byteOut.toByteArray();
+            Log.d(MmsService.TAG, "HTTP: response size="
+                    + (responseBody != null ? responseBody.length : 0));
+            return responseBody;
+        } catch (MalformedURLException e) {
+            final String redactedUrl = Utils.redactUrlForNonVerbose(urlString);
+            Log.e(MmsService.TAG, "HTTP: invalid URL " + redactedUrl, e);
+            throw new MmsHttpException(0/*statusCode*/, "Invalid URL " + redactedUrl, e);
+        } catch (ProtocolException e) {
+            final String redactedUrl = Utils.redactUrlForNonVerbose(urlString);
+            Log.e(MmsService.TAG, "HTTP: invalid URL protocol " + redactedUrl, e);
+            throw new MmsHttpException(0/*statusCode*/, "Invalid URL protocol " + redactedUrl, e);
+        } catch (IOException e) {
+            Log.e(MmsService.TAG, "HTTP: IO failure", e);
+            throw new MmsHttpException(0/*statusCode*/, e);
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    private static void logHttpHeaders(Map<String, List<String>> headers) {
+        final StringBuilder sb = new StringBuilder();
+        if (headers != null) {
+            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
+                final String key = entry.getKey();
+                final List<String> values = entry.getValue();
+                if (values != null) {
+                    for (String value : values) {
+                        sb.append(key).append('=').append(value).append('\n');
+                    }
+                }
+            }
+            Log.v(MmsService.TAG, "HTTP: headers\n" + sb.toString());
+        }
+    }
+
+    private static void checkMethod(String method) throws MmsHttpException {
+        if (!METHOD_GET.equals(method) && !METHOD_POST.equals(method)) {
+            throw new MmsHttpException(0/*statusCode*/, "Invalid method " + method);
+        }
+    }
+
+    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
+
+    /**
+     * Return the Accept-Language header.  Use the current locale plus
+     * US if we are in a different locale than US.
+     * This code copied from the browser's WebSettings.java
+     *
+     * @return Current AcceptLanguage String.
+     */
+    public static String getCurrentAcceptLanguage(Locale locale) {
+        final StringBuilder buffer = new StringBuilder();
+        addLocaleToHttpAcceptLanguage(buffer, locale);
+
+        if (!Locale.US.equals(locale)) {
+            if (buffer.length() > 0) {
+                buffer.append(", ");
+            }
+            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
+        }
+
+        return buffer.toString();
+    }
+
+    /**
+     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
+     * to new standard.
+     */
+    private static String convertObsoleteLanguageCodeToNew(String langCode) {
+        if (langCode == null) {
+            return null;
+        }
+        if ("iw".equals(langCode)) {
+            // Hebrew
+            return "he";
+        } else if ("in".equals(langCode)) {
+            // Indonesian
+            return "id";
+        } else if ("ji".equals(langCode)) {
+            // Yiddish
+            return "yi";
+        }
+        return langCode;
+    }
+
+    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder, Locale locale) {
+        final String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
+        if (language != null) {
+            builder.append(language);
+            final String country = locale.getCountry();
+            if (country != null) {
+                builder.append("-");
+                builder.append(country);
+            }
+        }
+    }
+
+    private static final Pattern MACRO_P = Pattern.compile("##(\\S+)##");
+    /**
+     * Resolve the macro in HTTP param value text
+     * For example, "something##LINE1##something" is resolved to "something9139531419something"
+     *
+     * @param value The HTTP param value possibly containing macros
+     * @return The HTTP param with macro resolved to real value
+     */
+    private String resolveMacro(String value, Bundle mmsConfig) {
+        if (TextUtils.isEmpty(value)) {
+            return value;
+        }
+        final Matcher matcher = MACRO_P.matcher(value);
+        int nextStart = 0;
+        StringBuilder replaced = null;
+        while (matcher.find()) {
+            if (replaced == null) {
+                replaced = new StringBuilder();
+            }
+            final int matchedStart = matcher.start();
+            if (matchedStart > nextStart) {
+                replaced.append(value.substring(nextStart, matchedStart));
+            }
+            final String macro = matcher.group(1);
+            final String macroValue = getHttpParamMacro(macro, mmsConfig);
+            if (macroValue != null) {
+                replaced.append(macroValue);
+            }
+            nextStart = matcher.end();
+        }
+        if (replaced != null && nextStart < value.length()) {
+            replaced.append(value.substring(nextStart));
+        }
+        return replaced == null ? value : replaced.toString();
+    }
+
+    /**
+     * Add extra HTTP headers from mms_config.xml's httpParams, which is a list of key/value
+     * pairs separated by "|". Each key/value pair is separated by ":". Value may contain
+     * macros like "##LINE1##" or "##NAI##" which is resolved with methods in this class
+     *
+     * @param connection The HttpURLConnection that we add headers to
+     * @param mmsConfig The MmsConfig object
+     */
+    private void addExtraHeaders(HttpURLConnection connection, Bundle mmsConfig) {
+        final String extraHttpParams = mmsConfig.getString(
+                CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS);
+        if (!TextUtils.isEmpty(extraHttpParams)) {
+            // Parse the parameter list
+            String paramList[] = extraHttpParams.split("\\|");
+            for (String paramPair : paramList) {
+                String splitPair[] = paramPair.split(":", 2);
+                if (splitPair.length == 2) {
+                    final String name = splitPair[0].trim();
+                    final String value = resolveMacro(splitPair[1].trim(), mmsConfig);
+                    if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) {
+                        // Add the header if the param is valid
+                        connection.setRequestProperty(name, value);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Return the HTTP param macro value.
+     * Example: LINE1 returns the phone number, etc.
+     *
+     * @param macro The macro name
+     * @param mmsConfig The carrier configuration values
+     * @return The value of the defined macro
+     */
+    private String getHttpParamMacro(final String macro, final Bundle mmsConfig) {
+        if (MACRO_LINE1.equals(macro)) {
+            return getSelfNumber();
+        } else if (MACRO_LINE1NOCOUNTRYCODE.equals(macro)) {
+            return PhoneNumberHelper.getNumberNoCountryCode(
+                    getSelfNumber(), getSimOrLocaleCountry());
+        }  else if (MACRO_NAI.equals(macro)) {
+            return getEncodedNai(mmsConfig.getString(
+                    CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX,
+                    CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX_DEFAULT));
+        }
+        return null;
+    }
+
+    /**
+     * Get the device phone number
+     *
+     * @return the phone number text
+     */
+    private String getSelfNumber() {
+        if (Utils.supportMSim()) {
+            final SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
+            final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(
+                    SmsManager.getDefaultSmsSubscriptionId());
+            if (info != null) {
+                return info.getNumber();
+            } else {
+                return null;
+            }
+        } else {
+            return mTelephonyManager.getLine1Number();
+        }
+    }
+
+    /**
+     * Get the country ISO code from SIM or system locale
+     *
+     * @return the country ISO code
+     */
+    private String getSimOrLocaleCountry() {
+        String country = null;
+        if (Utils.supportMSim()) {
+            final SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
+            final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(
+                    SmsManager.getDefaultSmsSubscriptionId());
+            if (info != null) {
+                country = info.getCountryIso();
+            }
+        } else {
+            country = mTelephonyManager.getSimCountryIso();
+        }
+        if (!TextUtils.isEmpty(country)) {
+            return country.toUpperCase();
+        } else {
+            return Locale.getDefault().getCountry();
+        }
+    }
+
+    /**
+     * Get encoded NAI string to use as the HTTP header for some carriers.
+     * On L-MR1+, we call the hidden system API to get this
+     * On L-MR1-, we try to find it via system property.
+     *
+     * @param naiSuffix the suffix to append to NAI before encoding
+     * @return the Base64 encoded NAI string to use as HTTP header
+     */
+    private String getEncodedNai(final String naiSuffix) {
+        String nai;
+        if (Utils.supportMSim()) {
+            nai = getNaiBySystemApi(
+                    getSlotId(Utils.getEffectiveSubscriptionId(MmsManager.DEFAULT_SUB_ID)));
+        } else {
+            nai = getNaiBySystemProperty();
+        }
+        if (!TextUtils.isEmpty(nai)) {
+            Log.i(MmsService.TAG, "NAI is not empty");
+            if (!TextUtils.isEmpty(naiSuffix)) {
+                nai = nai + naiSuffix;
+            }
+            byte[] encoded = null;
+            try {
+                encoded = Base64.encode(nai.getBytes("UTF-8"), Base64.NO_WRAP);
+            } catch (UnsupportedEncodingException e) {
+                encoded = Base64.encode(nai.getBytes(), Base64.NO_WRAP);
+            }
+            try {
+                return new String(encoded, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                return new String(encoded);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoke hidden SubscriptionManager.getSlotIndex(int)
+     *
+     * @param subId the subId
+     * @return the SIM slot ID
+     */
+    private static int getSlotId(final int subId) {
+        try {
+            final Method method = SubscriptionManager.class.getMethod("getSlotIndex", Integer.TYPE);
+            if (method != null) {
+                return (Integer) method.invoke(null, subId);
+            }
+        } catch (Exception e) {
+            Log.w(MmsService.TAG, "SubscriptionManager.getSlotIndex failed " + e);
+        }
+        return -1;
+    }
+
+    /**
+     * Get NAI using hidden TelephonyManager.getNai(int)
+     *
+     * @param slotId the SIM slot ID
+     * @return the NAI string
+     */
+    private String getNaiBySystemApi(final int slotId) {
+        try {
+            final Method method = mTelephonyManager.getClass().getMethod("getNai", Integer.TYPE);
+            if (method != null) {
+                return (String) method.invoke(mTelephonyManager, slotId);
+            }
+        } catch (Exception e) {
+            Log.w(MmsService.TAG, "TelephonyManager.getNai failed " + e);
+        }
+        return null;
+    }
+
+    /**
+     * Get NAI using hidden SystemProperties.get(String)
+     *
+     * @return the NAI string as system property
+     */
+    private static String getNaiBySystemProperty() {
+        try {
+            final Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
+            if (systemPropertiesClass != null) {
+                final Method method = systemPropertiesClass.getMethod("get", String.class);
+                if (method != null) {
+                    return (String) method.invoke(null, NAI_PROPERTY);
+                }
+            }
+        } catch (Exception e) {
+            Log.w(MmsService.TAG, "SystemProperties.get failed " + e);
+        }
+        return null;
+    }
+}
diff --git a/src/android/support/v7/mms/MmsHttpException.java b/src/android/support/v7/mms/MmsHttpException.java
new file mode 100644
index 0000000..545c66d
--- /dev/null
+++ b/src/android/support/v7/mms/MmsHttpException.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+/**
+ * HTTP exception
+ */
+public class MmsHttpException extends Exception {
+    // Optional HTTP status code. 0 means ignore. Otherwise this
+    // should be a valid HTTP status code.
+    private final int mStatusCode;
+
+    public MmsHttpException(int statusCode) {
+        super();
+        mStatusCode = statusCode;
+    }
+
+    public MmsHttpException(int statusCode, String message) {
+        super(message);
+        mStatusCode = statusCode;
+    }
+
+    public MmsHttpException(int statusCode, Throwable cause) {
+        super(cause);
+        mStatusCode = statusCode;
+    }
+
+    public MmsHttpException(int statusCode, String message, Throwable cause) {
+        super(message, cause);
+        mStatusCode = statusCode;
+    }
+
+    public int getStatusCode() {
+        return mStatusCode;
+    }
+}
diff --git a/src/android/support/v7/mms/MmsManager.java b/src/android/support/v7/mms/MmsManager.java
new file mode 100644
index 0000000..642a141
--- /dev/null
+++ b/src/android/support/v7/mms/MmsManager.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telephony.SmsManager;
+import android.util.SparseArray;
+
+/**
+ * The public interface of MMS library
+ */
+public class MmsManager {
+    /**
+     * Default subscription ID
+     */
+    public static final int DEFAULT_SUB_ID = -1;
+
+    // Whether to force legacy MMS sending
+    private static volatile boolean sForceLegacyMms = false;
+
+    // Cached computed overrides for carrier configuration values
+    private static SparseArray<Bundle> sConfigOverridesMap = new SparseArray<>();
+
+    /**
+     * Set the flag about whether to force to use legacy system APIs instead of system MMS API
+     *
+     * @param forceLegacyMms value to set
+     */
+    public static void setForceLegacyMms(boolean forceLegacyMms) {
+        sForceLegacyMms = forceLegacyMms;
+    }
+
+    /**
+     * Set the size of thread pool for request execution.
+     *
+     * Default is 4
+     *
+     * Note: if system MMS API is used, this has no effect
+     *
+     * @param size thread pool size
+     */
+    public static void setThreadPoolSize(int size) {
+        MmsService.setThreadPoolSize(size);
+    }
+
+    /**
+     * Set whether to use wake lock while sending or downloading MMS.
+     *
+     * Default value is true
+     *
+     * Note: if system MMS API is used, this has no effect
+     *
+     * @param useWakeLock true to use wake lock, false otherwise
+     */
+    public static void setUseWakeLock(final boolean useWakeLock) {
+        MmsService.setUseWakeLock(useWakeLock);
+    }
+
+    /**
+     * Set the optional carrier config values loader
+     *
+     * Note: if system MMS API is used, this is used to compute the overrides
+     * of carrier configuration values
+     *
+     * @param loader the carrier config values loader
+     */
+    public static void setCarrierConfigValuesLoader(CarrierConfigValuesLoader loader) {
+        if (loader == null) {
+            throw new IllegalArgumentException("Carrier configuration loader can not be empty");
+        }
+        synchronized (sConfigOverridesMap) {
+            MmsService.setCarrierConfigValuesLoader(loader);
+            sConfigOverridesMap.clear();
+        }
+    }
+
+    /**
+     * Set the optional APN settings loader
+     *
+     * Note: if system MMS API is used, this has no effect
+     *
+     * @param loader the APN settings loader
+     */
+    public static void setApnSettingsLoader(ApnSettingsLoader loader) {
+        if (loader == null) {
+            throw new IllegalArgumentException("APN settings loader can not be empty");
+        }
+        MmsService.setApnSettingsLoader(loader);
+    }
+
+    /**
+     * Set user agent info loader
+     *
+     * Note: if system MMS API is used, this is used to compute the overrides
+     * of carrier configuration values
+
+     * @param loader the user agent info loader
+     */
+    public static void setUserAgentInfoLoader(final UserAgentInfoLoader loader) {
+        if (loader == null) {
+            throw new IllegalArgumentException("User agent info loader can not be empty");
+        }
+        synchronized (sConfigOverridesMap) {
+            MmsService.setUserAgentInfoLoader(loader);
+            sConfigOverridesMap.clear();
+        }
+    }
+
+    /**
+     * Send MMS via platform MMS API (if platform supports and not forced to
+     * use legacy APIs) or legacy APIs
+     *
+     * @param subId the subscription ID of the SIM to use
+     * @param context the Context to use
+     * @param contentUri the content URI of the PDU to be sent
+     * @param locationUrl the optional location URL to use for sending
+     * @param sentIntent the pending intent for returning results
+     */
+    public static void sendMultimediaMessage(int subId, Context context, Uri contentUri,
+            String locationUrl, PendingIntent sentIntent) {
+        if (shouldUseLegacyMms()) {
+            MmsService.startRequest(context, new SendRequest(locationUrl, contentUri, sentIntent));
+        } else {
+            subId = Utils.getEffectiveSubscriptionId(subId);
+            final SmsManager smsManager = Utils.getSmsManager(subId);
+            smsManager.sendMultimediaMessage(context, contentUri, locationUrl,
+                    getConfigOverrides(subId), sentIntent);
+        }
+    }
+
+    /**
+     * Download MMS via platform MMS API (if platform supports and not forced to
+     * use legacy APIs) or legacy APIs
+     *
+     * @param subId the subscription ID of the SIM to use
+     * @param context the Context to use
+     * @param contentUri the content URI of the PDU to be sent
+     * @param locationUrl the optional location URL to use for sending
+     * @param downloadedIntent the pending intent for returning results
+     */
+    public static void downloadMultimediaMessage(int subId, Context context, String locationUrl,
+            Uri contentUri, PendingIntent downloadedIntent) {
+        if (shouldUseLegacyMms()) {
+            MmsService.startRequest(context,
+                    new DownloadRequest(locationUrl, contentUri, downloadedIntent));
+        } else {
+            subId = Utils.getEffectiveSubscriptionId(subId);
+            final SmsManager smsManager = Utils.getSmsManager(subId);
+            smsManager.downloadMultimediaMessage(context, locationUrl, contentUri,
+                    getConfigOverrides(subId), downloadedIntent);
+        }
+    }
+
+    /**
+     * Checks if we should use legacy APIs for MMS.
+     *
+     * @return true if forced to use legacy APIs or platform doesn't supports MMS APIs.
+     */
+    public static boolean shouldUseLegacyMms() {
+        return sForceLegacyMms || !Utils.hasMmsApi();
+    }
+
+    /**
+     * Get carrier configuration values overrides when platform MMS API is called.
+     * We only need to compute this if customized carrier config values loader or
+     * user agent info loader are set
+     *
+     * @param subId the ID of the SIM to use
+     * @return a Bundle containing the overrides
+     */
+    private static Bundle getConfigOverrides(final int subId) {
+        if (!Utils.hasMmsApi()) {
+            // If MMS API is not present, it is not necessary to compute overrides
+            return null;
+        }
+        Bundle overrides = null;
+        synchronized (sConfigOverridesMap) {
+            overrides = sConfigOverridesMap.get(subId);
+            if (overrides == null) {
+                overrides = new Bundle();
+                sConfigOverridesMap.put(subId, overrides);
+                computeOverridesLocked(subId, overrides);
+            }
+        }
+        return overrides;
+    }
+
+    /**
+     * Compute the overrides, incorporating the user agent info
+     *
+     * @param subId the subId of the SIM to use
+     * @param overrides the computed values overrides
+     */
+    private static void computeOverridesLocked(final int subId, final Bundle overrides) {
+        // Overrides not computed yet
+        final CarrierConfigValuesLoader carrierConfigValuesLoader =
+                MmsService.getCarrierConfigValuesLoader();
+        if (carrierConfigValuesLoader != null &&
+                !(carrierConfigValuesLoader instanceof DefaultCarrierConfigValuesLoader)) {
+            // Compute the overrides for carrier config values first if the config loader
+            // is not the default one.
+            final Bundle systemValues = Utils.getSmsManager(subId).getCarrierConfigValues();
+            final Bundle callerValues =
+                    MmsService.getCarrierConfigValuesLoader().get(subId);
+            if (systemValues != null && callerValues != null) {
+                computeConfigDelta(systemValues, callerValues, overrides);
+            } else if (systemValues == null && callerValues != null) {
+                overrides.putAll(callerValues);
+            }
+        }
+        final UserAgentInfoLoader userAgentInfoLoader = MmsService.getUserAgentInfoLoader();
+        if (userAgentInfoLoader != null &&
+                !(userAgentInfoLoader instanceof DefaultUserAgentInfoLoader)) {
+            // Also set the user agent and ua prof url via the overrides
+            // if the user agent loader is not the default one.
+            overrides.putString(UserAgentInfoLoader.CONFIG_USER_AGENT,
+                    userAgentInfoLoader.getUserAgent());
+            overrides.putString(UserAgentInfoLoader.CONFIG_UA_PROF_URL,
+                    userAgentInfoLoader.getUAProfUrl());
+        }
+    }
+
+    /**
+     * Compute the delta between two sets of carrier configuration values: system and caller
+     *
+     * @param systemValues the system config values
+     * @param callerValues the caller's config values
+     * @param delta the delta of values (caller - system), using caller value to override system's
+     */
+    private static void computeConfigDelta(final Bundle systemValues, final Bundle callerValues,
+            final Bundle delta) {
+        for (final String key : callerValues.keySet()) {
+            final Object callerValue = callerValues.get(key);
+            final Object systemValue = systemValues.get(key);
+            if ((callerValue != null && systemValue != null && !callerValue.equals(systemValue)) ||
+                    (callerValue != null && systemValue == null) ||
+                    (callerValue == null && systemValue != null)) {
+                if (callerValue == null || callerValue instanceof String) {
+                    delta.putString(key, (String) callerValue);
+                } else if (callerValue instanceof Integer) {
+                    delta.putInt(key, (Integer) callerValue);
+                } else if (callerValue instanceof Boolean) {
+                    delta.putBoolean(key, (Boolean) callerValue);
+                }
+            }
+        }
+    }
+}
diff --git a/src/android/support/v7/mms/MmsNetworkException.java b/src/android/support/v7/mms/MmsNetworkException.java
new file mode 100644
index 0000000..77e0912
--- /dev/null
+++ b/src/android/support/v7/mms/MmsNetworkException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+/**
+ * MMS network exception
+ */
+class MmsNetworkException extends Exception {
+
+    public MmsNetworkException() {
+        super();
+    }
+
+    public MmsNetworkException(String message) {
+        super(message);
+    }
+
+    public MmsNetworkException(Throwable cause) {
+        super(cause);
+    }
+
+    public MmsNetworkException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/android/support/v7/mms/MmsNetworkManager.java b/src/android/support/v7/mms/MmsNetworkManager.java
new file mode 100644
index 0000000..1021b5a
--- /dev/null
+++ b/src/android/support/v7/mms/MmsNetworkManager.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Build;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Class manages MMS network connectivity using legacy platform APIs
+ * (deprecated since Android L) on pre-L devices (or when forced to
+ * be used on L and later)
+ */
+class MmsNetworkManager {
+    // Hidden platform constants
+    private static final String FEATURE_ENABLE_MMS = "enableMMS";
+    private static final String REASON_VOICE_CALL_ENDED = "2GVoiceCallEnded";
+    private static final int APN_ALREADY_ACTIVE     = 0;
+    private static final int APN_REQUEST_STARTED    = 1;
+    private static final int APN_TYPE_NOT_AVAILABLE = 2;
+    private static final int APN_REQUEST_FAILED     = 3;
+    private static final int APN_ALREADY_INACTIVE   = 4;
+    // A map from platform APN constant to text string
+    private static final String[] APN_RESULT_STRING = new String[]{
+            "already active",
+            "request started",
+            "type not available",
+            "request failed",
+            "already inactive",
+            "unknown",
+    };
+
+    private static final long NETWORK_ACQUIRE_WAIT_INTERVAL_MS = 15000;
+    private static final long DEFAULT_NETWORK_ACQUIRE_TIMEOUT_MS = 180000;
+    private static final String MMS_NETWORK_EXTENSION_TIMER = "mms_network_extension_timer";
+    private static final long MMS_NETWORK_EXTENSION_TIMER_WAIT_MS = 30000;
+
+    private static volatile long sNetworkAcquireTimeoutMs = DEFAULT_NETWORK_ACQUIRE_TIMEOUT_MS;
+
+    /**
+     * Set the network acquire timeout
+     *
+     * @param timeoutMs timeout in millisecond
+     */
+    static void setNetworkAcquireTimeout(final long timeoutMs) {
+        sNetworkAcquireTimeoutMs = timeoutMs;
+    }
+
+    private final Context mContext;
+    private final ConnectivityManager mConnectivityManager;
+
+    // If the connectivity intent receiver is registered
+    private boolean mReceiverRegistered;
+    // Count of requests that are using the MMS network
+    private int mUseCount;
+    // Count of requests that are waiting for connectivity (i.e. in acquireNetwork wait loop)
+    private int mWaitCount;
+    // Timer to extend the network connectivity
+    private Timer mExtensionTimer;
+
+    private final MmsHttpClient mHttpClient;
+
+    private final IntentFilter mConnectivityIntentFilter;
+    private final BroadcastReceiver mConnectivityChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(final Context context, final Intent intent) {
+            if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
+                return;
+            }
+            final int networkType = getConnectivityChangeNetworkType(intent);
+            if (networkType != ConnectivityManager.TYPE_MOBILE_MMS) {
+                return;
+            }
+            onMmsConnectivityChange(context, intent);
+        }
+    };
+
+    MmsNetworkManager(final Context context) {
+        mContext = context;
+        mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        mHttpClient = new MmsHttpClient(mContext);
+        mConnectivityIntentFilter = new IntentFilter();
+        mConnectivityIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        mUseCount = 0;
+        mWaitCount = 0;
+    }
+
+    ConnectivityManager getConnectivityManager() {
+        return mConnectivityManager;
+    }
+
+    MmsHttpClient getHttpClient() {
+        return mHttpClient;
+    }
+
+    /**
+     * Synchronously acquire MMS network connectivity
+     *
+     * @throws MmsNetworkException If failed permanently or timed out
+     */
+    void acquireNetwork() throws MmsNetworkException {
+        Log.i(MmsService.TAG, "Acquire MMS network");
+        synchronized (this) {
+            try {
+                mUseCount++;
+                mWaitCount++;
+                if (mWaitCount == 1) {
+                    // Register the receiver for the first waiting request
+                    registerConnectivityChangeReceiverLocked();
+                }
+                long waitMs = sNetworkAcquireTimeoutMs;
+                final long beginMs = SystemClock.elapsedRealtime();
+                do {
+                    if (!isMobileDataEnabled()) {
+                        // Fast fail if mobile data is not enabled
+                        throw new MmsNetworkException("Mobile data is disabled");
+                    }
+                    // Always try to extend and check the MMS network connectivity
+                    // before we start waiting to make sure we don't miss the change
+                    // of MMS connectivity. As one example, some devices fail to send
+                    // connectivity change intent. So this would make sure we catch
+                    // the state change.
+                    if (extendMmsConnectivityLocked()) {
+                        // Connected
+                        return;
+                    }
+                    try {
+                        wait(Math.min(waitMs, NETWORK_ACQUIRE_WAIT_INTERVAL_MS));
+                    } catch (final InterruptedException e) {
+                        Log.w(MmsService.TAG, "Unexpected exception", e);
+                    }
+                    // Calculate the remaining time to wait
+                    waitMs = sNetworkAcquireTimeoutMs - (SystemClock.elapsedRealtime() - beginMs);
+                } while (waitMs > 0);
+                // Last check
+                if (extendMmsConnectivityLocked()) {
+                    return;
+                } else {
+                    // Reaching here means timed out.
+                    throw new MmsNetworkException("Acquiring MMS network timed out");
+                }
+            } finally {
+                mWaitCount--;
+                if (mWaitCount == 0) {
+                    // Receiver is used to listen to connectivity change and unblock
+                    // the waiting requests. If nobody's waiting on change, there is
+                    // no need for the receiver. The auto extension timer will try
+                    // to maintain the connectivity periodically.
+                    unregisterConnectivityChangeReceiverLocked();
+                }
+            }
+        }
+    }
+
+    /**
+     * Release MMS network connectivity. This is ref counted. So it only disconnect
+     * when the ref count is 0.
+     */
+    void releaseNetwork() {
+        Log.i(MmsService.TAG, "release MMS network");
+        synchronized (this) {
+            mUseCount--;
+            if (mUseCount == 0) {
+                stopNetworkExtensionTimerLocked();
+                endMmsConnectivity();
+            }
+        }
+    }
+
+    String getApnName() {
+        String apnName = null;
+        final NetworkInfo mmsNetworkInfo = mConnectivityManager.getNetworkInfo(
+                ConnectivityManager.TYPE_MOBILE_MMS);
+        if (mmsNetworkInfo != null) {
+            apnName = mmsNetworkInfo.getExtraInfo();
+        }
+        return apnName;
+    }
+
+    // Process mobile MMS connectivity change, waking up the waiting request thread
+    // in certain conditions:
+    // - Successfully connected
+    // - Failed permanently
+    // - Required another kickoff
+    // We don't initiate connection here but just notifyAll so the waiting request
+    // would wake up and retry connection before next wait.
+    private void onMmsConnectivityChange(final Context context, final Intent intent) {
+        if (mUseCount < 1) {
+            return;
+        }
+        final NetworkInfo mmsNetworkInfo =
+                mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
+        // Check availability of the mobile network.
+        if (mmsNetworkInfo != null) {
+            if (REASON_VOICE_CALL_ENDED.equals(mmsNetworkInfo.getReason())) {
+                // This is a very specific fix to handle the case where the phone receives an
+                // incoming call during the time we're trying to setup the mms connection.
+                // When the call ends, restart the process of mms connectivity.
+                // Once the waiting request is unblocked, before the next wait, we would start
+                // MMS network again.
+                unblockWait();
+            } else {
+                final NetworkInfo.State state = mmsNetworkInfo.getState();
+                if (state == NetworkInfo.State.CONNECTED ||
+                        (state == NetworkInfo.State.DISCONNECTED && !isMobileDataEnabled())) {
+                    // Unblock the waiting request when we either connected
+                    // OR
+                    // disconnected due to mobile data disabled therefore needs to fast fail
+                    // (on some devices if mobile data disabled and starting MMS would cause
+                    // an immediate state change to disconnected, so causing a tight loop of
+                    // trying and failing)
+                    // Once the waiting request is unblocked, before the next wait, we would
+                    // check mobile data and start MMS network again. So we should catch
+                    // both the success and the fast failure.
+                    unblockWait();
+                }
+            }
+        }
+    }
+
+    private void unblockWait() {
+        synchronized (this) {
+            notifyAll();
+        }
+    }
+
+    private void startNetworkExtensionTimerLocked() {
+        if (mExtensionTimer == null) {
+            mExtensionTimer = new Timer(MMS_NETWORK_EXTENSION_TIMER, true/*daemon*/);
+            mExtensionTimer.schedule(
+                    new TimerTask() {
+                        @Override
+                        public void run() {
+                            synchronized (this) {
+                                if (mUseCount > 0) {
+                                    try {
+                                        // Try extending the connectivity
+                                        extendMmsConnectivityLocked();
+                                    } catch (final MmsNetworkException e) {
+                                        // Ignore the exception
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    MMS_NETWORK_EXTENSION_TIMER_WAIT_MS);
+        }
+    }
+
+    private void stopNetworkExtensionTimerLocked() {
+        if (mExtensionTimer != null) {
+            mExtensionTimer.cancel();
+            mExtensionTimer = null;
+        }
+    }
+
+    private boolean extendMmsConnectivityLocked() throws MmsNetworkException {
+        final int result = startMmsConnectivity();
+        if (result == APN_ALREADY_ACTIVE) {
+            // Already active
+            startNetworkExtensionTimerLocked();
+            return true;
+        } else if (result != APN_REQUEST_STARTED) {
+            stopNetworkExtensionTimerLocked();
+            throw new MmsNetworkException("Cannot acquire MMS network: " +
+                    result + " - " + getMmsConnectivityResultString(result));
+        }
+        return false;
+    }
+
+    private int startMmsConnectivity() {
+        Log.i(MmsService.TAG, "Start MMS connectivity");
+        try {
+            final Method method = mConnectivityManager.getClass().getMethod(
+                "startUsingNetworkFeature", Integer.TYPE, String.class);
+            if (method != null) {
+                return (Integer) method.invoke(
+                    mConnectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
+            }
+        } catch (final Exception e) {
+            Log.w(MmsService.TAG, "ConnectivityManager.startUsingNetworkFeature failed " + e);
+        }
+        return APN_REQUEST_FAILED;
+    }
+
+    private void endMmsConnectivity() {
+        Log.i(MmsService.TAG, "End MMS connectivity");
+        try {
+            final Method method = mConnectivityManager.getClass().getMethod(
+                "stopUsingNetworkFeature", Integer.TYPE, String.class);
+            if (method != null) {
+                method.invoke(
+                        mConnectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
+            }
+        } catch (final Exception e) {
+            Log.w(MmsService.TAG, "ConnectivityManager.stopUsingNetworkFeature failed " + e);
+        }
+    }
+
+    private void registerConnectivityChangeReceiverLocked() {
+        if (!mReceiverRegistered) {
+            mContext.registerReceiver(mConnectivityChangeReceiver, mConnectivityIntentFilter,
+                    Context.RECEIVER_EXPORTED/*UNAUDITED*/);
+            mReceiverRegistered = true;
+        }
+    }
+
+    private void unregisterConnectivityChangeReceiverLocked() {
+        if (mReceiverRegistered) {
+            mContext.unregisterReceiver(mConnectivityChangeReceiver);
+            mReceiverRegistered = false;
+        }
+    }
+
+    /**
+     * The absence of a connection type.
+     */
+    private static final int TYPE_NONE = -1;
+
+    /**
+     * Get the network type of the connectivity change
+     *
+     * @param intent the broadcast intent of connectivity change
+     * @return The change's network type
+     */
+    private static int getConnectivityChangeNetworkType(final Intent intent) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, TYPE_NONE);
+        } else {
+            final NetworkInfo info = intent.getParcelableExtra(
+                    ConnectivityManager.EXTRA_NETWORK_INFO);
+            if (info != null) {
+                return info.getType();
+            }
+        }
+        return TYPE_NONE;
+    }
+
+    private static String getMmsConnectivityResultString(int result) {
+        if (result < 0 || result >= APN_RESULT_STRING.length) {
+            result = APN_RESULT_STRING.length - 1;
+        }
+        return APN_RESULT_STRING[result];
+    }
+
+    private boolean isMobileDataEnabled() {
+        try {
+            final Class cmClass = mConnectivityManager.getClass();
+            final Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
+            method.setAccessible(true); // Make the method callable
+            // get the setting for "mobile data"
+            return (Boolean) method.invoke(mConnectivityManager);
+        } catch (final Exception e) {
+            Log.w(MmsService.TAG, "TelephonyManager.getMobileDataEnabled failed", e);
+        }
+        return false;
+    }
+}
diff --git a/src/android/support/v7/mms/MmsRequest.java b/src/android/support/v7/mms/MmsRequest.java
new file mode 100644
index 0000000..b96902e
--- /dev/null
+++ b/src/android/support/v7/mms/MmsRequest.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import androidx.appcompat.mms.pdu.GenericPdu;
+import androidx.appcompat.mms.pdu.PduHeaders;
+import androidx.appcompat.mms.pdu.PduParser;
+import androidx.appcompat.mms.pdu.SendConf;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * MMS request base class. This handles the execution of any MMS request.
+ */
+abstract class MmsRequest implements Parcelable {
+    /**
+     * Prepare to make the HTTP request - will download message for sending
+     *
+     * @param context the Context
+     * @param mmsConfig carrier config values to use
+     * @return true if loading request PDU from calling app succeeds, false otherwise
+     */
+    protected abstract boolean loadRequest(Context context, Bundle mmsConfig);
+
+    /**
+     * Transfer the received response to the caller
+     *
+     * @param context the Context
+     * @param fillIn the content of pending intent to be returned
+     * @param response the pdu to transfer
+     * @return true if transferring response PDU to calling app succeeds, false otherwise
+     */
+    protected abstract boolean transferResponse(Context context, Intent fillIn, byte[] response);
+
+    /**
+     * Making the HTTP request to MMSC
+     *
+     * @param context The context
+     * @param netMgr The current {@link MmsNetworkManager}
+     * @param apn The APN
+     * @param mmsConfig The carrier configuration values to use
+     * @param userAgent The User-Agent header value
+     * @param uaProfUrl The UA Prof URL header value
+     * @return The HTTP response data
+     * @throws MmsHttpException If any network error happens
+     */
+    protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr,
+            ApnSettingsLoader.Apn apn, Bundle mmsConfig, String userAgent, String uaProfUrl)
+            throws MmsHttpException;
+
+    /**
+     * Get the HTTP request URL for this MMS request
+     *
+     * @param apn The APN to use
+     * @return The HTTP request URL in text
+     */
+    protected abstract String getHttpRequestUrl(ApnSettingsLoader.Apn apn);
+
+    // Maximum time to spend waiting to read data from a content provider before failing with error.
+    protected static final int TASK_TIMEOUT_MS = 30 * 1000;
+
+    protected final String mLocationUrl;
+    protected final Uri mPduUri;
+    protected final PendingIntent mPendingIntent;
+    // Thread pool for transferring PDU with MMS apps
+    protected final ExecutorService mPduTransferExecutor = Executors.newCachedThreadPool();
+
+    // Whether this request should acquire wake lock
+    private boolean mUseWakeLock;
+
+    protected MmsRequest(final String locationUrl, final Uri pduUri,
+            final PendingIntent pendingIntent) {
+        mLocationUrl = locationUrl;
+        mPduUri = pduUri;
+        mPendingIntent = pendingIntent;
+        mUseWakeLock = true;
+    }
+
+    void setUseWakeLock(final boolean useWakeLock) {
+        mUseWakeLock = useWakeLock;
+    }
+
+    boolean getUseWakeLock() {
+        return mUseWakeLock;
+    }
+
+    /**
+     * Run the MMS request.
+     *
+     * @param context the context to use
+     * @param networkManager the MmsNetworkManager to use to setup MMS network
+     * @param apnSettingsLoader the APN loader
+     * @param carrierConfigValuesLoader the carrier config loader
+     * @param userAgentInfoLoader the user agent info loader
+     */
+    void execute(final Context context, final MmsNetworkManager networkManager,
+            final ApnSettingsLoader apnSettingsLoader,
+            final CarrierConfigValuesLoader carrierConfigValuesLoader,
+            final UserAgentInfoLoader userAgentInfoLoader) {
+        Log.i(MmsService.TAG, "Execute " + this.getClass().getSimpleName());
+        int result = SmsManager.MMS_ERROR_UNSPECIFIED;
+        int httpStatusCode = 0;
+        byte[] response = null;
+        final Bundle mmsConfig = carrierConfigValuesLoader.get(MmsManager.DEFAULT_SUB_ID);
+        if (mmsConfig == null) {
+            Log.e(MmsService.TAG, "Failed to load carrier configuration values");
+            result = SmsManager.MMS_ERROR_CONFIGURATION_ERROR;
+        } else if (!loadRequest(context, mmsConfig)) {
+            Log.e(MmsService.TAG, "Failed to load PDU");
+            result = SmsManager.MMS_ERROR_IO_ERROR;
+        } else {
+            // Everything's OK. Now execute the request.
+            try {
+                // Acquire the MMS network
+                networkManager.acquireNetwork();
+                // Load the potential APNs. In most cases there should be only one APN available.
+                // On some devices on which we can't obtain APN from system, we look up our own
+                // APN list. Since we don't have exact information, we may get a list of potential
+                // APNs to try. Whenever we found a successful APN, we signal it and return.
+                final String apnName = networkManager.getApnName();
+                final List<ApnSettingsLoader.Apn> apns = apnSettingsLoader.get(apnName);
+                if (apns.size() < 1) {
+                    throw new ApnException("No valid APN");
+                } else {
+                    Log.d(MmsService.TAG, "Trying " + apns.size() + " APNs");
+                }
+                final String userAgent = userAgentInfoLoader.getUserAgent();
+                final String uaProfUrl = userAgentInfoLoader.getUAProfUrl();
+                MmsHttpException lastException = null;
+                for (ApnSettingsLoader.Apn apn : apns) {
+                    Log.i(MmsService.TAG, "Using APN ["
+                            + "MMSC=" + apn.getMmsc() + ", "
+                            + "PROXY=" + apn.getMmsProxy() + ", "
+                            + "PORT=" + apn.getMmsProxyPort() + "]");
+                    try {
+                        final String url = getHttpRequestUrl(apn);
+                        // Request a global route for the host to connect
+                        requestRoute(networkManager.getConnectivityManager(), apn, url);
+                        // Perform the HTTP request
+                        response = doHttp(
+                                context, networkManager, apn, mmsConfig, userAgent, uaProfUrl);
+                        // Additional check of whether this is a success
+                        if (isWrongApnResponse(response, mmsConfig)) {
+                            throw new MmsHttpException(0/*statusCode*/, "Invalid sending address");
+                        }
+                        // Notify APN loader this is a valid APN
+                        apn.setSuccess();
+                        result = Activity.RESULT_OK;
+                        break;
+                    } catch (MmsHttpException e) {
+                        Log.w(MmsService.TAG, "HTTP or network failure", e);
+                        lastException = e;
+                    }
+                }
+                if (lastException != null) {
+                    throw lastException;
+                }
+            } catch (ApnException e) {
+                Log.e(MmsService.TAG, "MmsRequest: APN failure", e);
+                result = SmsManager.MMS_ERROR_INVALID_APN;
+            } catch (MmsNetworkException e) {
+                Log.e(MmsService.TAG, "MmsRequest: MMS network acquiring failure", e);
+                result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS;
+            } catch (MmsHttpException e) {
+                Log.e(MmsService.TAG, "MmsRequest: HTTP or network I/O failure", e);
+                result = SmsManager.MMS_ERROR_HTTP_FAILURE;
+                httpStatusCode = e.getStatusCode();
+            } catch (Exception e) {
+                Log.e(MmsService.TAG, "MmsRequest: unexpected failure", e);
+                result = SmsManager.MMS_ERROR_UNSPECIFIED;
+            } finally {
+                // Release MMS network
+                networkManager.releaseNetwork();
+            }
+        }
+        // Process result and send back via PendingIntent
+        returnResult(context, result, response, httpStatusCode);
+    }
+
+    /**
+     * Check if the response indicates a failure when we send to wrong APN.
+     * Sometimes even if you send to the wrong APN, a response in valid PDU format can still
+     * be sent back but with an error status. Check one specific case here.
+     *
+     * TODO: maybe there are other possibilities.
+     *
+     * @param response the response data
+     * @param mmsConfig the carrier configuration values to use
+     * @return false if we find an invalid response case, otherwise true
+     */
+    static boolean isWrongApnResponse(final byte[] response, final Bundle mmsConfig) {
+        if (response != null && response.length > 0) {
+            try {
+                final GenericPdu pdu = new PduParser(
+                        response,
+                        mmsConfig.getBoolean(
+                                CarrierConfigValuesLoader
+                                        .CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
+                                CarrierConfigValuesLoader
+                                        .CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION_DEFAULT))
+                        .parse();
+                if (pdu != null && pdu instanceof SendConf) {
+                    final SendConf sendConf = (SendConf) pdu;
+                    final int responseStatus = sendConf.getResponseStatus();
+                    return responseStatus ==
+                            PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED ||
+                            responseStatus ==
+                                    PduHeaders.RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED;
+                }
+            } catch (RuntimeException e) {
+                Log.w(MmsService.TAG, "Parsing response failed", e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the result back via pending intent
+     *
+     * @param context The context
+     * @param result The result code of execution
+     * @param response The response body
+     * @param httpStatusCode The optional http status code in case of http failure
+     */
+    void returnResult(final Context context, int result, final byte[] response,
+            final int httpStatusCode) {
+        if (mPendingIntent == null) {
+            // Result not needed
+            return;
+        }
+        // Extra information to send back with the pending intent
+        final Intent fillIn = new Intent();
+        if (response != null) {
+            if (!transferResponse(context, fillIn, response)) {
+                // Failed to send PDU data back to caller
+                result = SmsManager.MMS_ERROR_IO_ERROR;
+            }
+        }
+        if (result == SmsManager.MMS_ERROR_HTTP_FAILURE && httpStatusCode != 0) {
+            // For HTTP failure, fill in the status code for more information
+            fillIn.putExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, httpStatusCode);
+        }
+        try {
+            mPendingIntent.send(context, result, fillIn);
+        } catch (PendingIntent.CanceledException e) {
+            Log.e(MmsService.TAG, "Sending pending intent canceled", e);
+        }
+    }
+
+    /**
+     * Request the route to the APN (either proxy host or the MMSC host)
+     *
+     * @param connectivityManager the ConnectivityManager to use
+     * @param apn the current APN
+     * @param url the URL to connect to
+     * @throws MmsHttpException for unknown host or route failure
+     */
+    private static void requestRoute(final ConnectivityManager connectivityManager,
+            final ApnSettingsLoader.Apn apn, final String url) throws MmsHttpException {
+        String host = apn.getMmsProxy();
+        if (TextUtils.isEmpty(host)) {
+            final Uri uri = Uri.parse(url);
+            host = uri.getHost();
+        }
+        boolean success = false;
+        // Request route to all resolved host addresses
+        try {
+            for (final InetAddress addr : InetAddress.getAllByName(host)) {
+                final boolean requested = requestRouteToHostAddress(connectivityManager, addr);
+                if (requested) {
+                    success = true;
+                    Log.i(MmsService.TAG, "Requested route to " + addr);
+                } else {
+                    Log.i(MmsService.TAG, "Could not requested route to " + addr);
+                }
+            }
+            if (!success) {
+                throw new MmsHttpException(0/*statusCode*/, "No route requested");
+            }
+        } catch (UnknownHostException e) {
+            Log.w(MmsService.TAG, "Unknown host " + host);
+            throw new MmsHttpException(0/*statusCode*/, "Unknown host");
+        }
+    }
+
+    private static final Integer TYPE_MOBILE_MMS =
+            Integer.valueOf(ConnectivityManager.TYPE_MOBILE_MMS);
+    /**
+     * Wrapper for platform API requestRouteToHostAddress
+     *
+     * We first try the hidden but correct method on ConnectivityManager. If we can't, use
+     * the old but buggy one
+     *
+     * @param connMgr the ConnectivityManager instance
+     * @param inetAddr the InetAddress to request
+     * @return true if route is successfully setup, false otherwise
+     */
+    private static boolean requestRouteToHostAddress(final ConnectivityManager connMgr,
+            final InetAddress inetAddr) {
+        // First try the good method using reflection
+        try {
+            final Method method = connMgr.getClass().getMethod("requestRouteToHostAddress",
+                    Integer.TYPE, InetAddress.class);
+            if (method != null) {
+                return (Boolean) method.invoke(connMgr, TYPE_MOBILE_MMS, inetAddr);
+            }
+        } catch (Exception e) {
+            Log.w(MmsService.TAG, "ConnectivityManager.requestRouteToHostAddress failed " + e);
+        }
+        // If we fail, try the old but buggy one
+        if (inetAddr instanceof Inet4Address) {
+            try {
+                final Method method = connMgr.getClass().getMethod("requestRouteToHost",
+                        Integer.TYPE, Integer.TYPE);
+                if (method != null) {
+                    return (Boolean) method.invoke(connMgr, TYPE_MOBILE_MMS,
+                        inetAddressToInt(inetAddr));
+                }
+            } catch (Exception e) {
+                Log.w(MmsService.TAG, "ConnectivityManager.requestRouteToHost failed " + e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Convert a IPv4 address from an InetAddress to an integer
+     *
+     * @param inetAddr is an InetAddress corresponding to the IPv4 address
+     * @return the IP address as an integer in network byte order
+     */
+    private static int inetAddressToInt(final InetAddress inetAddr)
+            throws IllegalArgumentException {
+        final byte [] addr = inetAddr.getAddress();
+        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
+                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeByte((byte) (mUseWakeLock ? 1 : 0));
+        parcel.writeString(mLocationUrl);
+        parcel.writeParcelable(mPduUri, 0);
+        parcel.writeParcelable(mPendingIntent, 0);
+    }
+
+    protected MmsRequest(final Parcel in) {
+        final ClassLoader classLoader = MmsRequest.class.getClassLoader();
+        mUseWakeLock = in.readByte() != 0;
+        mLocationUrl = in.readString();
+        mPduUri = in.readParcelable(classLoader);
+        mPendingIntent = in.readParcelable(classLoader);
+    }
+}
diff --git a/src/android/support/v7/mms/MmsService.java b/src/android/support/v7/mms/MmsService.java
new file mode 100644
index 0000000..fb2dee8
--- /dev/null
+++ b/src/android/support/v7/mms/MmsService.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.Process;
+import android.telephony.SmsManager;
+import android.util.Log;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * Service to execute MMS requests using deprecated legacy APIs on older platform (prior to L)
+ */
+public class MmsService extends Service {
+    static final String TAG = "MmsLib";
+
+    //The default number of threads allowed to run MMS requests
+    private static final int DEFAULT_THREAD_POOL_SIZE = 4;
+    // Delay before stopping the service
+    private static final int SERVICE_STOP_DELAY_MILLIS = 2000;
+
+    private static final String EXTRA_REQUEST = "request";
+    private static final String EXTRA_MYPID = "mypid";
+
+    private static final String WAKELOCK_ID = "mmslib_wakelock";
+
+    /**
+     * Thread pool size for each request queue
+     */
+    private static volatile int sThreadPoolSize = DEFAULT_THREAD_POOL_SIZE;
+
+    /**
+     * Optional wake lock to use
+     */
+    private static volatile boolean sUseWakeLock = true;
+    private static volatile PowerManager.WakeLock sWakeLock = null;
+    private static final Object sWakeLockLock = new Object();
+
+    /**
+     * Carrier configuration values loader
+     */
+    private static volatile CarrierConfigValuesLoader sCarrierConfigValuesLoader = null;
+
+    /**
+     * APN loader
+     */
+    private static volatile ApnSettingsLoader sApnSettingsLoader = null;
+
+    /**
+     * UserAgent and UA Prof URL loader
+     */
+    private static volatile UserAgentInfoLoader sUserAgentInfoLoader = null;
+
+    /**
+     * Set the size of thread pool for request execution.
+     * Default is DEFAULT_THREAD_POOL_SIZE
+     *
+     * @param size thread pool size
+     */
+    static void setThreadPoolSize(final int size) {
+        sThreadPoolSize = size;
+    }
+
+    /**
+     * Set whether to use wake lock
+     *
+     * @param useWakeLock true to use wake lock, false otherwise
+     */
+    static void setUseWakeLock(final boolean useWakeLock) {
+        sUseWakeLock = useWakeLock;
+    }
+
+    /**
+     * Set the optional carrier config values
+     *
+     * @param loader the carrier config values loader
+     */
+    static void setCarrierConfigValuesLoader(final CarrierConfigValuesLoader loader) {
+        sCarrierConfigValuesLoader = loader;
+    }
+
+    /**
+     * Get the current carrier config values loader
+     *
+     * @return the carrier config values loader currently set
+     */
+    static CarrierConfigValuesLoader getCarrierConfigValuesLoader() {
+        return sCarrierConfigValuesLoader;
+    }
+
+    /**
+     * Set APN settings loader
+     *
+     * @param loader the APN settings loader
+     */
+    static void setApnSettingsLoader(final ApnSettingsLoader loader) {
+        sApnSettingsLoader = loader;
+    }
+
+    /**
+     * Get the current APN settings loader
+     *
+     * @return the APN settings loader currently set
+     */
+    static ApnSettingsLoader getApnSettingsLoader() {
+        return sApnSettingsLoader;
+    }
+
+    /**
+     * Set user agent info loader
+     *
+     * @param loader the user agent info loader
+     */
+    static void setUserAgentInfoLoader(final UserAgentInfoLoader loader) {
+        sUserAgentInfoLoader = loader;
+    }
+
+    /**
+     * Get the current user agent info loader
+     *
+     * @return the user agent info loader currently set
+     */
+    static UserAgentInfoLoader getUserAgentInfoLoader() {
+        return sUserAgentInfoLoader;
+    }
+
+    /**
+     * Make sure loaders are not null. Set to default if that's the case
+     *
+     * @param context the Context to use
+     */
+    private static void ensureLoaders(final Context context) {
+        if (sUserAgentInfoLoader == null) {
+            sUserAgentInfoLoader = new DefaultUserAgentInfoLoader(context);
+        }
+        if (sCarrierConfigValuesLoader == null) {
+            sCarrierConfigValuesLoader = new DefaultCarrierConfigValuesLoader(context);
+        }
+        if (sApnSettingsLoader == null) {
+            sApnSettingsLoader = new DefaultApnSettingsLoader(context);
+        }
+    }
+
+    /**
+     * Acquire the wake lock
+     *
+     * @param context the context to use
+     */
+    private static void acquireWakeLock(final Context context) {
+        synchronized (sWakeLockLock) {
+            if (sWakeLock == null) {
+                final PowerManager pm =
+                        (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+                sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_ID);
+            }
+            sWakeLock.acquire();
+        }
+    }
+
+    /**
+     * Release the wake lock
+     */
+    private static void releaseWakeLock() {
+        boolean releasedEmptyWakeLock = false;
+        synchronized (sWakeLockLock) {
+            if (sWakeLock != null) {
+                sWakeLock.release();
+            } else {
+                releasedEmptyWakeLock = true;
+            }
+        }
+        if (releasedEmptyWakeLock) {
+            Log.w(TAG, "Releasing empty wake lock");
+        }
+    }
+
+    /**
+     * Check if wake lock is not held (e.g. when service stops)
+     */
+    private static void verifyWakeLockNotHeld() {
+        boolean wakeLockHeld = false;
+        synchronized (sWakeLockLock) {
+            wakeLockHeld = sWakeLock != null && sWakeLock.isHeld();
+        }
+        if (wakeLockHeld) {
+            Log.e(TAG, "Wake lock still held!");
+        }
+    }
+
+    // Remember my PID to discard restarted intent
+    private static volatile int sMyPid = -1;
+
+    /**
+     * Get the current PID
+     *
+     * @return the current PID
+     */
+    private static int getMyPid() {
+        if (sMyPid < 0) {
+            sMyPid = Process.myPid();
+        }
+        return sMyPid;
+    }
+
+    /**
+     * Check if the intent is coming from this process
+     *
+     * @param intent the incoming intent for the service
+     * @return true if the intent is from the current process
+     */
+    private static boolean fromThisProcess(final Intent intent) {
+        final int pid = intent.getIntExtra(EXTRA_MYPID, -1);
+        return pid == getMyPid();
+    }
+
+    // Request execution thread pools. One thread pool for sending and one for downloading.
+    // The size of the thread pool controls the parallelism of request execution.
+    // See {@link setThreadPoolSize}
+    private ExecutorService[] mExecutors = new ExecutorService[2];
+
+    // Active request count
+    private int mActiveRequestCount;
+    // The latest intent startId, used for safely stopping service
+    private int mLastStartId;
+
+    private MmsNetworkManager mNetworkManager;
+
+    // Handler for scheduling service stop
+    private final Handler mHandler = new Handler();
+    // Service stop task
+    private final Runnable mServiceStopRunnable = new Runnable() {
+        @Override
+        public void run() {
+            tryStopService();
+        }
+    };
+
+    /**
+     * Start the service with a request
+     *
+     * @param context the Context to use
+     * @param request the request to start
+     */
+    public static void startRequest(final Context context, final MmsRequest request) {
+        final boolean useWakeLock = sUseWakeLock;
+        request.setUseWakeLock(useWakeLock);
+        final Intent intent = new Intent(context, MmsService.class);
+        intent.putExtra(EXTRA_REQUEST, request);
+        intent.putExtra(EXTRA_MYPID, getMyPid());
+        if (useWakeLock) {
+            acquireWakeLock(context);
+        }
+        if (context.startService(intent) == null) {
+            if (useWakeLock) {
+                releaseWakeLock();
+            }
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        ensureLoaders(this);
+
+        for (int i = 0; i < mExecutors.length; i++) {
+            mExecutors[i] = Executors.newFixedThreadPool(sThreadPoolSize);
+        }
+
+        mNetworkManager = new MmsNetworkManager(this);
+
+        synchronized (this) {
+            mActiveRequestCount = 0;
+            mLastStartId = -1;
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        for (ExecutorService executor : mExecutors) {
+            executor.shutdown();
+        }
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // Always remember the latest startId for use when we try releasing the service
+        synchronized (this) {
+            mLastStartId = startId;
+        }
+        boolean scheduled = false;
+        if (intent != null) {
+            // There is a rare situation that right after a intent is started,
+            // the service gets killed. Then the service will restart with
+            // the old intent which we don't want it to run since it will
+            // break our assumption for wake lock. Check the process ID
+            // embedded in the intent to make sure it is indeed from the
+            // the current life of this service.
+            if (fromThisProcess(intent)) {
+                final MmsRequest request = intent.getParcelableExtra(EXTRA_REQUEST);
+                if (request != null) {
+                    try {
+                        retainService(request, new Runnable() {
+                            @Override
+                            public void run() {
+                                try {
+                                    request.execute(
+                                            MmsService.this,
+                                            mNetworkManager,
+                                            getApnSettingsLoader(),
+                                            getCarrierConfigValuesLoader(),
+                                            getUserAgentInfoLoader());
+                                } catch (Exception e) {
+                                    Log.w(TAG, "Unexpected execution failure", e);
+                                } finally {
+                                    if (request.getUseWakeLock()) {
+                                        releaseWakeLock();
+                                    }
+                                    releaseService();
+                                }
+                            }
+                        });
+                        scheduled = true;
+                    } catch (RejectedExecutionException e) {
+                        // Rare thing happened. Send back failure using the pending intent
+                        // and also release the wake lock.
+                        Log.w(TAG, "Executing request failed " + e);
+                        request.returnResult(this, SmsManager.MMS_ERROR_UNSPECIFIED,
+                                null/*response*/, 0/*httpStatusCode*/);
+                        if (request.getUseWakeLock()) {
+                            releaseWakeLock();
+                        }
+                    }
+                } else {
+                    Log.w(TAG, "Empty request");
+                }
+            } else {
+                Log.w(TAG, "Got a restarted intent from previous incarnation");
+            }
+        } else {
+            Log.w(TAG, "Empty intent");
+        }
+        if (!scheduled) {
+            // If the request is not started successfully, we need to try shutdown the service
+            // if nobody is using it.
+            tryScheduleStop();
+        }
+        return START_NOT_STICKY;
+    }
+
+    /**
+     * Retain the service for executing the request in service thread pool
+     *
+     * @param request The request to execute
+     * @param runnable The runnable to run the request in thread pool
+     */
+    private void retainService(final MmsRequest request, final Runnable runnable) {
+        final ExecutorService executor = getRequestExecutor(request);
+        synchronized (this) {
+            executor.execute(runnable);
+            mActiveRequestCount++;
+        }
+    }
+
+    /**
+     * Release the service from the request. If nobody is using it, schedule service stop.
+     */
+    private void releaseService() {
+        synchronized (this) {
+            mActiveRequestCount--;
+            if (mActiveRequestCount <= 0) {
+                mActiveRequestCount = 0;
+                rescheduleServiceStop();
+            }
+        }
+    }
+
+    /**
+     * Schedule the service stop if there is no active request
+     */
+    private void tryScheduleStop() {
+        synchronized (this) {
+            if (mActiveRequestCount == 0) {
+                rescheduleServiceStop();
+            }
+        }
+    }
+
+    /**
+     * Reschedule service stop task
+     */
+    private void rescheduleServiceStop() {
+        mHandler.removeCallbacks(mServiceStopRunnable);
+        mHandler.postDelayed(mServiceStopRunnable, SERVICE_STOP_DELAY_MILLIS);
+    }
+
+    /**
+     * Really try to stop the service if there is not active request
+     */
+    private void tryStopService() {
+        Boolean stopped = null;
+        synchronized (this) {
+            if (mActiveRequestCount == 0) {
+                stopped = stopSelfResult(mLastStartId);
+            }
+        }
+        logServiceStop(stopped);
+    }
+
+    /**
+     * Log the result of service stopping. Also check wake lock status when service stops.
+     *
+     * @param stopped Not empty if service stop is performed: true if really stopped, false
+     *                if cancelled.
+     */
+    private void logServiceStop(final Boolean stopped) {
+        if (stopped != null) {
+            if (stopped) {
+                Log.i(TAG, "Service successfully stopped");
+                verifyWakeLockNotHeld();
+            } else {
+                Log.i(TAG, "Service stopping cancelled");
+            }
+        }
+    }
+
+    private ExecutorService getRequestExecutor(final MmsRequest request) {
+        if (request instanceof SendRequest) {
+            // Send
+            return mExecutors[0];
+        } else {
+            // Download
+            return mExecutors[1];
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+}
diff --git a/src/android/support/v7/mms/MmsXmlResourceParser.java b/src/android/support/v7/mms/MmsXmlResourceParser.java
new file mode 100644
index 0000000..60d1ed7
--- /dev/null
+++ b/src/android/support/v7/mms/MmsXmlResourceParser.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Base class for a parser of XML resources
+ */
+abstract class MmsXmlResourceParser {
+    /**
+     * Parse the content
+     *
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    protected abstract void parseRecord() throws IOException, XmlPullParserException;
+
+    /**
+     * Get the root tag of the content
+     *
+     * @return the text of root tag
+     */
+    protected abstract String getRootTag();
+
+    private final StringBuilder mLogStringBuilder = new StringBuilder();
+
+    protected final XmlPullParser mInputParser;
+
+    protected MmsXmlResourceParser(XmlPullParser parser) {
+        mInputParser = parser;
+    }
+
+    void parse() {
+        try {
+            // Find the first element
+            if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("ApnsXmlProcessor: expecting start tag @"
+                        + xmlParserDebugContext());
+            }
+            if (!getRootTag().equals(mInputParser.getName())) {
+                Log.w(MmsService.TAG, "Carrier config does not start with " + getRootTag());
+                return;
+            }
+            // We are at the start tag
+            for (;;) {
+                int nextEvent;
+                // Skipping spaces
+                while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT);
+                if (nextEvent == XmlPullParser.START_TAG) {
+                    // Parse one record
+                    parseRecord();
+                } else if (nextEvent == XmlPullParser.END_TAG) {
+                    break;
+                } else {
+                    throw new XmlPullParserException("Expecting start or end tag @"
+                            + xmlParserDebugContext());
+                }
+            }
+        } catch (IOException e) {
+            Log.w(MmsService.TAG, "XmlResourceParser: I/O failure", e);
+        } catch (XmlPullParserException e) {
+            Log.w(MmsService.TAG, "XmlResourceParser: parsing failure", e);
+        }
+    }
+
+    /**
+     * Move XML parser forward to next event type or the end of doc
+     *
+     * @param eventType
+     * @return The final event type we meet
+     * @throws XmlPullParserException
+     * @throws IOException
+     */
+    protected int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException {
+        for (;;) {
+            int nextEvent = mInputParser.next();
+            if (nextEvent == eventType
+                    || nextEvent == XmlPullParser.END_DOCUMENT) {
+                return nextEvent;
+            }
+        }
+    }
+
+    /**
+     * @return The debugging information of the parser's current position
+     */
+    protected String xmlParserDebugContext() {
+        mLogStringBuilder.setLength(0);
+        if (mInputParser != null) {
+            try {
+                final int eventType = mInputParser.getEventType();
+                mLogStringBuilder.append(xmlParserEventString(eventType));
+                if (eventType == XmlPullParser.START_TAG
+                        || eventType == XmlPullParser.END_TAG
+                        || eventType == XmlPullParser.TEXT) {
+                    mLogStringBuilder.append('<').append(mInputParser.getName());
+                    for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
+                        mLogStringBuilder.append(' ')
+                                .append(mInputParser.getAttributeName(i))
+                                .append('=')
+                                .append(mInputParser.getAttributeValue(i));
+                    }
+                    mLogStringBuilder.append("/>");
+                }
+                return mLogStringBuilder.toString();
+            } catch (XmlPullParserException e) {
+                Log.w(MmsService.TAG, "XmlResourceParser exception", e);
+            }
+        }
+        return "Unknown";
+    }
+
+    private static String xmlParserEventString(int event) {
+        switch (event) {
+            case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
+            case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT";
+            case XmlPullParser.START_TAG: return "START_TAG";
+            case XmlPullParser.END_TAG: return "END_TAG";
+            case XmlPullParser.TEXT: return "TEXT";
+        }
+        return Integer.toString(event);
+    }
+}
diff --git a/src/android/support/v7/mms/PhoneNumberHelper.java b/src/android/support/v7/mms/PhoneNumberHelper.java
new file mode 100644
index 0000000..a5bebae
--- /dev/null
+++ b/src/android/support/v7/mms/PhoneNumberHelper.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
+
+/**
+ * Helper methods for phone number formatting
+ * This is isolated into a standalone class since it depends on libphonenumber
+ */
+public class PhoneNumberHelper {
+    /**
+     * Given a phone number, get its national part without country code
+     *
+     * @param number the original number
+     * @param country the country ISO code
+     * @return the national number
+     */
+    static String getNumberNoCountryCode(final String number, final String country) {
+        if (!TextUtils.isEmpty(number)) {
+            final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+            try {
+                final Phonenumber.PhoneNumber phoneNumber = phoneNumberUtil.parse(number, country);
+                if (phoneNumber != null && phoneNumberUtil.isValidNumber(phoneNumber)) {
+                    return phoneNumberUtil
+                            .format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.NATIONAL)
+                            .replaceAll("\\D", "");
+                }
+            } catch (final NumberParseException e) {
+                Log.w(MmsService.TAG, "getNumberNoCountryCode: invalid number " + e);
+            }
+        }
+        return number;
+    }
+}
diff --git a/src/android/support/v7/mms/SendRequest.java b/src/android/support/v7/mms/SendRequest.java
new file mode 100644
index 0000000..a36ffc4
--- /dev/null
+++ b/src/android/support/v7/mms/SendRequest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Request to send an MMS
+ */
+class SendRequest extends MmsRequest {
+    // Max send response PDU size in bytes (exceeding this may cause problem with
+    // system intent delivery).
+    private static final int MAX_SEND_RESPONSE_SIZE = 1000 * 1024;
+
+    private byte[] mPduData;
+
+    SendRequest(final String locationUrl, final Uri pduUri, final PendingIntent sentIntent) {
+        super(locationUrl, pduUri, sentIntent);
+    }
+
+    @Override
+    protected boolean loadRequest(final Context context, final Bundle mmsConfig) {
+        mPduData = readPduFromContentUri(
+                context,
+                mPduUri,
+                mmsConfig.getInt(
+                        CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE,
+                        CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE_DEFAULT));
+        return (mPduData != null);
+    }
+
+    @Override
+    protected boolean transferResponse(final Context context, final Intent fillIn,
+            final byte[] response) {
+        // SendConf pdus are always small and can be included in the intent
+        if (response != null && fillIn != null) {
+            if (response.length > MAX_SEND_RESPONSE_SIZE) {
+                // If the response PDU is too large, it won't be able to fit in
+                // the PendingIntent to be transferred via system IPC.
+                return false;
+            }
+            fillIn.putExtra(SmsManager.EXTRA_MMS_DATA, response);
+        }
+        return true;
+    }
+
+    @Override
+    protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettingsLoader.Apn apn,
+            Bundle mmsConfig, String userAgent, String uaProfUrl) throws MmsHttpException {
+        final MmsHttpClient httpClient = netMgr.getHttpClient();
+        return httpClient.execute(getHttpRequestUrl(apn), mPduData, MmsHttpClient.METHOD_POST,
+                !TextUtils.isEmpty(apn.getMmsProxy()), apn.getMmsProxy(), apn.getMmsProxyPort(),
+                mmsConfig, userAgent, uaProfUrl);
+    }
+
+    @Override
+    protected String getHttpRequestUrl(final ApnSettingsLoader.Apn apn) {
+        return !TextUtils.isEmpty(mLocationUrl) ? mLocationUrl : apn.getMmsc();
+    }
+
+    /**
+     * Read pdu from content provider uri
+     *
+     * @param contentUri content provider uri from which to read
+     * @param maxSize maximum number of bytes to read
+     * @return pdu bytes if succeeded else null
+     */
+    public byte[] readPduFromContentUri(final Context context, final Uri contentUri,
+            final int maxSize) {
+        if (contentUri == null) {
+            return null;
+        }
+        final Callable<byte[]> copyPduToArray = new Callable<byte[]>() {
+            public byte[] call() {
+                ParcelFileDescriptor.AutoCloseInputStream inStream = null;
+                try {
+                    final ContentResolver cr = context.getContentResolver();
+                    final ParcelFileDescriptor pduFd = cr.openFileDescriptor(contentUri, "r");
+                    inStream = new ParcelFileDescriptor.AutoCloseInputStream(pduFd);
+                    // Request one extra byte to make sure file not bigger than maxSize
+                    final byte[] readBuf = new byte[maxSize+1];
+                    final int bytesRead = inStream.read(readBuf, 0, maxSize+1);
+                    if (bytesRead <= 0) {
+                        Log.e(MmsService.TAG, "Reading PDU from sender: empty PDU");
+                        return null;
+                    }
+                    if (bytesRead > maxSize) {
+                        Log.e(MmsService.TAG, "Reading PDU from sender: PDU too large");
+                        return null;
+                    }
+                    // Copy and return the exact length of bytes
+                    final byte[] result = new byte[bytesRead];
+                    System.arraycopy(readBuf, 0, result, 0, bytesRead);
+                    return result;
+                } catch (IOException e) {
+                    Log.e(MmsService.TAG, "Reading PDU from sender: IO exception", e);
+                    return null;
+                } finally {
+                    if (inStream != null) {
+                        try {
+                            inStream.close();
+                        } catch (IOException ex) {
+                            // Ignore
+                        }
+                    }
+                }
+            }
+        };
+        final Future<byte[]> pendingResult = mPduTransferExecutor.submit(copyPduToArray);
+        try {
+            return pendingResult.get(TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            // Typically a timeout occurred - cancel task
+            pendingResult.cancel(true);
+        }
+        return null;
+    }
+
+    public static final Parcelable.Creator<SendRequest> CREATOR
+            = new Parcelable.Creator<SendRequest>() {
+        public SendRequest createFromParcel(Parcel in) {
+            return new SendRequest(in);
+        }
+
+        public SendRequest[] newArray(int size) {
+            return new SendRequest[size];
+        }
+    };
+
+    private SendRequest(Parcel in) {
+        super(in);
+    }
+}
diff --git a/src/android/support/v7/mms/UserAgentInfoLoader.java b/src/android/support/v7/mms/UserAgentInfoLoader.java
new file mode 100644
index 0000000..783f99c
--- /dev/null
+++ b/src/android/support/v7/mms/UserAgentInfoLoader.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+/**
+ * Interface to load UserAgent and UA Prof URL
+ */
+public interface UserAgentInfoLoader {
+    // Carrier configuration keys for passing as config overrides into system MMS service
+    public static final String CONFIG_USER_AGENT = "userAgent";
+    public static final String CONFIG_UA_PROF_URL = "uaProfUrl";
+
+    /**
+     * Get UserAgent value
+     *
+     * @return the text of UserAgent
+     */
+    String getUserAgent();
+
+    /**
+     * Get UA Profile URL
+     *
+     * @return the URL of UA profile
+     */
+    String getUAProfUrl();
+}
diff --git a/src/android/support/v7/mms/Utils.java b/src/android/support/v7/mms/Utils.java
new file mode 100644
index 0000000..593e444
--- /dev/null
+++ b/src/android/support/v7/mms/Utils.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2015 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 androidx.appcompat.mms;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Utility methods
+ */
+class Utils {
+    /**
+     * Check if MMS API is available
+     *
+     * @return true if MMS API is available, false otherwise
+     */
+    static boolean hasMmsApi() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+    }
+
+    /**
+     * Check if support multi-SIM
+     *
+     * @return true if MSIM is supported, false otherwise
+     */
+    static boolean supportMSim() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1;
+    }
+
+    /**
+     * Check if support APIs for getting UserAgent and UAProfUrl
+     *
+     * @return true if those APIs are supported, false otherwise
+     */
+    static boolean hasUserAgentApi() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+    }
+
+    /**
+     * Get system SmsManager
+     *
+     * @param subId the subscription ID of the SmsManager
+     * @return the SmsManager for the input subId
+     */
+    static SmsManager getSmsManager(final int subId) {
+        if (supportMSim()) {
+            return SmsManager.getSmsManagerForSubscriptionId(subId);
+        } else {
+            return SmsManager.getDefault();
+        }
+    }
+
+    /**
+     * Get the real subscription ID if the input is -1
+     *
+     * @param subId input subscription ID
+     * @return the default SMS subscription ID if the input is -1, otherwise the original
+     */
+    static int getEffectiveSubscriptionId(int subId) {
+        if (supportMSim()) {
+            if (subId == MmsManager.DEFAULT_SUB_ID) {
+                subId = SmsManager.getDefaultSmsSubscriptionId();
+            }
+        }
+        if (subId < 0) {
+            subId = MmsManager.DEFAULT_SUB_ID;
+        }
+        return subId;
+    }
+
+    /**
+     * Get MCC/MNC of an SIM subscription
+     *
+     * @param context the Context to use
+     * @param subId the SIM subId
+     * @return a non-empty array with exactly two elements, first is mcc and last is mnc.
+     */
+    static int[] getMccMnc(final Context context, final int subId) {
+        final int[] mccMnc = new int[] { 0, 0 };
+        if (Utils.supportMSim()) {
+            final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
+            final SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId);
+            if (subInfo != null) {
+                mccMnc[0] = subInfo.getMcc();
+                mccMnc[1] = subInfo.getMnc();
+            }
+        } else {
+            final TelephonyManager telephonyManager =
+                    (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+            final String mccMncString = telephonyManager.getSimOperator();
+            try {
+                mccMnc[0] = Integer.parseInt(mccMncString.substring(0, 3));
+                mccMnc[1] = Integer.parseInt(mccMncString.substring(3));
+            } catch (Exception e) {
+                Log.w(MmsService.TAG, "Invalid mcc/mnc from system " + mccMncString + ": " + e);
+                mccMnc[0] = 0;
+                mccMnc[1] = 0;
+            }
+        }
+        return mccMnc;
+    }
+
+    /**
+     * Get a subscription's Context so we can load resources from it
+     *
+     * @param context the sub-independent Context
+     * @param subId the SIM's subId
+     * @return the sub-dependent Context
+     */
+    static Context getSubDepContext(final Context context, final int subId) {
+        if (!supportMSim()) {
+            return context;
+        }
+        final int[] mccMnc = getMccMnc(context, subId);
+        final int mcc = mccMnc[0];
+        final int mnc = mccMnc[1];
+        if (mcc == 0 && mnc == 0) {
+            return context;
+        }
+        final Configuration subConfig = new Configuration();
+        subConfig.mcc = mcc;
+        subConfig.mnc = mnc;
+        return context.createConfigurationContext(subConfig);
+    }
+
+    /**
+     * Redact the URL for non-VERBOSE logging. Replace url with only the host part and the length
+     * of the input URL string.
+     *
+     * @param urlString
+     * @return
+     */
+    static String redactUrlForNonVerbose(String urlString) {
+        if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
+            // Don't redact for VERBOSE level logging
+            return urlString;
+        }
+        if (TextUtils.isEmpty(urlString)) {
+            return urlString;
+        }
+        String protocol = "http";
+        String host = "";
+        try {
+            final URL url = new URL(urlString);
+            protocol = url.getProtocol();
+            host = url.getHost();
+        } catch (MalformedURLException e) {
+            // Ignore
+        }
+        // Print "http://host[length]"
+        final StringBuilder sb = new StringBuilder();
+        sb.append(protocol).append("://").append(host)
+                .append("[").append(urlString.length()).append("]");
+        return sb.toString();
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/AcknowledgeInd.java b/src/android/support/v7/mms/pdu/AcknowledgeInd.java
new file mode 100644
index 0000000..b2ca729
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/AcknowledgeInd.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * M-Acknowledge.ind PDU.
+ */
+public class AcknowledgeInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-Acknowledge.ind pdu.
+     *
+     * @param mmsVersion current viersion of mms
+     * @param transactionId the transaction-id value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     *         NullPointerException if transactionId is null.
+     */
+    public AcknowledgeInd(int mmsVersion, byte[] transactionId)
+            throws InvalidHeaderValueException {
+        super();
+
+        setMessageType(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    AcknowledgeInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Report-Allowed field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getReportAllowed() {
+        return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Report-Allowed field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReportAllowed(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/Base64.java b/src/android/support/v7/mms/pdu/Base64.java
new file mode 100644
index 0000000..18c2959
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/Base64.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class Base64 {
+    /**
+     * Used to get the number of Quadruples.
+     */
+    static final int FOURBYTE = 4;
+
+    /**
+     * Byte used to pad output.
+     */
+    static final byte PAD = (byte) '=';
+
+    /**
+     * The base length.
+     */
+    static final int BASELENGTH = 255;
+
+    // Create arrays to hold the base64 characters
+    private static byte[] base64Alphabet = new byte[BASELENGTH];
+
+    // Populating the character arrays
+    static {
+        for (int i = 0; i < BASELENGTH; i++) {
+            base64Alphabet[i] = (byte) -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--) {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--) {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+        for (int i = '9'; i >= '0'; i--) {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param base64Data Byte array containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decodeBase64(byte[] base64Data) {
+        // RFC 2045 requires that we discard ALL non-Base64 characters
+        base64Data = discardNonBase64(base64Data);
+
+        // handle the edge case, so we don't have to worry about it later
+        if (base64Data.length == 0) {
+            return new byte[0];
+        }
+
+        int numberQuadruple = base64Data.length / FOURBYTE;
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
+
+        // Throw away anything not in base64Data
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        {
+            // this sizes the output array properly - rlw
+            int lastData = base64Data.length;
+            // ignore the '=' padding
+            while (base64Data[lastData - 1] == PAD) {
+                if (--lastData == 0) {
+                    return new byte[0];
+                }
+            }
+            decodedData = new byte[lastData - numberQuadruple];
+        }
+
+        for (int i = 0; i < numberQuadruple; i++) {
+            dataIndex = i * 4;
+            marker0 = base64Data[dataIndex + 2];
+            marker1 = base64Data[dataIndex + 3];
+
+            b1 = base64Alphabet[base64Data[dataIndex]];
+            b2 = base64Alphabet[base64Data[dataIndex + 1]];
+
+            if (marker0 != PAD && marker1 != PAD) {
+                //No PAD e.g 3cQl
+                b3 = base64Alphabet[marker0];
+                b4 = base64Alphabet[marker1];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
+            } else if (marker0 == PAD) {
+                //Two PAD e.g. 3c[Pad][Pad]
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+            } else if (marker1 == PAD) {
+                //One PAD e.g. 3cQ[Pad]
+                b3 = base64Alphabet[marker0];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            }
+            encodedIndex += 3;
+        }
+        return decodedData;
+    }
+
+    /**
+     * Check octect wheter it is a base64 encoding.
+     *
+     * @param octect to be checked byte
+     * @return ture if it is base64 encoding, false otherwise.
+     */
+    private static boolean isBase64(byte octect) {
+        if (octect == PAD) {
+            return true;
+        } else if (base64Alphabet[octect] == -1) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Discards any characters outside of the base64 alphabet, per
+     * the requirements on page 25 of RFC 2045 - "Any characters
+     * outside of the base64 alphabet are to be ignored in base64
+     * encoded data."
+     *
+     * @param data The base-64 encoded data to groom
+     * @return The data, less non-base64 characters (see RFC 2045).
+     */
+    static byte[] discardNonBase64(byte[] data) {
+        byte groomedData[] = new byte[data.length];
+        int bytesCopied = 0;
+
+        for (int i = 0; i < data.length; i++) {
+            if (isBase64(data[i])) {
+                groomedData[bytesCopied++] = data[i];
+            }
+        }
+
+        byte packedData[] = new byte[bytesCopied];
+
+        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+
+        return packedData;
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/CharacterSets.java b/src/android/support/v7/mms/pdu/CharacterSets.java
new file mode 100644
index 0000000..e03ee60
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/CharacterSets.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+
+public class CharacterSets {
+    /**
+     * IANA assigned MIB enum numbers.
+     *
+     * From wap-230-wsp-20010705-a.pdf
+     * Any-charset = <Octet 128>
+     * Equivalent to the special RFC2616 charset value "*"
+     */
+    public static final int ANY_CHARSET = 0x00;
+    public static final int US_ASCII    = 0x03;
+    public static final int ISO_8859_1  = 0x04;
+    public static final int ISO_8859_2  = 0x05;
+    public static final int ISO_8859_3  = 0x06;
+    public static final int ISO_8859_4  = 0x07;
+    public static final int ISO_8859_5  = 0x08;
+    public static final int ISO_8859_6  = 0x09;
+    public static final int ISO_8859_7  = 0x0A;
+    public static final int ISO_8859_8  = 0x0B;
+    public static final int ISO_8859_9  = 0x0C;
+    public static final int SHIFT_JIS   = 0x11;
+    public static final int UTF_8       = 0x6A;
+    public static final int BIG5        = 0x07EA;
+    public static final int UCS2        = 0x03E8;
+    public static final int UTF_16      = 0x03F7;
+
+    /**
+     * If the encoding of given data is unsupported, use UTF_8 to decode it.
+     */
+    public static final int DEFAULT_CHARSET = UTF_8;
+
+    /**
+     * Array of MIB enum numbers.
+     */
+    private static final int[] MIBENUM_NUMBERS = {
+        ANY_CHARSET,
+        US_ASCII,
+        ISO_8859_1,
+        ISO_8859_2,
+        ISO_8859_3,
+        ISO_8859_4,
+        ISO_8859_5,
+        ISO_8859_6,
+        ISO_8859_7,
+        ISO_8859_8,
+        ISO_8859_9,
+        SHIFT_JIS,
+        UTF_8,
+        BIG5,
+        UCS2,
+        UTF_16,
+    };
+
+    /**
+     * The Well-known-charset Mime name.
+     */
+    public static final String MIMENAME_ANY_CHARSET = "*";
+    public static final String MIMENAME_US_ASCII    = "us-ascii";
+    public static final String MIMENAME_ISO_8859_1  = "iso-8859-1";
+    public static final String MIMENAME_ISO_8859_2  = "iso-8859-2";
+    public static final String MIMENAME_ISO_8859_3  = "iso-8859-3";
+    public static final String MIMENAME_ISO_8859_4  = "iso-8859-4";
+    public static final String MIMENAME_ISO_8859_5  = "iso-8859-5";
+    public static final String MIMENAME_ISO_8859_6  = "iso-8859-6";
+    public static final String MIMENAME_ISO_8859_7  = "iso-8859-7";
+    public static final String MIMENAME_ISO_8859_8  = "iso-8859-8";
+    public static final String MIMENAME_ISO_8859_9  = "iso-8859-9";
+    public static final String MIMENAME_SHIFT_JIS   = "shift_JIS";
+    public static final String MIMENAME_UTF_8       = "utf-8";
+    public static final String MIMENAME_BIG5        = "big5";
+    public static final String MIMENAME_UCS2        = "iso-10646-ucs-2";
+    public static final String MIMENAME_UTF_16      = "utf-16";
+
+    public static final String DEFAULT_CHARSET_NAME = MIMENAME_UTF_8;
+
+    /**
+     * Array of the names of character sets.
+     */
+    private static final String[] MIME_NAMES = {
+        MIMENAME_ANY_CHARSET,
+        MIMENAME_US_ASCII,
+        MIMENAME_ISO_8859_1,
+        MIMENAME_ISO_8859_2,
+        MIMENAME_ISO_8859_3,
+        MIMENAME_ISO_8859_4,
+        MIMENAME_ISO_8859_5,
+        MIMENAME_ISO_8859_6,
+        MIMENAME_ISO_8859_7,
+        MIMENAME_ISO_8859_8,
+        MIMENAME_ISO_8859_9,
+        MIMENAME_SHIFT_JIS,
+        MIMENAME_UTF_8,
+        MIMENAME_BIG5,
+        MIMENAME_UCS2,
+        MIMENAME_UTF_16,
+    };
+
+    private static final HashMap<Integer, String> MIBENUM_TO_NAME_MAP;
+    private static final HashMap<String, Integer> NAME_TO_MIBENUM_MAP;
+
+    static {
+        // Create the HashMaps.
+        MIBENUM_TO_NAME_MAP = new HashMap<Integer, String>();
+        NAME_TO_MIBENUM_MAP = new HashMap<String, Integer>();
+        assert(MIBENUM_NUMBERS.length == MIME_NAMES.length);
+        int count = MIBENUM_NUMBERS.length - 1;
+        for(int i = 0; i <= count; i++) {
+            MIBENUM_TO_NAME_MAP.put(MIBENUM_NUMBERS[i], MIME_NAMES[i]);
+            NAME_TO_MIBENUM_MAP.put(MIME_NAMES[i], MIBENUM_NUMBERS[i]);
+        }
+    }
+
+    private CharacterSets() {} // Non-instantiatable
+
+    /**
+     * Map an MIBEnum number to the name of the charset which this number
+     * is assigned to by IANA.
+     *
+     * @param mibEnumValue An IANA assigned MIBEnum number.
+     * @return The name string of the charset.
+     * @throws UnsupportedEncodingException
+     */
+    public static String getMimeName(int mibEnumValue)
+            throws UnsupportedEncodingException {
+        String name = MIBENUM_TO_NAME_MAP.get(mibEnumValue);
+        if (name == null) {
+            throw new UnsupportedEncodingException();
+        }
+        return name;
+    }
+
+    /**
+     * Map a well-known charset name to its assigned MIBEnum number.
+     *
+     * @param mimeName The charset name.
+     * @return The MIBEnum number assigned by IANA for this charset.
+     * @throws UnsupportedEncodingException
+     */
+    public static int getMibEnumValue(String mimeName)
+            throws UnsupportedEncodingException {
+        if(null == mimeName) {
+            return -1;
+        }
+
+        Integer mibEnumValue = NAME_TO_MIBENUM_MAP.get(mimeName);
+        if (mibEnumValue == null) {
+            throw new UnsupportedEncodingException();
+        }
+        return mibEnumValue;
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/ContentType.java b/src/android/support/v7/mms/pdu/ContentType.java
new file mode 100644
index 0000000..eee98c1
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/ContentType.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import java.util.ArrayList;
+
+public class ContentType {
+    public static final String MMS_MESSAGE       = "application/vnd.wap.mms-message";
+    // The phony content type for generic PDUs (e.g. ReadOrig.ind,
+    // Notification.ind, Delivery.ind).
+    public static final String MMS_GENERIC       = "application/vnd.wap.mms-generic";
+    public static final String MULTIPART_MIXED   = "application/vnd.wap.multipart.mixed";
+    public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+    public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
+
+    public static final String TEXT_PLAIN        = "text/plain";
+    public static final String TEXT_HTML         = "text/html";
+    public static final String TEXT_VCALENDAR    = "text/x-vCalendar";
+    public static final String TEXT_VCARD        = "text/x-vCard";
+
+    public static final String IMAGE_UNSPECIFIED = "image/*";
+    public static final String IMAGE_JPEG        = "image/jpeg";
+    public static final String IMAGE_JPG         = "image/jpg";
+    public static final String IMAGE_GIF         = "image/gif";
+    public static final String IMAGE_WBMP        = "image/vnd.wap.wbmp";
+    public static final String IMAGE_PNG         = "image/png";
+    public static final String IMAGE_X_MS_BMP    = "image/x-ms-bmp";
+
+    public static final String AUDIO_UNSPECIFIED = "audio/*";
+    public static final String AUDIO_AAC         = "audio/aac";
+    public static final String AUDIO_AMR         = "audio/amr";
+    public static final String AUDIO_IMELODY     = "audio/imelody";
+    public static final String AUDIO_MID         = "audio/mid";
+    public static final String AUDIO_MIDI        = "audio/midi";
+    public static final String AUDIO_MP3         = "audio/mp3";
+    public static final String AUDIO_MPEG3       = "audio/mpeg3";
+    public static final String AUDIO_MPEG        = "audio/mpeg";
+    public static final String AUDIO_MPG         = "audio/mpg";
+    public static final String AUDIO_MP4         = "audio/mp4";
+    public static final String AUDIO_X_MID       = "audio/x-mid";
+    public static final String AUDIO_X_MIDI      = "audio/x-midi";
+    public static final String AUDIO_X_MP3       = "audio/x-mp3";
+    public static final String AUDIO_X_MPEG3     = "audio/x-mpeg3";
+    public static final String AUDIO_X_MPEG      = "audio/x-mpeg";
+    public static final String AUDIO_X_MPG       = "audio/x-mpg";
+    public static final String AUDIO_3GPP        = "audio/3gpp";
+    public static final String AUDIO_X_WAV       = "audio/x-wav";
+    public static final String AUDIO_OGG         = "application/ogg";
+
+    public static final String VIDEO_UNSPECIFIED = "video/*";
+    public static final String VIDEO_3GPP        = "video/3gpp";
+    public static final String VIDEO_3G2         = "video/3gpp2";
+    public static final String VIDEO_H263        = "video/h263";
+    public static final String VIDEO_MP4         = "video/mp4";
+
+    public static final String APP_SMIL          = "application/smil";
+    public static final String APP_WAP_XHTML     = "application/vnd.wap.xhtml+xml";
+    public static final String APP_XHTML         = "application/xhtml+xml";
+
+    public static final String APP_DRM_CONTENT   = "application/vnd.oma.drm.content";
+    public static final String APP_DRM_MESSAGE   = "application/vnd.oma.drm.message";
+
+    private static final ArrayList<String> sSupportedContentTypes = new ArrayList<String>();
+    private static final ArrayList<String> sSupportedImageTypes = new ArrayList<String>();
+    private static final ArrayList<String> sSupportedAudioTypes = new ArrayList<String>();
+    private static final ArrayList<String> sSupportedVideoTypes = new ArrayList<String>();
+
+    static {
+        sSupportedContentTypes.add(TEXT_PLAIN);
+        sSupportedContentTypes.add(TEXT_HTML);
+        sSupportedContentTypes.add(TEXT_VCALENDAR);
+        sSupportedContentTypes.add(TEXT_VCARD);
+
+        sSupportedContentTypes.add(IMAGE_JPEG);
+        sSupportedContentTypes.add(IMAGE_GIF);
+        sSupportedContentTypes.add(IMAGE_WBMP);
+        sSupportedContentTypes.add(IMAGE_PNG);
+        sSupportedContentTypes.add(IMAGE_JPG);
+        sSupportedContentTypes.add(IMAGE_X_MS_BMP);
+        //supportedContentTypes.add(IMAGE_SVG); not yet supported.
+
+        sSupportedContentTypes.add(AUDIO_AAC);
+        sSupportedContentTypes.add(AUDIO_AMR);
+        sSupportedContentTypes.add(AUDIO_IMELODY);
+        sSupportedContentTypes.add(AUDIO_MID);
+        sSupportedContentTypes.add(AUDIO_MIDI);
+        sSupportedContentTypes.add(AUDIO_MP3);
+        sSupportedContentTypes.add(AUDIO_MP4);
+        sSupportedContentTypes.add(AUDIO_MPEG3);
+        sSupportedContentTypes.add(AUDIO_MPEG);
+        sSupportedContentTypes.add(AUDIO_MPG);
+        sSupportedContentTypes.add(AUDIO_X_MID);
+        sSupportedContentTypes.add(AUDIO_X_MIDI);
+        sSupportedContentTypes.add(AUDIO_X_MP3);
+        sSupportedContentTypes.add(AUDIO_X_MPEG3);
+        sSupportedContentTypes.add(AUDIO_X_MPEG);
+        sSupportedContentTypes.add(AUDIO_X_MPG);
+        sSupportedContentTypes.add(AUDIO_X_WAV);
+        sSupportedContentTypes.add(AUDIO_3GPP);
+        sSupportedContentTypes.add(AUDIO_OGG);
+
+        sSupportedContentTypes.add(VIDEO_3GPP);
+        sSupportedContentTypes.add(VIDEO_3G2);
+        sSupportedContentTypes.add(VIDEO_H263);
+        sSupportedContentTypes.add(VIDEO_MP4);
+
+        sSupportedContentTypes.add(APP_SMIL);
+        sSupportedContentTypes.add(APP_WAP_XHTML);
+        sSupportedContentTypes.add(APP_XHTML);
+
+        sSupportedContentTypes.add(APP_DRM_CONTENT);
+        sSupportedContentTypes.add(APP_DRM_MESSAGE);
+
+        // add supported image types
+        sSupportedImageTypes.add(IMAGE_JPEG);
+        sSupportedImageTypes.add(IMAGE_GIF);
+        sSupportedImageTypes.add(IMAGE_WBMP);
+        sSupportedImageTypes.add(IMAGE_PNG);
+        sSupportedImageTypes.add(IMAGE_JPG);
+        sSupportedImageTypes.add(IMAGE_X_MS_BMP);
+
+        // add supported audio types
+        sSupportedAudioTypes.add(AUDIO_AAC);
+        sSupportedAudioTypes.add(AUDIO_AMR);
+        sSupportedAudioTypes.add(AUDIO_IMELODY);
+        sSupportedAudioTypes.add(AUDIO_MID);
+        sSupportedAudioTypes.add(AUDIO_MIDI);
+        sSupportedAudioTypes.add(AUDIO_MP3);
+        sSupportedAudioTypes.add(AUDIO_MPEG3);
+        sSupportedAudioTypes.add(AUDIO_MPEG);
+        sSupportedAudioTypes.add(AUDIO_MPG);
+        sSupportedAudioTypes.add(AUDIO_MP4);
+        sSupportedAudioTypes.add(AUDIO_X_MID);
+        sSupportedAudioTypes.add(AUDIO_X_MIDI);
+        sSupportedAudioTypes.add(AUDIO_X_MP3);
+        sSupportedAudioTypes.add(AUDIO_X_MPEG3);
+        sSupportedAudioTypes.add(AUDIO_X_MPEG);
+        sSupportedAudioTypes.add(AUDIO_X_MPG);
+        sSupportedAudioTypes.add(AUDIO_X_WAV);
+        sSupportedAudioTypes.add(AUDIO_3GPP);
+        sSupportedAudioTypes.add(AUDIO_OGG);
+
+        // add supported video types
+        sSupportedVideoTypes.add(VIDEO_3GPP);
+        sSupportedVideoTypes.add(VIDEO_3G2);
+        sSupportedVideoTypes.add(VIDEO_H263);
+        sSupportedVideoTypes.add(VIDEO_MP4);
+    }
+
+    // This class should never be instantiated.
+    private ContentType() {
+    }
+
+    public static boolean isSupportedType(String contentType) {
+        return (null != contentType) && sSupportedContentTypes.contains(contentType);
+    }
+
+    public static boolean isSupportedImageType(String contentType) {
+        return isImageType(contentType) && isSupportedType(contentType);
+    }
+
+    public static boolean isSupportedAudioType(String contentType) {
+        return isAudioType(contentType) && isSupportedType(contentType);
+    }
+
+    public static boolean isSupportedVideoType(String contentType) {
+        return isVideoType(contentType) && isSupportedType(contentType);
+    }
+
+    public static boolean isTextType(String contentType) {
+        return (null != contentType) && contentType.startsWith("text/");
+    }
+
+    public static boolean isImageType(String contentType) {
+        return (null != contentType) && contentType.startsWith("image/");
+    }
+
+    public static boolean isAudioType(String contentType) {
+        return (null != contentType) && contentType.startsWith("audio/");
+    }
+
+    public static boolean isVideoType(String contentType) {
+        return (null != contentType) && contentType.startsWith("video/");
+    }
+
+    public static boolean isDrmType(String contentType) {
+        return (null != contentType)
+                && (contentType.equals(APP_DRM_CONTENT)
+                        || contentType.equals(APP_DRM_MESSAGE));
+    }
+
+    public static boolean isUnspecified(String contentType) {
+        return (null != contentType) && contentType.endsWith("*");
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ArrayList<String> getImageTypes() {
+        return (ArrayList<String>) sSupportedImageTypes.clone();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ArrayList<String> getAudioTypes() {
+        return (ArrayList<String>) sSupportedAudioTypes.clone();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ArrayList<String> getVideoTypes() {
+        return (ArrayList<String>) sSupportedVideoTypes.clone();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ArrayList<String> getSupportedTypes() {
+        return (ArrayList<String>) sSupportedContentTypes.clone();
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/DeliveryInd.java b/src/android/support/v7/mms/pdu/DeliveryInd.java
new file mode 100644
index 0000000..1ee1539
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/DeliveryInd.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * M-Delivery.Ind Pdu.
+ */
+public class DeliveryInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public DeliveryInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_DELIVERY_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    DeliveryInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value, should not be null
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get Status value.
+     *
+     * @return the value
+     */
+    public int getStatus() {
+        return mPduHeaders.getOctet(PduHeaders.STATUS);
+    }
+
+    /**
+     * Set Status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.STATUS);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public EncodedStringValue getStatusText() {return null;}
+     *     public void setStatusText(EncodedStringValue value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/EncodedStringValue.java b/src/android/support/v7/mms/pdu/EncodedStringValue.java
new file mode 100644
index 0000000..0a5d2be
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/EncodedStringValue.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+/**
+ * Encoded-string-value = Text-string | Value-length Char-set Text-string
+ */
+public class EncodedStringValue implements Cloneable {
+    private static final String TAG = "EncodedStringValue";
+    private static final boolean DEBUG = false;
+    private static final boolean LOCAL_LOGV = false;
+
+    /**
+     * The Char-set value.
+     */
+    private int mCharacterSet;
+
+    /**
+     * The Text-string value.
+     */
+    private byte[] mData;
+
+    /**
+     * Constructor.
+     *
+     * @param charset the Char-set value
+     * @param data the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public EncodedStringValue(int charset, byte[] data) {
+        // TODO: CharSet needs to be validated against MIBEnum.
+        if(null == data) {
+            throw new NullPointerException("EncodedStringValue: Text-string is null.");
+        }
+
+        mCharacterSet = charset;
+        mData = new byte[data.length];
+        System.arraycopy(data, 0, mData, 0, data.length);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param data the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public EncodedStringValue(byte[] data) {
+        this(CharacterSets.DEFAULT_CHARSET, data);
+    }
+
+    public EncodedStringValue(String data) {
+        try {
+            mData = data.getBytes(CharacterSets.DEFAULT_CHARSET_NAME);
+            mCharacterSet = CharacterSets.DEFAULT_CHARSET;
+        } catch (UnsupportedEncodingException e) {
+            Log.e(TAG, "Default encoding must be supported.", e);
+        }
+    }
+
+    /**
+     * Get Char-set value.
+     *
+     * @return the value
+     */
+    public int getCharacterSet() {
+        return mCharacterSet;
+    }
+
+    /**
+     * Set Char-set value.
+     *
+     * @param charset the Char-set value
+     */
+    public void setCharacterSet(int charset) {
+        // TODO: CharSet needs to be validated against MIBEnum.
+        mCharacterSet = charset;
+    }
+
+    /**
+     * Get Text-string value.
+     *
+     * @return the value
+     */
+    public byte[] getTextString() {
+        byte[] byteArray = new byte[mData.length];
+
+        System.arraycopy(mData, 0, byteArray, 0, mData.length);
+        return byteArray;
+    }
+
+    /**
+     * Set Text-string value.
+     *
+     * @param textString the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public void setTextString(byte[] textString) {
+        if(null == textString) {
+            throw new NullPointerException("EncodedStringValue: Text-string is null.");
+        }
+
+        mData = new byte[textString.length];
+        System.arraycopy(textString, 0, mData, 0, textString.length);
+    }
+
+    /**
+     * Convert this object to a {@link java.lang.String}. If the encoding of
+     * the EncodedStringValue is null or unsupported, it will be
+     * treated as iso-8859-1 encoding.
+     *
+     * @return The decoded String.
+     */
+    public String getString()  {
+        if (CharacterSets.ANY_CHARSET == mCharacterSet) {
+            return new String(mData); // system default encoding.
+        } else {
+            try {
+                String name = CharacterSets.getMimeName(mCharacterSet);
+                return new String(mData, name);
+            } catch (UnsupportedEncodingException e) {
+            	if (LOCAL_LOGV) {
+            		Log.v(TAG, e.getMessage(), e);
+            	}
+            	try {
+                    return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
+                } catch (UnsupportedEncodingException e2) {
+                    return new String(mData); // system default encoding.
+                }
+            }
+        }
+    }
+
+    /**
+     * Append to Text-string.
+     *
+     * @param textString the textString to append
+     * @throws NullPointerException if the text String is null
+     *                      or an IOException occured.
+     */
+    public void appendTextString(byte[] textString) {
+        if(null == textString) {
+            throw new NullPointerException("Text-string is null.");
+        }
+
+        if(null == mData) {
+            mData = new byte[textString.length];
+            System.arraycopy(textString, 0, mData, 0, textString.length);
+        } else {
+            ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
+            try {
+                newTextString.write(mData);
+                newTextString.write(textString);
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new NullPointerException(
+                        "appendTextString: failed when write a new Text-string");
+            }
+
+            mData = newTextString.toByteArray();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public Object clone() throws CloneNotSupportedException {
+        int len = mData.length;
+        byte[] dstBytes = new byte[len];
+        System.arraycopy(mData, 0, dstBytes, 0, len);
+
+        try {
+            return new EncodedStringValue(mCharacterSet, dstBytes);
+        } catch (Exception e) {
+            Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
+            e.printStackTrace();
+            throw new CloneNotSupportedException(e.getMessage());
+        }
+    }
+
+    /**
+     * Split this encoded string around matches of the given pattern.
+     *
+     * @param pattern the delimiting pattern
+     * @return the array of encoded strings computed by splitting this encoded
+     *         string around matches of the given pattern
+     */
+    public EncodedStringValue[] split(String pattern) {
+        String[] temp = getString().split(pattern);
+        EncodedStringValue[] ret = new EncodedStringValue[temp.length];
+        for (int i = 0; i < ret.length; ++i) {
+            try {
+                ret[i] = new EncodedStringValue(mCharacterSet,
+                        temp[i].getBytes());
+            } catch (NullPointerException e) {
+                // Can't arrive here
+                return null;
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Extract an EncodedStringValue[] from a given String.
+     */
+    public static EncodedStringValue[] extract(String src) {
+        String[] values = src.split(";");
+
+        ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
+        for (int i = 0; i < values.length; i++) {
+            if (values[i].length() > 0) {
+                list.add(new EncodedStringValue(values[i]));
+            }
+        }
+
+        int len = list.size();
+        if (len > 0) {
+            return list.toArray(new EncodedStringValue[len]);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Concatenate an EncodedStringValue[] into a single String.
+     */
+    public static String concat(EncodedStringValue[] addr) {
+        StringBuilder sb = new StringBuilder();
+        int maxIndex = addr.length - 1;
+        for (int i = 0; i <= maxIndex; i++) {
+            sb.append(addr[i].getString());
+            if (i < maxIndex) {
+                sb.append(";");
+            }
+        }
+
+        return sb.toString();
+    }
+
+    public static EncodedStringValue copy(EncodedStringValue value) {
+        if (value == null) {
+            return null;
+        }
+
+        return new EncodedStringValue(value.mCharacterSet, value.mData);
+    }
+
+    public static EncodedStringValue[] encodeStrings(String[] array) {
+        int count = array.length;
+        if (count > 0) {
+            EncodedStringValue[] encodedArray = new EncodedStringValue[count];
+            for (int i = 0; i < count; i++) {
+                encodedArray[i] = new EncodedStringValue(array[i]);
+            }
+            return encodedArray;
+        }
+        return null;
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/GenericPdu.java b/src/android/support/v7/mms/pdu/GenericPdu.java
new file mode 100644
index 0000000..a19520c
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/GenericPdu.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class GenericPdu {
+    /**
+     * The headers of pdu.
+     */
+    PduHeaders mPduHeaders = null;
+
+    /**
+     * Constructor.
+     */
+    public GenericPdu() {
+        mPduHeaders = new PduHeaders();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param headers Headers for this PDU.
+     */
+    GenericPdu(PduHeaders headers) {
+        mPduHeaders = headers;
+    }
+
+    /**
+     * Get the headers of this PDU.
+     *
+     * @return A PduHeaders of this PDU.
+     */
+    PduHeaders getPduHeaders() {
+        return mPduHeaders;
+    }
+
+    /**
+     * Get X-Mms-Message-Type field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getMessageType() {
+        return mPduHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
+    }
+
+    /**
+     * Set X-Mms-Message-Type field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if field's value is not Octet.
+     */
+    public void setMessageType(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.MESSAGE_TYPE);
+    }
+
+    /**
+     * Get X-Mms-MMS-Version field value.
+     *
+     * @return the X-Mms-MMS-Version value
+     */
+    public int getMmsVersion() {
+        return mPduHeaders.getOctet(PduHeaders.MMS_VERSION);
+    }
+
+    /**
+     * Set X-Mms-MMS-Version field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if field's value is not Octet.
+     */
+    public void setMmsVersion(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.MMS_VERSION);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+       return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/InvalidHeaderValueException.java b/src/android/support/v7/mms/pdu/InvalidHeaderValueException.java
new file mode 100644
index 0000000..6df4974
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/InvalidHeaderValueException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * Thrown when an invalid header value was set.
+ */
+public class InvalidHeaderValueException extends MmsException {
+    private static final long serialVersionUID = -2053384496042052262L;
+
+    /**
+     * Constructs an InvalidHeaderValueException with no detailed message.
+     */
+    public InvalidHeaderValueException() {
+        super();
+    }
+
+    /**
+     * Constructs an InvalidHeaderValueException with the specified detailed message.
+     *
+     * @param message the detailed message.
+     */
+    public InvalidHeaderValueException(String message) {
+        super(message);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/MmsException.java b/src/android/support/v7/mms/pdu/MmsException.java
new file mode 100644
index 0000000..1237e90
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/MmsException.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * A generic exception that is thrown by the Mms client.
+ */
+public class MmsException extends Exception {
+    private static final long serialVersionUID = -7323249827281485390L;
+
+    /**
+     * Creates a new MmsException.
+     */
+    public MmsException() {
+        super();
+    }
+
+    /**
+     * Creates a new MmsException with the specified detail message.
+     *
+     * @param message the detail message.
+     */
+    public MmsException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new MmsException with the specified cause.
+     *
+     * @param cause the cause.
+     */
+    public MmsException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Creates a new MmsException with the specified detail message and cause.
+     *
+     * @param message the detail message.
+     * @param cause the cause.
+     */
+    public MmsException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/MultimediaMessagePdu.java b/src/android/support/v7/mms/pdu/MultimediaMessagePdu.java
new file mode 100644
index 0000000..69670b6
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/MultimediaMessagePdu.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * Multimedia message PDU.
+ */
+public class MultimediaMessagePdu extends GenericPdu{
+    /**
+     * The body.
+     */
+    private PduBody mMessageBody;
+
+    /**
+     * Constructor.
+     */
+    public MultimediaMessagePdu() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param header the header of this PDU
+     * @param body the body of this PDU
+     */
+    public MultimediaMessagePdu(PduHeaders header, PduBody body) {
+        super(header);
+        mMessageBody = body;
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    MultimediaMessagePdu(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get body of the PDU.
+     *
+     * @return the body
+     */
+    public PduBody getBody() {
+        return mMessageBody;
+    }
+
+    /**
+     * Set body of the PDU.
+     *
+     * @param body the body
+     */
+    public void setBody(PduBody body) {
+        mMessageBody = body;
+    }
+
+    /**
+     * Get subject.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getSubject() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Set subject.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setSubject(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Add a "To" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addTo(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-Mms-Priority value.
+     *
+     * @return the value
+     */
+    public int getPriority() {
+        return mPduHeaders.getOctet(PduHeaders.PRIORITY);
+    }
+
+    /**
+     * Set X-Mms-Priority value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setPriority(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.PRIORITY);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value in seconds.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/NotificationInd.java b/src/android/support/v7/mms/pdu/NotificationInd.java
new file mode 100644
index 0000000..cad6ac4
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/NotificationInd.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * M-Notification.ind PDU.
+ */
+public class NotificationInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public NotificationInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    NotificationInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Content-Class Value.
+     *
+     * @return the value
+     */
+    public int getContentClass() {
+        return mPduHeaders.getOctet(PduHeaders.CONTENT_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Content-Class Value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setContentClass(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.CONTENT_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Content-Location value.
+     * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
+     * Content-location-value = Uri-value
+     *
+     * @return the value
+     */
+    public byte[] getContentLocation() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_LOCATION);
+    }
+
+    /**
+     * Set X-Mms-Content-Location value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setContentLocation(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_LOCATION);
+    }
+
+    /**
+     * Get X-Mms-Expiry value.
+     *
+     * Expiry-value = Value-length
+     *      (Absolute-token Date-value | Relative-token Delta-seconds-value)
+     *
+     * @return the value
+     */
+    public long getExpiry() {
+        return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Set X-Mms-Expiry value.
+     *
+     * @param value the value
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setExpiry(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+       return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Message-Size value.
+     * Message-size-value = Long-integer
+     *
+     * @return the value
+     */
+    public long getMessageSize() {
+        return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Set X-Mms-Message-Size value.
+     *
+     * @param value the value
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setMessageSize(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Get subject.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getSubject() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Set subject.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setSubject(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id.
+     *
+     * @return the value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report Value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report Value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public byte getDistributionIndicator() {return 0x00;}
+     *     public void setDistributionIndicator(byte value) {}
+     *
+     *     public ElementDescriptorValue getElementDescriptor() {return null;}
+     *     public void getElementDescriptor(ElementDescriptorValue value) {}
+     *
+     *     public byte getPriority() {return 0x00;}
+     *     public void setPriority(byte value) {}
+     *
+     *     public byte getRecommendedRetrievalMode() {return 0x00;}
+     *     public void setRecommendedRetrievalMode(byte value) {}
+     *
+     *     public byte getRecommendedRetrievalModeText() {return 0x00;}
+     *     public void setRecommendedRetrievalModeText(byte value) {}
+     *
+     *     public byte[] getReplaceId() {return 0x00;}
+     *     public void setReplaceId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     *
+     *     public byte getStored() {return 0x00;}
+     *     public void setStored(byte value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/NotifyRespInd.java b/src/android/support/v7/mms/pdu/NotifyRespInd.java
new file mode 100644
index 0000000..c28458b
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/NotifyRespInd.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * M-NofifyResp.ind PDU.
+ */
+public class NotifyRespInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-NotifyResp.ind pdu.
+     *
+     * @param mmsVersion current version of mms
+     * @param transactionId the transaction-id value
+     * @param status the status value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     *         NullPointerException if transactionId is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public NotifyRespInd(int mmsVersion,
+                         byte[] transactionId,
+                         int status) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+        setStatus(status);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    NotifyRespInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Report-Allowed field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getReportAllowed() {
+        return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Report-Allowed field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setReportAllowed(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Status field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.STATUS);
+    }
+
+    /**
+     * GetX-Mms-Status field value.
+     *
+     * @return the X-Mms-Status value
+     */
+    public int getStatus() {
+        return mPduHeaders.getOctet(PduHeaders.STATUS);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     *         RuntimeException if an undeclared error occurs.
+     */
+    public void setTransactionId(byte[] value) {
+            mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/PduBody.java b/src/android/support/v7/mms/pdu/PduBody.java
new file mode 100644
index 0000000..fa2b4a6
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/PduBody.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+public class PduBody {
+    private Vector<PduPart> mParts = null;
+
+    private Map<String, PduPart> mPartMapByContentId = null;
+    private Map<String, PduPart> mPartMapByContentLocation = null;
+    private Map<String, PduPart> mPartMapByName = null;
+    private Map<String, PduPart> mPartMapByFileName = null;
+
+    /**
+     * Constructor.
+     */
+    public PduBody() {
+        mParts = new Vector<PduPart>();
+
+        mPartMapByContentId = new HashMap<String, PduPart>();
+        mPartMapByContentLocation  = new HashMap<String, PduPart>();
+        mPartMapByName = new HashMap<String, PduPart>();
+        mPartMapByFileName = new HashMap<String, PduPart>();
+    }
+
+    private void putPartToMaps(PduPart part) {
+        // Put part to mPartMapByContentId.
+        byte[] contentId = part.getContentId();
+        if(null != contentId) {
+            mPartMapByContentId.put(new String(contentId), part);
+        }
+
+        // Put part to mPartMapByContentLocation.
+        byte[] contentLocation = part.getContentLocation();
+        if(null != contentLocation) {
+            String clc = new String(contentLocation);
+            mPartMapByContentLocation.put(clc, part);
+        }
+
+        // Put part to mPartMapByName.
+        byte[] name = part.getName();
+        if(null != name) {
+            String clc = new String(name);
+            mPartMapByName.put(clc, part);
+        }
+
+        // Put part to mPartMapByFileName.
+        byte[] fileName = part.getFilename();
+        if(null != fileName) {
+            String clc = new String(fileName);
+            mPartMapByFileName.put(clc, part);
+        }
+    }
+
+    /**
+     * Appends the specified part to the end of this body.
+     *
+     * @param part part to be appended
+     * @return true when success, false when fail
+     * @throws NullPointerException when part is null
+     */
+    public boolean addPart(PduPart part) {
+        if(null == part) {
+            throw new NullPointerException();
+        }
+
+        putPartToMaps(part);
+        return mParts.add(part);
+    }
+
+    /**
+     * Inserts the specified part at the specified position.
+     *
+     * @param index index at which the specified part is to be inserted
+     * @param part part to be inserted
+     * @throws NullPointerException when part is null
+     */
+    public void addPart(int index, PduPart part) {
+        if(null == part) {
+            throw new NullPointerException();
+        }
+
+        putPartToMaps(part);
+        mParts.add(index, part);
+    }
+
+    /**
+     * Removes the part at the specified position.
+     *
+     * @param index index of the part to return
+     * @return part at the specified index
+     */
+    public PduPart removePart(int index) {
+        return mParts.remove(index);
+    }
+
+    /**
+     * Remove all of the parts.
+     */
+    public void removeAll() {
+        mParts.clear();
+    }
+
+    /**
+     * Get the part at the specified position.
+     *
+     * @param index index of the part to return
+     * @return part at the specified index
+     */
+    public PduPart getPart(int index) {
+        return mParts.get(index);
+    }
+
+    /**
+     * Get the index of the specified part.
+     *
+     * @param part the part object
+     * @return index the index of the first occurrence of the part in this body
+     */
+    public int getPartIndex(PduPart part) {
+        return mParts.indexOf(part);
+    }
+
+    /**
+     * Get the number of parts.
+     *
+     * @return the number of parts
+     */
+    public int getPartsNum() {
+        return mParts.size();
+    }
+
+    /**
+     * Get pdu part by content id.
+     *
+     * @param cid the value of content id.
+     * @return the pdu part.
+     */
+    public PduPart getPartByContentId(String cid) {
+        return mPartMapByContentId.get(cid);
+    }
+
+    /**
+     * Get pdu part by Content-Location. Content-Location of part is
+     * the same as filename and name(param of content-type).
+     *
+     * @param contentLocation the content location.
+     * @return the pdu part.
+     */
+    public PduPart getPartByContentLocation(String contentLocation) {
+        return mPartMapByContentLocation.get(contentLocation);
+    }
+
+    /**
+     * Get pdu part by name.
+     *
+     * @param name the value of filename.
+     * @return the pdu part.
+     */
+    public PduPart getPartByName(String name) {
+        return mPartMapByName.get(name);
+    }
+
+    /**
+     * Get pdu part by filename.
+     *
+     * @param filename the value of filename.
+     * @return the pdu part.
+     */
+    public PduPart getPartByFileName(String filename) {
+        return mPartMapByFileName.get(filename);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/PduContentTypes.java b/src/android/support/v7/mms/pdu/PduContentTypes.java
new file mode 100644
index 0000000..9639119
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/PduContentTypes.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class PduContentTypes {
+    /**
+     * All content types. From:
+     * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.htm
+     */
+    static final String[] contentTypes = {
+        "*/*",                                        /* 0x00 */
+        "text/*",                                     /* 0x01 */
+        "text/html",                                  /* 0x02 */
+        "text/plain",                                 /* 0x03 */
+        "text/x-hdml",                                /* 0x04 */
+        "text/x-ttml",                                /* 0x05 */
+        "text/x-vCalendar",                           /* 0x06 */
+        "text/x-vCard",                               /* 0x07 */
+        "text/vnd.wap.wml",                           /* 0x08 */
+        "text/vnd.wap.wmlscript",                     /* 0x09 */
+        "text/vnd.wap.wta-event",                     /* 0x0A */
+        "multipart/*",                                /* 0x0B */
+        "multipart/mixed",                            /* 0x0C */
+        "multipart/form-data",                        /* 0x0D */
+        "multipart/byterantes",                       /* 0x0E */
+        "multipart/alternative",                      /* 0x0F */
+        "application/*",                              /* 0x10 */
+        "application/java-vm",                        /* 0x11 */
+        "application/x-www-form-urlencoded",          /* 0x12 */
+        "application/x-hdmlc",                        /* 0x13 */
+        "application/vnd.wap.wmlc",                   /* 0x14 */
+        "application/vnd.wap.wmlscriptc",             /* 0x15 */
+        "application/vnd.wap.wta-eventc",             /* 0x16 */
+        "application/vnd.wap.uaprof",                 /* 0x17 */
+        "application/vnd.wap.wtls-ca-certificate",    /* 0x18 */
+        "application/vnd.wap.wtls-user-certificate",  /* 0x19 */
+        "application/x-x509-ca-cert",                 /* 0x1A */
+        "application/x-x509-user-cert",               /* 0x1B */
+        "image/*",                                    /* 0x1C */
+        "image/gif",                                  /* 0x1D */
+        "image/jpeg",                                 /* 0x1E */
+        "image/tiff",                                 /* 0x1F */
+        "image/png",                                  /* 0x20 */
+        "image/vnd.wap.wbmp",                         /* 0x21 */
+        "application/vnd.wap.multipart.*",            /* 0x22 */
+        "application/vnd.wap.multipart.mixed",        /* 0x23 */
+        "application/vnd.wap.multipart.form-data",    /* 0x24 */
+        "application/vnd.wap.multipart.byteranges",   /* 0x25 */
+        "application/vnd.wap.multipart.alternative",  /* 0x26 */
+        "application/xml",                            /* 0x27 */
+        "text/xml",                                   /* 0x28 */
+        "application/vnd.wap.wbxml",                  /* 0x29 */
+        "application/x-x968-cross-cert",              /* 0x2A */
+        "application/x-x968-ca-cert",                 /* 0x2B */
+        "application/x-x968-user-cert",               /* 0x2C */
+        "text/vnd.wap.si",                            /* 0x2D */
+        "application/vnd.wap.sic",                    /* 0x2E */
+        "text/vnd.wap.sl",                            /* 0x2F */
+        "application/vnd.wap.slc",                    /* 0x30 */
+        "text/vnd.wap.co",                            /* 0x31 */
+        "application/vnd.wap.coc",                    /* 0x32 */
+        "application/vnd.wap.multipart.related",      /* 0x33 */
+        "application/vnd.wap.sia",                    /* 0x34 */
+        "text/vnd.wap.connectivity-xml",              /* 0x35 */
+        "application/vnd.wap.connectivity-wbxml",     /* 0x36 */
+        "application/pkcs7-mime",                     /* 0x37 */
+        "application/vnd.wap.hashed-certificate",     /* 0x38 */
+        "application/vnd.wap.signed-certificate",     /* 0x39 */
+        "application/vnd.wap.cert-response",          /* 0x3A */
+        "application/xhtml+xml",                      /* 0x3B */
+        "application/wml+xml",                        /* 0x3C */
+        "text/css",                                   /* 0x3D */
+        "application/vnd.wap.mms-message",            /* 0x3E */
+        "application/vnd.wap.rollover-certificate",   /* 0x3F */
+        "application/vnd.wap.locc+wbxml",             /* 0x40 */
+        "application/vnd.wap.loc+xml",                /* 0x41 */
+        "application/vnd.syncml.dm+wbxml",            /* 0x42 */
+        "application/vnd.syncml.dm+xml",              /* 0x43 */
+        "application/vnd.syncml.notification",        /* 0x44 */
+        "application/vnd.wap.xhtml+xml",              /* 0x45 */
+        "application/vnd.wv.csp.cir",                 /* 0x46 */
+        "application/vnd.oma.dd+xml",                 /* 0x47 */
+        "application/vnd.oma.drm.message",            /* 0x48 */
+        "application/vnd.oma.drm.content",            /* 0x49 */
+        "application/vnd.oma.drm.rights+xml",         /* 0x4A */
+        "application/vnd.oma.drm.rights+wbxml",       /* 0x4B */
+        "application/vnd.wv.csp+xml",                 /* 0x4C */
+        "application/vnd.wv.csp+wbxml",               /* 0x4D */
+        "application/vnd.syncml.ds.notification",     /* 0x4E */
+        "audio/*",                                    /* 0x4F */
+        "video/*",                                    /* 0x50 */
+        "application/vnd.oma.dd2+xml",                /* 0x51 */
+        "application/mikey"                           /* 0x52 */
+    };
+}
diff --git a/src/android/support/v7/mms/pdu/PduHeaders.java b/src/android/support/v7/mms/pdu/PduHeaders.java
new file mode 100644
index 0000000..bea31bf
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/PduHeaders.java
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class PduHeaders {
+    /**
+     * All pdu header fields.
+     */
+    public static final int BCC                             = 0x81;
+    public static final int CC                              = 0x82;
+    public static final int CONTENT_LOCATION                = 0x83;
+    public static final int CONTENT_TYPE                    = 0x84;
+    public static final int DATE                            = 0x85;
+    public static final int DELIVERY_REPORT                 = 0x86;
+    public static final int DELIVERY_TIME                   = 0x87;
+    public static final int EXPIRY                          = 0x88;
+    public static final int FROM                            = 0x89;
+    public static final int MESSAGE_CLASS                   = 0x8A;
+    public static final int MESSAGE_ID                      = 0x8B;
+    public static final int MESSAGE_TYPE                    = 0x8C;
+    public static final int MMS_VERSION                     = 0x8D;
+    public static final int MESSAGE_SIZE                    = 0x8E;
+    public static final int PRIORITY                        = 0x8F;
+
+    public static final int READ_REPLY                      = 0x90;
+    public static final int READ_REPORT                     = 0x90;
+    public static final int REPORT_ALLOWED                  = 0x91;
+    public static final int RESPONSE_STATUS                 = 0x92;
+    public static final int RESPONSE_TEXT                   = 0x93;
+    public static final int SENDER_VISIBILITY               = 0x94;
+    public static final int STATUS                          = 0x95;
+    public static final int SUBJECT                         = 0x96;
+    public static final int TO                              = 0x97;
+    public static final int TRANSACTION_ID                  = 0x98;
+    public static final int RETRIEVE_STATUS                 = 0x99;
+    public static final int RETRIEVE_TEXT                   = 0x9A;
+    public static final int READ_STATUS                     = 0x9B;
+    public static final int REPLY_CHARGING                  = 0x9C;
+    public static final int REPLY_CHARGING_DEADLINE         = 0x9D;
+    public static final int REPLY_CHARGING_ID               = 0x9E;
+    public static final int REPLY_CHARGING_SIZE             = 0x9F;
+
+    public static final int PREVIOUSLY_SENT_BY              = 0xA0;
+    public static final int PREVIOUSLY_SENT_DATE            = 0xA1;
+    public static final int STORE                           = 0xA2;
+    public static final int MM_STATE                        = 0xA3;
+    public static final int MM_FLAGS                        = 0xA4;
+    public static final int STORE_STATUS                    = 0xA5;
+    public static final int STORE_STATUS_TEXT               = 0xA6;
+    public static final int STORED                          = 0xA7;
+    public static final int ATTRIBUTES                      = 0xA8;
+    public static final int TOTALS                          = 0xA9;
+    public static final int MBOX_TOTALS                     = 0xAA;
+    public static final int QUOTAS                          = 0xAB;
+    public static final int MBOX_QUOTAS                     = 0xAC;
+    public static final int MESSAGE_COUNT                   = 0xAD;
+    public static final int CONTENT                         = 0xAE;
+    public static final int START                           = 0xAF;
+
+    public static final int ADDITIONAL_HEADERS              = 0xB0;
+    public static final int DISTRIBUTION_INDICATOR          = 0xB1;
+    public static final int ELEMENT_DESCRIPTOR              = 0xB2;
+    public static final int LIMIT                           = 0xB3;
+    public static final int RECOMMENDED_RETRIEVAL_MODE      = 0xB4;
+    public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
+    public static final int STATUS_TEXT                     = 0xB6;
+    public static final int APPLIC_ID                       = 0xB7;
+    public static final int REPLY_APPLIC_ID                 = 0xB8;
+    public static final int AUX_APPLIC_ID                   = 0xB9;
+    public static final int CONTENT_CLASS                   = 0xBA;
+    public static final int DRM_CONTENT                     = 0xBB;
+    public static final int ADAPTATION_ALLOWED              = 0xBC;
+    public static final int REPLACE_ID                      = 0xBD;
+    public static final int CANCEL_ID                       = 0xBE;
+    public static final int CANCEL_STATUS                   = 0xBF;
+
+    /**
+     * X-Mms-Message-Type field types.
+     */
+    public static final int MESSAGE_TYPE_SEND_REQ           = 0x80;
+    public static final int MESSAGE_TYPE_SEND_CONF          = 0x81;
+    public static final int MESSAGE_TYPE_NOTIFICATION_IND   = 0x82;
+    public static final int MESSAGE_TYPE_NOTIFYRESP_IND     = 0x83;
+    public static final int MESSAGE_TYPE_RETRIEVE_CONF      = 0x84;
+    public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND    = 0x85;
+    public static final int MESSAGE_TYPE_DELIVERY_IND       = 0x86;
+    public static final int MESSAGE_TYPE_READ_REC_IND       = 0x87;
+    public static final int MESSAGE_TYPE_READ_ORIG_IND      = 0x88;
+    public static final int MESSAGE_TYPE_FORWARD_REQ        = 0x89;
+    public static final int MESSAGE_TYPE_FORWARD_CONF       = 0x8A;
+    public static final int MESSAGE_TYPE_MBOX_STORE_REQ     = 0x8B;
+    public static final int MESSAGE_TYPE_MBOX_STORE_CONF    = 0x8C;
+    public static final int MESSAGE_TYPE_MBOX_VIEW_REQ      = 0x8D;
+    public static final int MESSAGE_TYPE_MBOX_VIEW_CONF     = 0x8E;
+    public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ    = 0x8F;
+    public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF   = 0x90;
+    public static final int MESSAGE_TYPE_MBOX_DELETE_REQ    = 0x91;
+    public static final int MESSAGE_TYPE_MBOX_DELETE_CONF   = 0x92;
+    public static final int MESSAGE_TYPE_MBOX_DESCR         = 0x93;
+    public static final int MESSAGE_TYPE_DELETE_REQ         = 0x94;
+    public static final int MESSAGE_TYPE_DELETE_CONF        = 0x95;
+    public static final int MESSAGE_TYPE_CANCEL_REQ         = 0x96;
+    public static final int MESSAGE_TYPE_CANCEL_CONF        = 0x97;
+
+    /**
+     *  X-Mms-Delivery-Report |
+     *  X-Mms-Read-Report |
+     *  X-Mms-Report-Allowed |
+     *  X-Mms-Sender-Visibility |
+     *  X-Mms-Store |
+     *  X-Mms-Stored |
+     *  X-Mms-Totals |
+     *  X-Mms-Quotas |
+     *  X-Mms-Distribution-Indicator |
+     *  X-Mms-DRM-Content |
+     *  X-Mms-Adaptation-Allowed |
+     *  field types.
+     */
+    public static final int VALUE_YES                       = 0x80;
+    public static final int VALUE_NO                        = 0x81;
+
+    /**
+     *  Delivery-Time |
+     *  Expiry and Reply-Charging-Deadline |
+     *  field type components.
+     */
+    public static final int VALUE_ABSOLUTE_TOKEN            = 0x80;
+    public static final int VALUE_RELATIVE_TOKEN            = 0x81;
+
+    /**
+     * X-Mms-MMS-Version field types.
+     */
+    public static final int MMS_VERSION_1_3                 = ((1 << 4) | 3);
+    public static final int MMS_VERSION_1_2                 = ((1 << 4) | 2);
+    public static final int MMS_VERSION_1_1                 = ((1 << 4) | 1);
+    public static final int MMS_VERSION_1_0                 = ((1 << 4) | 0);
+
+    // Current version is 1.2.
+    public static final int CURRENT_MMS_VERSION             = MMS_VERSION_1_2;
+
+    /**
+     *  From field type components.
+     */
+    public static final int FROM_ADDRESS_PRESENT_TOKEN      = 0x80;
+    public static final int FROM_INSERT_ADDRESS_TOKEN       = 0x81;
+
+    public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
+    public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
+
+    /**
+     *  X-Mms-Status Field.
+     */
+    public static final int STATUS_EXPIRED                  = 0x80;
+    public static final int STATUS_RETRIEVED                = 0x81;
+    public static final int STATUS_REJECTED                 = 0x82;
+    public static final int STATUS_DEFERRED                 = 0x83;
+    public static final int STATUS_UNRECOGNIZED             = 0x84;
+    public static final int STATUS_INDETERMINATE            = 0x85;
+    public static final int STATUS_FORWARDED                = 0x86;
+    public static final int STATUS_UNREACHABLE              = 0x87;
+
+    /**
+     *  MM-Flags field type components.
+     */
+    public static final int MM_FLAGS_ADD_TOKEN              = 0x80;
+    public static final int MM_FLAGS_REMOVE_TOKEN           = 0x81;
+    public static final int MM_FLAGS_FILTER_TOKEN           = 0x82;
+
+    /**
+     *  X-Mms-Message-Class field types.
+     */
+    public static final int MESSAGE_CLASS_PERSONAL          = 0x80;
+    public static final int MESSAGE_CLASS_ADVERTISEMENT     = 0x81;
+    public static final int MESSAGE_CLASS_INFORMATIONAL     = 0x82;
+    public static final int MESSAGE_CLASS_AUTO              = 0x83;
+
+    public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
+    public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
+    public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
+    public static final String MESSAGE_CLASS_AUTO_STR = "auto";
+
+    /**
+     *  X-Mms-Priority field types.
+     */
+    public static final int PRIORITY_LOW                    = 0x80;
+    public static final int PRIORITY_NORMAL                 = 0x81;
+    public static final int PRIORITY_HIGH                   = 0x82;
+
+    /**
+     *  X-Mms-Response-Status field types.
+     */
+    public static final int RESPONSE_STATUS_OK                   = 0x80;
+    public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED    = 0x81;
+    public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
+
+    public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT     = 0x83;
+    public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
+
+    public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND    = 0x85;
+    public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM      = 0x86;
+    public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
+    public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE  = 0x88;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE    = 0xC0;
+
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND         = 0xC2;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM           = 0xC3;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS           = 0xC4;
+
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE                             = 0xE0;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED                      = 0xE1;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT              = 0xE2;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED          = 0xE3;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND                   = 0xE4;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED                = 0xE5;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET  = 0xE6;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED = 0xE6;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED    = 0xE8;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED        = 0xE9;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED        = 0xEA;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID                     = 0xEB;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_END                                 = 0xFF;
+
+    /**
+     *  X-Mms-Retrieve-Status field types.
+     */
+    public static final int RETRIEVE_STATUS_OK                                  = 0x80;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE             = 0xC0;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND   = 0xC1;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM     = 0xC2;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE             = 0xE0;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED      = 0xE1;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND   = 0xE2;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
+    public static final int RETRIEVE_STATUS_ERROR_END                           = 0xFF;
+
+    /**
+     *  X-Mms-Sender-Visibility field types.
+     */
+    public static final int SENDER_VISIBILITY_HIDE          = 0x80;
+    public static final int SENDER_VISIBILITY_SHOW          = 0x81;
+
+    /**
+     *  X-Mms-Read-Status field types.
+     */
+    public static final int READ_STATUS_READ                        = 0x80;
+    public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
+
+    /**
+     *  X-Mms-Cancel-Status field types.
+     */
+    public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
+    public static final int CANCEL_STATUS_REQUEST_CORRUPTED             = 0x81;
+
+    /**
+     *  X-Mms-Reply-Charging field types.
+     */
+    public static final int REPLY_CHARGING_REQUESTED           = 0x80;
+    public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
+    public static final int REPLY_CHARGING_ACCEPTED            = 0x82;
+    public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY  = 0x83;
+
+    /**
+     *  X-Mms-MM-State field types.
+     */
+    public static final int MM_STATE_DRAFT                  = 0x80;
+    public static final int MM_STATE_SENT                   = 0x81;
+    public static final int MM_STATE_NEW                    = 0x82;
+    public static final int MM_STATE_RETRIEVED              = 0x83;
+    public static final int MM_STATE_FORWARDED              = 0x84;
+
+    /**
+     * X-Mms-Recommended-Retrieval-Mode field types.
+     */
+    public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
+
+    /**
+     *  X-Mms-Content-Class field types.
+     */
+    public static final int CONTENT_CLASS_TEXT              = 0x80;
+    public static final int CONTENT_CLASS_IMAGE_BASIC       = 0x81;
+    public static final int CONTENT_CLASS_IMAGE_RICH        = 0x82;
+    public static final int CONTENT_CLASS_VIDEO_BASIC       = 0x83;
+    public static final int CONTENT_CLASS_VIDEO_RICH        = 0x84;
+    public static final int CONTENT_CLASS_MEGAPIXEL         = 0x85;
+    public static final int CONTENT_CLASS_CONTENT_BASIC     = 0x86;
+    public static final int CONTENT_CLASS_CONTENT_RICH      = 0x87;
+
+    /**
+     *  X-Mms-Store-Status field types.
+     */
+    public static final int STORE_STATUS_SUCCESS                                = 0x80;
+    public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE                = 0xC0;
+    public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM        = 0xC1;
+    public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE                = 0xE0;
+    public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED         = 0xE1;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND      = 0xE3;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL             = 0xE4;
+    public static final int STORE_STATUS_ERROR_END                              = 0xFF;
+
+    /**
+     * The map contains the value of all headers.
+     */
+    private HashMap<Integer, Object> mHeaderMap = null;
+
+    /**
+     * Constructor of PduHeaders.
+     */
+    public PduHeaders() {
+        mHeaderMap = new HashMap<Integer, Object>();
+    }
+
+    /**
+     * Get octet value by header field.
+     *
+     * @param field the field
+     * @return the octet value of the pdu header
+     *          with specified header field. Return 0 if
+     *          the value is not set.
+     */
+    protected int getOctet(int field) {
+        Integer octet = (Integer) mHeaderMap.get(field);
+        if (null == octet) {
+            return 0;
+        }
+
+        return octet;
+    }
+
+    /**
+     * Set octet value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    protected void setOctet(int value, int field)
+            throws InvalidHeaderValueException{
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        switch (field) {
+            case REPORT_ALLOWED:
+            case ADAPTATION_ALLOWED:
+            case DELIVERY_REPORT:
+            case DRM_CONTENT:
+            case DISTRIBUTION_INDICATOR:
+            case QUOTAS:
+            case READ_REPORT:
+            case STORE:
+            case STORED:
+            case TOTALS:
+            case SENDER_VISIBILITY:
+                if ((VALUE_YES != value) && (VALUE_NO != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case READ_STATUS:
+                if ((READ_STATUS_READ != value) &&
+                        (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case CANCEL_STATUS:
+                if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
+                        (CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case PRIORITY:
+                if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case STATUS:
+                if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case REPLY_CHARGING:
+                if ((value < REPLY_CHARGING_REQUESTED)
+                        || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case MM_STATE:
+                if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case RECOMMENDED_RETRIEVAL_MODE:
+                if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case CONTENT_CLASS:
+                if ((value < CONTENT_CLASS_TEXT)
+                        || (value > CONTENT_CLASS_CONTENT_RICH)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case RETRIEVE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
+                if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
+                        (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
+                        (value <= RETRIEVE_STATUS_ERROR_END)) {
+                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
+                } else if ((value < RETRIEVE_STATUS_OK) ||
+                        ((value > RETRIEVE_STATUS_OK) &&
+                                (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                                (value > RETRIEVE_STATUS_ERROR_END)) {
+                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case STORE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
+                if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
+                        (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
+                        (value <= STORE_STATUS_ERROR_END)) {
+                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
+                } else if ((value < STORE_STATUS_SUCCESS) ||
+                        ((value > STORE_STATUS_SUCCESS) &&
+                                (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                                (value > STORE_STATUS_ERROR_END)) {
+                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case RESPONSE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
+                if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
+                        (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
+                        (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
+                        (value < RESPONSE_STATUS_OK) ||
+                        ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
+                                (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                                (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
+                    value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case MMS_VERSION:
+                if ((value < MMS_VERSION_1_0)|| (value > MMS_VERSION_1_3)) {
+                    value = CURRENT_MMS_VERSION; // Current version is the default value.
+                }
+                break;
+            case MESSAGE_TYPE:
+                if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            default:
+                // This header value should not be Octect.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Get TextString value by header field.
+     *
+     * @param field the field
+     * @return the TextString value of the pdu header
+     *          with specified header field
+     */
+    protected byte[] getTextString(int field) {
+        return (byte[]) mHeaderMap.get(field);
+    }
+
+    /**
+     * Set TextString value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the TextString value of the pdu header
+     *          with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setTextString(byte[] value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case TRANSACTION_ID:
+            case REPLY_CHARGING_ID:
+            case AUX_APPLIC_ID:
+            case APPLIC_ID:
+            case REPLY_APPLIC_ID:
+            case MESSAGE_ID:
+            case REPLACE_ID:
+            case CANCEL_ID:
+            case CONTENT_LOCATION:
+            case MESSAGE_CLASS:
+            case CONTENT_TYPE:
+                break;
+            default:
+                // This header value should not be Text-String.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Get EncodedStringValue value by header field.
+     *
+     * @param field the field
+     * @return the EncodedStringValue value of the pdu header
+     *          with specified header field
+     */
+    protected EncodedStringValue getEncodedStringValue(int field) {
+        return (EncodedStringValue) mHeaderMap.get(field);
+    }
+
+    /**
+     * Get TO, CC or BCC header value.
+     *
+     * @param field the field
+     * @return the EncodeStringValue array of the pdu header
+     *          with specified header field
+     */
+    protected EncodedStringValue[] getEncodedStringValues(int field) {
+        ArrayList<EncodedStringValue> list =
+                (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
+        if (null == list) {
+            return null;
+        }
+        EncodedStringValue[] values = new EncodedStringValue[list.size()];
+        return list.toArray(values);
+    }
+
+    /**
+     * Set EncodedStringValue value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the EncodedStringValue value of the pdu header
+     *          with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setEncodedStringValue(EncodedStringValue value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case SUBJECT:
+            case RECOMMENDED_RETRIEVAL_MODE_TEXT:
+            case RETRIEVE_TEXT:
+            case STATUS_TEXT:
+            case STORE_STATUS_TEXT:
+            case RESPONSE_TEXT:
+            case FROM:
+            case PREVIOUSLY_SENT_BY:
+            case MM_FLAGS:
+                break;
+            default:
+                // This header value should not be Encoded-String-Value.
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Set TO, CC or BCC header value.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the EncodedStringValue value array of the pdu header
+     *          with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case BCC:
+            case CC:
+            case TO:
+                break;
+            default:
+                // This header value should not be Encoded-String-Value.
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
+        for (int i = 0; i < value.length; i++) {
+            list.add(value[i]);
+        }
+        mHeaderMap.put(field, list);
+    }
+
+    /**
+     * Append one EncodedStringValue to another.
+     *
+     * @param value the EncodedStringValue to append
+     * @param field the field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void appendEncodedStringValue(EncodedStringValue value,
+                                    int field) {
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case BCC:
+            case CC:
+            case TO:
+                break;
+            default:
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        ArrayList<EncodedStringValue> list =
+            (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
+        if (null == list) {
+            list  = new ArrayList<EncodedStringValue>();
+        }
+        list.add(value);
+        mHeaderMap.put(field, list);
+    }
+
+    /**
+     * Get LongInteger value by header field.
+     *
+     * @param field the field
+     * @return the LongInteger value of the pdu header
+     *          with specified header field. if return -1, the
+     *          field is not existed in pdu header.
+     */
+    protected long getLongInteger(int field) {
+        Long longInteger = (Long) mHeaderMap.get(field);
+        if (null == longInteger) {
+            return -1;
+        }
+
+        return longInteger.longValue();
+    }
+
+    /**
+     * Set LongInteger value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     */
+    protected void setLongInteger(long value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        switch (field) {
+            case DATE:
+            case REPLY_CHARGING_SIZE:
+            case MESSAGE_SIZE:
+            case MESSAGE_COUNT:
+            case START:
+            case LIMIT:
+            case DELIVERY_TIME:
+            case EXPIRY:
+            case REPLY_CHARGING_DEADLINE:
+            case PREVIOUSLY_SENT_DATE:
+                break;
+            default:
+                // This header value should not be LongInteger.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/PduParser.java b/src/android/support/v7/mms/pdu/PduParser.java
new file mode 100755
index 0000000..206aa12
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/PduParser.java
@@ -0,0 +1,2008 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class PduParser {
+    /**
+     *  The next are WAP values defined in WSP specification.
+     */
+    private static final int QUOTE = 127;
+    private static final int LENGTH_QUOTE = 31;
+    private static final int TEXT_MIN = 32;
+    private static final int TEXT_MAX = 127;
+    private static final int SHORT_INTEGER_MAX = 127;
+    private static final int SHORT_LENGTH_MAX = 30;
+    private static final int LONG_INTEGER_LENGTH_MAX = 8;
+    private static final int QUOTED_STRING_FLAG = 34;
+    private static final int END_STRING_FLAG = 0x00;
+    //The next two are used by the interface "parseWapString" to
+    //distinguish Text-String and Quoted-String.
+    private static final int TYPE_TEXT_STRING = 0;
+    private static final int TYPE_QUOTED_STRING = 1;
+    private static final int TYPE_TOKEN_STRING = 2;
+
+    /**
+     * Specify the part position.
+     */
+    private static final int THE_FIRST_PART = 0;
+    private static final int THE_LAST_PART = 1;
+
+    /**
+     * The pdu data.
+     */
+    private ByteArrayInputStream mPduDataStream = null;
+
+    /**
+     * Store pdu headers
+     */
+    private PduHeaders mHeaders = null;
+
+    /**
+     * Store pdu parts.
+     */
+    private PduBody mBody = null;
+
+    /**
+     * Store the "type" parameter in "Content-Type" header field.
+     */
+    private static byte[] mTypeParam = null;
+
+    /**
+     * Store the "start" parameter in "Content-Type" header field.
+     */
+    private static byte[] mStartParam = null;
+
+    /**
+     * The log tag.
+     */
+    private static final String LOG_TAG = "PduParser";
+    private static final boolean DEBUG = false;
+    private static final boolean LOCAL_LOGV = false;
+
+    /**
+     * Whether to parse content-disposition part header
+     */
+    private final boolean mParseContentDisposition;
+
+    /**
+     * Constructor.
+     *
+     * @param pduDataStream pdu data to be parsed
+     * @param parseContentDisposition whether to parse the Content-Disposition part header
+     */
+    public PduParser(byte[] pduDataStream, boolean parseContentDisposition) {
+        mPduDataStream = new ByteArrayInputStream(pduDataStream);
+        mParseContentDisposition = parseContentDisposition;
+    }
+
+    /**
+     * Parse the pdu.
+     *
+     * @return the pdu structure if parsing successfully.
+     *         null if parsing error happened or mandatory fields are not set.
+     */
+    public GenericPdu parse(){
+        if (mPduDataStream == null) {
+            return null;
+        }
+
+        /* parse headers */
+        mHeaders = parseHeaders(mPduDataStream);
+        if (null == mHeaders) {
+            // Parse headers failed.
+            return null;
+        }
+
+        /* get the message type */
+        int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
+
+        /* check mandatory header fields */
+        if (false == checkMandatoryHeader(mHeaders)) {
+            log("check mandatory headers failed!");
+            return null;
+        }
+
+        if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
+                (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
+            /* need to parse the parts */
+            mBody = parseParts(mPduDataStream);
+            if (null == mBody) {
+                // Parse parts failed.
+                return null;
+            }
+        }
+
+        switch (messageType) {
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_REQ");
+                }
+                SendReq sendReq = new SendReq(mHeaders, mBody);
+                return sendReq;
+            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_CONF");
+                }
+                SendConf sendConf = new SendConf(mHeaders);
+                return sendConf;
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFICATION_IND");
+                }
+                NotificationInd notificationInd =
+                    new NotificationInd(mHeaders);
+                return notificationInd;
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFYRESP_IND");
+                }
+                NotifyRespInd notifyRespInd =
+                    new NotifyRespInd(mHeaders);
+                return notifyRespInd;
+            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF");
+                }
+                RetrieveConf retrieveConf =
+                    new RetrieveConf(mHeaders, mBody);
+
+                byte[] contentType = retrieveConf.getContentType();
+                if (null == contentType) {
+                    return null;
+                }
+                String ctTypeStr = new String(contentType);
+                if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
+                        || ctTypeStr.equals(ContentType.MULTIPART_RELATED)
+                        || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
+                    // The MMS content type must be "application/vnd.wap.multipart.mixed"
+                    // or "application/vnd.wap.multipart.related"
+                    // or "application/vnd.wap.multipart.alternative"
+                    return retrieveConf;
+                } else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
+                    // "application/vnd.wap.multipart.alternative"
+                    // should take only the first part.
+                    PduPart firstPart = mBody.getPart(0);
+                    mBody.removeAll();
+                    mBody.addPart(0, firstPart);
+                    return retrieveConf;
+                }
+                return null;
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_DELIVERY_IND");
+                }
+                DeliveryInd deliveryInd =
+                    new DeliveryInd(mHeaders);
+                return deliveryInd;
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_ACKNOWLEDGE_IND");
+                }
+                AcknowledgeInd acknowledgeInd =
+                    new AcknowledgeInd(mHeaders);
+                return acknowledgeInd;
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_ORIG_IND");
+                }
+                ReadOrigInd readOrigInd =
+                    new ReadOrigInd(mHeaders);
+                return readOrigInd;
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_REC_IND");
+                }
+                ReadRecInd readRecInd =
+                    new ReadRecInd(mHeaders);
+                return readRecInd;
+            default:
+                log("Parser doesn't support this message type in this version!");
+            return null;
+        }
+    }
+
+    /**
+     * Parse pdu headers.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return headers in PduHeaders structure, null when parse fail
+     */
+    protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream){
+        if (pduDataStream == null) {
+            return null;
+        }
+        boolean keepParsing = true;
+        PduHeaders headers = new PduHeaders();
+
+        while (keepParsing && (pduDataStream.available() > 0)) {
+            pduDataStream.mark(1);
+            int headerField = extractByteValue(pduDataStream);
+            /* parse custom text header */
+            if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
+                pduDataStream.reset();
+                byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
+                }
+                /* we should ignore it at the moment */
+                continue;
+            }
+            switch (headerField) {
+                case PduHeaders.MESSAGE_TYPE:
+                {
+                    int messageType = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: messageType: " + messageType);
+                    }
+                    switch (messageType) {
+                        // We don't support these kind of messages now.
+                        case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
+                        case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
+                        case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
+                        case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
+                            return null;
+                    }
+                    try {
+                        headers.setOctet(messageType, headerField);
+                    } catch(InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + messageType +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+                /* Octect value */
+                case PduHeaders.REPORT_ALLOWED:
+                case PduHeaders.ADAPTATION_ALLOWED:
+                case PduHeaders.DELIVERY_REPORT:
+                case PduHeaders.DRM_CONTENT:
+                case PduHeaders.DISTRIBUTION_INDICATOR:
+                case PduHeaders.QUOTAS:
+                case PduHeaders.READ_REPORT:
+                case PduHeaders.STORE:
+                case PduHeaders.STORED:
+                case PduHeaders.TOTALS:
+                case PduHeaders.SENDER_VISIBILITY:
+                case PduHeaders.READ_STATUS:
+                case PduHeaders.CANCEL_STATUS:
+                case PduHeaders.PRIORITY:
+                case PduHeaders.STATUS:
+                case PduHeaders.REPLY_CHARGING:
+                case PduHeaders.MM_STATE:
+                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE:
+                case PduHeaders.CONTENT_CLASS:
+                case PduHeaders.RETRIEVE_STATUS:
+                case PduHeaders.STORE_STATUS:
+                    /**
+                     * The following field has a different value when
+                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
+                     * For now we ignore this fact, since we do not support these PDUs
+                     */
+                case PduHeaders.RESPONSE_STATUS:
+                {
+                    int value = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: byte: " + headerField + " value: " +
+                                value);
+                    }
+
+                    try {
+                        headers.setOctet(value, headerField);
+                    } catch(InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + value +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Long-Integer */
+                case PduHeaders.DATE:
+                case PduHeaders.REPLY_CHARGING_SIZE:
+                case PduHeaders.MESSAGE_SIZE:
+                {
+                    try {
+                        long value = parseLongInteger(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: longint: " + headerField + " value: " +
+                                    value);
+                        }
+                        headers.setLongInteger(value, headerField);
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Integer-Value */
+                case PduHeaders.MESSAGE_COUNT:
+                case PduHeaders.START:
+                case PduHeaders.LIMIT:
+                {
+                    try {
+                        long value = parseIntegerValue(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: int: " + headerField + " value: " +
+                                    value);
+                        }
+                        headers.setLongInteger(value, headerField);
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Text-String */
+                case PduHeaders.TRANSACTION_ID:
+                case PduHeaders.REPLY_CHARGING_ID:
+                case PduHeaders.AUX_APPLIC_ID:
+                case PduHeaders.APPLIC_ID:
+                case PduHeaders.REPLY_APPLIC_ID:
+                    /**
+                     * The next three header fields are email addresses
+                     * as defined in RFC2822,
+                     * not including the characters "<" and ">"
+                     */
+                case PduHeaders.MESSAGE_ID:
+                case PduHeaders.REPLACE_ID:
+                case PduHeaders.CANCEL_ID:
+                    /**
+                     * The following field has a different value when
+                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
+                     * For now we ignore this fact, since we do not support these PDUs
+                     */
+                case PduHeaders.CONTENT_LOCATION:
+                {
+                    byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if (null != value) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: string: " + headerField + " value: " +
+                                        new String(value));
+                            }
+                            headers.setTextString(value, headerField);
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch(RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Encoded-string-value */
+                case PduHeaders.SUBJECT:
+                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT:
+                case PduHeaders.RETRIEVE_TEXT:
+                case PduHeaders.STATUS_TEXT:
+                case PduHeaders.STORE_STATUS_TEXT:
+                    /* the next one is not support
+                     * M-Mbox-Delete.conf and M-Delete.conf now */
+                case PduHeaders.RESPONSE_TEXT:
+                {
+                    EncodedStringValue value =
+                        parseEncodedStringValue(pduDataStream);
+                    if (null != value) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: encoded string: " + headerField
+                                        + " value: " + value.getString());
+                            }
+                            headers.setEncodedStringValue(value, headerField);
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Addressing model */
+                case PduHeaders.BCC:
+                case PduHeaders.CC:
+                case PduHeaders.TO:
+                {
+                    EncodedStringValue value =
+                        parseEncodedStringValue(pduDataStream);
+                    if (null != value) {
+                        byte[] address = value.getTextString();
+                        if (null != address) {
+                            String str = new String(address);
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: (to/cc/bcc) address: " + headerField
+                                        + " value: " + str);
+                            }
+                            int endIndex = str.indexOf("/");
+                            if (endIndex > 0) {
+                                str = str.substring(0, endIndex);
+                            }
+                            try {
+                                value.setTextString(str.getBytes());
+                            } catch(NullPointerException e) {
+                                log("null pointer error!");
+                                return null;
+                            }
+                        }
+
+                        try {
+                            headers.appendEncodedStringValue(value, headerField);
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch(RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Value-length
+                 * (Absolute-token Date-value | Relative-token Delta-seconds-value) */
+                case PduHeaders.DELIVERY_TIME:
+                case PduHeaders.EXPIRY:
+                case PduHeaders.REPLY_CHARGING_DEADLINE:
+                {
+                    /* parse Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Absolute-token or Relative-token */
+                    int token = extractByteValue(pduDataStream);
+
+                    /* Date-value or Delta-seconds-value */
+                    long timeValue;
+                    try {
+                        timeValue = parseLongInteger(pduDataStream);
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    if (PduHeaders.VALUE_RELATIVE_TOKEN == token) {
+                        /* need to convert the Delta-seconds-value
+                         * into Date-value */
+                        timeValue = System.currentTimeMillis()/1000 + timeValue;
+                    }
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: time value: " + headerField
+                                    + " value: " + timeValue);
+                        }
+                        headers.setLongInteger(timeValue, headerField);
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.FROM: {
+                    /* From-value =
+                     * Value-length
+                     * (Address-present-token Encoded-string-value | Insert-address-token)
+                     */
+                    EncodedStringValue from = null;
+                    parseValueLength(pduDataStream); /* parse value-length */
+
+                    /* Address-present-token or Insert-address-token */
+                    int fromToken = extractByteValue(pduDataStream);
+
+                    /* Address-present-token or Insert-address-token */
+                    if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) {
+                        /* Encoded-string-value */
+                        from = parseEncodedStringValue(pduDataStream);
+                        if (null != from) {
+                            byte[] address = from.getTextString();
+                            if (null != address) {
+                                String str = new String(address);
+                                int endIndex = str.indexOf("/");
+                                if (endIndex > 0) {
+                                    str = str.substring(0, endIndex);
+                                }
+                                try {
+                                    from.setTextString(str.getBytes());
+                                } catch(NullPointerException e) {
+                                    log("null pointer error!");
+                                    return null;
+                                }
+                            }
+                        }
+                    } else {
+                        try {
+                            from = new EncodedStringValue(
+                                    PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes());
+                        } catch(NullPointerException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: from address: " + headerField
+                                    + " value: " + from.getString());
+                        }
+                        headers.setEncodedStringValue(from, PduHeaders.FROM);
+                    } catch(NullPointerException e) {
+                        log("null pointer error!");
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Encoded-String-Value header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.MESSAGE_CLASS: {
+                    /* Message-class-value = Class-identifier | Token-text */
+                    pduDataStream.mark(1);
+                    int messageClass = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: MESSAGE_CLASS: " + headerField
+                                + " value: " + messageClass);
+                    }
+
+                    if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) {
+                        /* Class-identifier */
+                        try {
+                            if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            }
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch(RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    } else {
+                        /* Token-text */
+                        pduDataStream.reset();
+                        byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if (null != messageClassString) {
+                            try {
+                                headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS);
+                            } catch(NullPointerException e) {
+                                log("null pointer error!");
+                            } catch(RuntimeException e) {
+                                log(headerField + "is not Text-String header field!");
+                                return null;
+                            }
+                        }
+                    }
+                    break;
+                }
+
+                case PduHeaders.MMS_VERSION: {
+                    int version = parseShortInteger(pduDataStream);
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: MMS_VERSION: " + headerField
+                                    + " value: " + version);
+                        }
+                        headers.setOctet(version, PduHeaders.MMS_VERSION);
+                    } catch(InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + version +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.PREVIOUSLY_SENT_BY: {
+                    /* Previously-sent-by-value =
+                     * Value-length Forwarded-count-value Encoded-string-value */
+                    /* parse value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* parse Forwarded-count-value */
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch(RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* parse Encoded-string-value */
+                    EncodedStringValue previouslySentBy =
+                        parseEncodedStringValue(pduDataStream);
+                    if (null != previouslySentBy) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_BY: " + headerField
+                                        + " value: " + previouslySentBy.getString());
+                            }
+                            headers.setEncodedStringValue(previouslySentBy,
+                                    PduHeaders.PREVIOUSLY_SENT_BY);
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch(RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                case PduHeaders.PREVIOUSLY_SENT_DATE: {
+                    /* Previously-sent-date-value =
+                     * Value-length Forwarded-count-value Date-value */
+                    /* parse value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* parse Forwarded-count-value */
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch(RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* Date-value */
+                    try {
+                        long perviouslySentDate = parseLongInteger(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_DATE: " + headerField
+                                    + " value: " + perviouslySentDate);
+                        }
+                        headers.setLongInteger(perviouslySentDate,
+                                PduHeaders.PREVIOUSLY_SENT_DATE);
+                    } catch(RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.MM_FLAGS: {
+                    /* MM-flags-value =
+                     * Value-length
+                     * ( Add-token | Remove-token | Filter-token )
+                     * Encoded-string-value
+                     */
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: MM_FLAGS: " + headerField
+                                + " NOT REALLY SUPPORTED");
+                    }
+
+                    /* parse Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Add-token | Remove-token | Filter-token */
+                    extractByteValue(pduDataStream);
+
+                    /* Encoded-string-value */
+                    parseEncodedStringValue(pduDataStream);
+
+                    /* not store this header filed in "headers",
+                     * because now PduHeaders doesn't support it */
+                    break;
+                }
+
+                /* Value-length
+                 * (Message-total-token | Size-total-token) Integer-Value */
+                case PduHeaders.MBOX_TOTALS:
+                case PduHeaders.MBOX_QUOTAS:
+                {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: MBOX_TOTALS: " + headerField);
+                    }
+                    /* Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Message-total-token | Size-total-token */
+                    extractByteValue(pduDataStream);
+
+                    /*Integer-Value*/
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch(RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* not store these headers filed in "headers",
+                    because now PduHeaders doesn't support them */
+                    break;
+                }
+
+                case PduHeaders.ELEMENT_DESCRIPTOR: {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: ELEMENT_DESCRIPTOR: " + headerField);
+                    }
+                    parseContentType(pduDataStream, null);
+
+                    /* not store this header filed in "headers",
+                    because now PduHeaders doesn't support it */
+                    break;
+                }
+
+                case PduHeaders.CONTENT_TYPE: {
+                    HashMap<Integer, Object> map =
+                        new HashMap<Integer, Object>();
+                    byte[] contentType =
+                        parseContentType(pduDataStream, map);
+
+                    if (null != contentType) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: CONTENT_TYPE: " + headerField +
+                                        Arrays.toString(contentType));
+                            }
+                            headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
+                        } catch(NullPointerException e) {
+                            log("null pointer error!");
+                        } catch(RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    }
+
+                    /* get start parameter */
+                    mStartParam = (byte[]) map.get(PduPart.P_START);
+
+                    /* get charset parameter */
+                    mTypeParam= (byte[]) map.get(PduPart.P_TYPE);
+
+                    keepParsing = false;
+                    break;
+                }
+
+                case PduHeaders.CONTENT:
+                case PduHeaders.ADDITIONAL_HEADERS:
+                case PduHeaders.ATTRIBUTES:
+                default: {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: Unknown header: " + headerField);
+                    }
+                    log("Unknown header");
+                }
+            }
+        }
+
+        return headers;
+    }
+
+    /**
+     * Parse pdu parts.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return parts in PduBody structure
+     */
+    protected PduBody parseParts(ByteArrayInputStream pduDataStream) {
+        if (pduDataStream == null) {
+            return null;
+        }
+
+        int count = parseUnsignedInt(pduDataStream); // get the number of parts
+        PduBody body = new PduBody();
+
+        for (int i = 0 ; i < count ; i++) {
+            int headerLength = parseUnsignedInt(pduDataStream);
+            int dataLength = parseUnsignedInt(pduDataStream);
+            PduPart part = new PduPart();
+            int startPos = pduDataStream.available();
+            if (startPos <= 0) {
+                // Invalid part.
+                return null;
+            }
+
+            /* parse part's content-type */
+            HashMap<Integer, Object> map = new HashMap<Integer, Object>();
+            byte[] contentType = parseContentType(pduDataStream, map);
+            if (null != contentType) {
+                part.setContentType(contentType);
+            } else {
+                part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
+            }
+
+            /* get name parameter */
+            byte[] name = (byte[]) map.get(PduPart.P_NAME);
+            if (null != name) {
+                part.setName(name);
+            }
+
+            /* get charset parameter */
+            Integer charset = (Integer) map.get(PduPart.P_CHARSET);
+            if (null != charset) {
+                part.setCharset(charset);
+            }
+
+            /* parse part's headers */
+            int endPos = pduDataStream.available();
+            int partHeaderLen = headerLength - (startPos - endPos);
+            if (partHeaderLen > 0) {
+                if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
+                    // Parse part header faild.
+                    return null;
+                }
+            } else if (partHeaderLen < 0) {
+                // Invalid length of content-type.
+                return null;
+            }
+
+            /* FIXME: check content-id, name, filename and content location,
+             * if not set anyone of them, generate a default content-location
+             */
+            if ((null == part.getContentLocation())
+                    && (null == part.getName())
+                    && (null == part.getFilename())
+                    && (null == part.getContentId())) {
+                part.setContentLocation(Long.toOctalString(
+                        System.currentTimeMillis()).getBytes());
+            }
+
+            /* get part's data */
+            if (dataLength > 0) {
+                byte[] partData = new byte[dataLength];
+                String partContentType = new String(part.getContentType());
+                pduDataStream.read(partData, 0, dataLength);
+                if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
+                    // parse "multipart/vnd.wap.multipart.alternative".
+                    PduBody childBody = parseParts(new ByteArrayInputStream(partData));
+                    // take the first part of children.
+                    part = childBody.getPart(0);
+                } else {
+                    // Check Content-Transfer-Encoding.
+                    byte[] partDataEncoding = part.getContentTransferEncoding();
+                    if (null != partDataEncoding) {
+                        String encoding = new String(partDataEncoding);
+                        if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
+                            // Decode "base64" into "binary".
+                            partData = Base64.decodeBase64(partData);
+                        } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
+                            // Decode "quoted-printable" into "binary".
+                            partData = QuotedPrintable.decodeQuotedPrintable(partData);
+                        } else {
+                            // "binary" is the default encoding.
+                        }
+                    }
+                    if (null == partData) {
+                        log("Decode part data error!");
+                        return null;
+                    }
+                    part.setData(partData);
+                }
+            }
+
+            /* add this part to body */
+            if (THE_FIRST_PART == checkPartPosition(part)) {
+                /* this is the first part */
+                body.addPart(0, part);
+            } else {
+                /* add the part to the end */
+                body.addPart(part);
+            }
+        }
+
+        return body;
+    }
+
+    /**
+     * Log status.
+     *
+     * @param text log information
+     */
+    private static void log(String text) {
+        if (LOCAL_LOGV) {
+            Log.v(LOG_TAG, text);
+        }
+    }
+
+    /**
+     * Parse unsigned integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the integer, -1 when failed
+     */
+    protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * The maximum size of a uintvar is 32 bits.
+         * So it will be encoded in no more than 5 octets.
+         */
+        assert(null != pduDataStream);
+        int result = 0;
+        int temp = pduDataStream.read();
+        if (temp == -1) {
+            return temp;
+        }
+
+        while((temp & 0x80) != 0) {
+            result = result << 7;
+            result |= temp & 0x7F;
+            temp = pduDataStream.read();
+            if (temp == -1) {
+                return temp;
+            }
+        }
+
+        result = result << 7;
+        result |= temp & 0x7F;
+
+        return result;
+    }
+
+    /**
+     * Parse value length.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the integer
+     */
+    protected static int parseValueLength(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Value-length = Short-length | (Length-quote Length)
+         * Short-length = <Any octet 0-30>
+         * Length-quote = <Octet 31>
+         * Length = Uintvar-integer
+         * Uintvar-integer = 1*5 OCTET
+         */
+        assert(null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        int first = temp & 0xFF;
+
+        if (first <= SHORT_LENGTH_MAX) {
+            return first;
+        } else if (first == LENGTH_QUOTE) {
+            return parseUnsignedInt(pduDataStream);
+        }
+
+        throw new RuntimeException("Value length > LENGTH_QUOTE!");
+    }
+
+    /**
+     * Parse encoded string value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the EncodedStringValue
+     */
+    protected static EncodedStringValue parseEncodedStringValue(ByteArrayInputStream pduDataStream){
+        /**
+         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf
+         * Encoded-string-value = Text-string | Value-length Char-set Text-string
+         */
+        assert(null != pduDataStream);
+        pduDataStream.mark(1);
+        EncodedStringValue returnValue = null;
+        int charset = 0;
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        int first = temp & 0xFF;
+        if (first == 0) {
+            return new EncodedStringValue("");
+        }
+
+        pduDataStream.reset();
+        if (first < TEXT_MIN) {
+            parseValueLength(pduDataStream);
+
+            charset = parseShortInteger(pduDataStream); //get the "Charset"
+        }
+
+        byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+
+        try {
+            if (0 != charset) {
+                returnValue = new EncodedStringValue(charset, textString);
+            } else {
+                returnValue = new EncodedStringValue(textString);
+            }
+        } catch(Exception e) {
+            return null;
+        }
+
+        return returnValue;
+    }
+
+    /**
+     * Parse Text-String or Quoted-String.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param stringType TYPE_TEXT_STRING or TYPE_QUOTED_STRING
+     * @return the string without End-of-string in byte array
+     */
+    protected static byte[] parseWapString(ByteArrayInputStream pduDataStream,
+            int stringType) {
+        assert(null != pduDataStream);
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Text-string = [Quote] *TEXT End-of-string
+         * If the first character in the TEXT is in the range of 128-255,
+         * a Quote character must precede it.
+         * Otherwise the Quote character must be omitted.
+         * The Quote is not part of the contents.
+         * Quote = <Octet 127>
+         * End-of-string = <Octet 0>
+         *
+         * Quoted-string = <Octet 34> *TEXT End-of-string
+         *
+         * Token-text = Token End-of-string
+         */
+
+        // Mark supposed beginning of Text-string
+        // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG
+        pduDataStream.mark(1);
+
+        // Check first char
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        if ((TYPE_QUOTED_STRING == stringType) &&
+                (QUOTED_STRING_FLAG == temp)) {
+            // Mark again if QUOTED_STRING_FLAG and ignore it
+            pduDataStream.mark(1);
+        } else if ((TYPE_TEXT_STRING == stringType) &&
+                (QUOTE == temp)) {
+            // Mark again if QUOTE and ignore it
+            pduDataStream.mark(1);
+        } else {
+            // Otherwise go back to origin
+            pduDataStream.reset();
+        }
+
+        // We are now definitely at the beginning of string
+        /**
+         * Return *TOKEN or *TEXT (Text-String without QUOTE,
+         * Quoted-String without QUOTED_STRING_FLAG and without End-of-string)
+         */
+        return getWapString(pduDataStream, stringType);
+    }
+
+    /**
+     * Check TOKEN data defined in RFC2616.
+     * @param ch checking data
+     * @return true when ch is TOKEN, false when ch is not TOKEN
+     */
+    protected static boolean isTokenCharacter(int ch) {
+        /**
+         * Token      = 1*<any CHAR except CTLs or separators>
+         * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64)
+         *            | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34)
+         *            | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61)
+         *            | "{"(123) | "}"(125) | SP(32) | HT(9)
+         * CHAR       = <any US-ASCII character (octets 0 - 127)>
+         * CTL        = <any US-ASCII control character
+         *            (octets 0 - 31) and DEL (127)>
+         * SP         = <US-ASCII SP, space (32)>
+         * HT         = <US-ASCII HT, horizontal-tab (9)>
+         */
+        if((ch < 33) || (ch > 126)) {
+            return false;
+        }
+
+        switch(ch) {
+            case '"': /* '"' */
+            case '(': /* '(' */
+            case ')': /* ')' */
+            case ',': /* ',' */
+            case '/': /* '/' */
+            case ':': /* ':' */
+            case ';': /* ';' */
+            case '<': /* '<' */
+            case '=': /* '=' */
+            case '>': /* '>' */
+            case '?': /* '?' */
+            case '@': /* '@' */
+            case '[': /* '[' */
+            case '\\': /* '\' */
+            case ']': /* ']' */
+            case '{': /* '{' */
+            case '}': /* '}' */
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check TEXT data defined in RFC2616.
+     * @param ch checking data
+     * @return true when ch is TEXT, false when ch is not TEXT
+     */
+    protected static boolean isText(int ch) {
+        /**
+         * TEXT = <any OCTET except CTLs,
+         *      but including LWS>
+         * CTL  = <any US-ASCII control character
+         *      (octets 0 - 31) and DEL (127)>
+         * LWS  = [CRLF] 1*( SP | HT )
+         * CRLF = CR LF
+         * CR   = <US-ASCII CR, carriage return (13)>
+         * LF   = <US-ASCII LF, linefeed (10)>
+         */
+        if(((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) {
+            return true;
+        }
+
+        switch(ch) {
+            case '\t': /* '\t' */
+            case '\n': /* '\n' */
+            case '\r': /* '\r' */
+                return true;
+        }
+
+        return false;
+    }
+
+    protected static byte[] getWapString(ByteArrayInputStream pduDataStream,
+            int stringType) {
+        assert(null != pduDataStream);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        while((-1 != temp) && ('\0' != temp)) {
+            // check each of the character
+            if (stringType == TYPE_TOKEN_STRING) {
+                if (isTokenCharacter(temp)) {
+                    out.write(temp);
+                }
+            } else {
+                if (isText(temp)) {
+                    out.write(temp);
+                }
+            }
+
+            temp = pduDataStream.read();
+            assert(-1 != temp);
+        }
+
+        if (out.size() > 0) {
+            return out.toByteArray();
+        }
+
+        return null;
+    }
+
+    /**
+     * Extract a byte value from the input stream.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the byte
+     */
+    protected static int extractByteValue(ByteArrayInputStream pduDataStream) {
+        assert(null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        return temp & 0xFF;
+    }
+
+    /**
+     * Parse Short-Integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the byte
+     */
+    protected static int parseShortInteger(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Short-integer = OCTET
+         * Integers in range 0-127 shall be encoded as a one
+         * octet value with the most significant bit set to one (1xxx xxxx)
+         * and with the value in the remaining least significant bits.
+         */
+        assert(null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        return temp & 0x7F;
+    }
+
+    /**
+     * Parse Long-Integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return long integer
+     */
+    protected static long parseLongInteger(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Long-integer = Short-length Multi-octet-integer
+         * The Short-length indicates the length of the Multi-octet-integer
+         * Multi-octet-integer = 1*30 OCTET
+         * The content octets shall be an unsigned integer value
+         * with the most significant octet encoded first (big-endian representation).
+         * The minimum number of octets must be used to encode the value.
+         * Short-length = <Any octet 0-30>
+         */
+        assert(null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        int count = temp & 0xFF;
+
+        if (count > LONG_INTEGER_LENGTH_MAX) {
+            throw new RuntimeException("Octet count greater than 8 and I can't represent that!");
+        }
+
+        long result = 0;
+
+        for (int i = 0 ; i < count ; i++) {
+            temp = pduDataStream.read();
+            assert(-1 != temp);
+            result <<= 8;
+            result += (temp & 0xFF);
+        }
+
+        return result;
+    }
+
+    /**
+     * Parse Integer-Value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return long integer
+     */
+    protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Integer-Value = Short-integer | Long-integer
+         */
+        assert(null != pduDataStream);
+        pduDataStream.mark(1);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        pduDataStream.reset();
+        if (temp > SHORT_INTEGER_MAX) {
+            return parseShortInteger(pduDataStream);
+        } else {
+            return parseLongInteger(pduDataStream);
+        }
+    }
+
+    /**
+     * To skip length of the wap value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param length area size
+     * @return the values in this area
+     */
+    protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) {
+        assert(null != pduDataStream);
+        byte[] area = new byte[length];
+        int readLen = pduDataStream.read(area, 0, length);
+        if (readLen < length) { //The actually read length is lower than the length
+            return -1;
+        } else {
+            return readLen;
+        }
+    }
+
+    /**
+     * Parse content type parameters. For now we just support
+     * four parameters used in mms: "type", "start", "name", "charset".
+     *
+     * @param pduDataStream pdu data input stream
+     * @param map to store parameters of Content-Type field
+     * @param length length of all the parameters
+     */
+    protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream,
+            HashMap<Integer, Object> map, Integer length) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Parameter = Typed-parameter | Untyped-parameter
+         * Typed-parameter = Well-known-parameter-token Typed-value
+         * the actual expected type of the value is implied by the well-known parameter
+         * Well-known-parameter-token = Integer-value
+         * the code values used for parameters are specified in the Assigned Numbers appendix
+         * Typed-value = Compact-value | Text-value
+         * In addition to the expected type, there may be no value.
+         * If the value cannot be encoded using the expected type, it shall be encoded as text.
+         * Compact-value = Integer-value |
+         * Date-value | Delta-seconds-value | Q-value | Version-value |
+         * Uri-value
+         * Untyped-parameter = Token-text Untyped-value
+         * the type of the value is unknown, but it shall be encoded as an integer,
+         * if that is possible.
+         * Untyped-value = Integer-value | Text-value
+         */
+        assert(null != pduDataStream);
+        assert(length > 0);
+
+        int startPos = pduDataStream.available();
+        int tempPos = 0;
+        int lastLen = length;
+        while(0 < lastLen) {
+            int param = pduDataStream.read();
+            assert(-1 != param);
+            lastLen--;
+
+            switch (param) {
+                /**
+                 * From rfc2387, chapter 3.1
+                 * The type parameter must be specified and its value is the MIME media
+                 * type of the "root" body part. It permits a MIME user agent to
+                 * determine the content-type without reference to the enclosed body
+                 * part. If the value of the type parameter and the root body part's
+                 * content-type differ then the User Agent's behavior is undefined.
+                 *
+                 * From wap-230-wsp-20010705-a.pdf
+                 * type = Constrained-encoding
+                 * Constrained-encoding = Extension-Media | Short-integer
+                 * Extension-media = *TEXT End-of-string
+                 */
+                case PduPart.P_TYPE:
+                case PduPart.P_CT_MR_TYPE:
+                    pduDataStream.mark(1);
+                    int first = extractByteValue(pduDataStream);
+                    pduDataStream.reset();
+                    if (first > TEXT_MAX) {
+                        // Short-integer (well-known type)
+                        int index = parseShortInteger(pduDataStream);
+
+                        if (index < PduContentTypes.contentTypes.length) {
+                            byte[] type = (PduContentTypes.contentTypes[index]).getBytes();
+                            map.put(PduPart.P_TYPE, type);
+                        } else {
+                            //not support this type, ignore it.
+                        }
+                    } else {
+                        // Text-String (extension-media)
+                        byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if ((null != type) && (null != map)) {
+                            map.put(PduPart.P_TYPE, type);
+                        }
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3.
+                     * Start Parameter Referring to Presentation
+                     *
+                     * From rfc2387, chapter 3.2
+                     * The start parameter, if given, is the content-ID of the compound
+                     * object's "root". If not present the "root" is the first body part in
+                     * the Multipart/Related entity. The "root" is the element the
+                     * applications processes first.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * start = Text-String
+                     */
+                case PduPart.P_START:
+                case PduPart.P_DEP_START:
+                    byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if ((null != start) && (null != map)) {
+                        map.put(PduPart.P_START, start);
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf
+                     * In creation, the character set SHALL be either us-ascii
+                     * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode].
+                     * In retrieval, both us-ascii and utf-8 SHALL be supported.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * charset = Well-known-charset|Text-String
+                     * Well-known-charset = Any-charset | Integer-value
+                     * Both are encoded using values from Character Set
+                     * Assignments table in Assigned Numbers
+                     * Any-charset = <Octet 128>
+                     * Equivalent to the special RFC2616 charset value "*"
+                     */
+                case PduPart.P_CHARSET:
+                    pduDataStream.mark(1);
+                    int firstValue = extractByteValue(pduDataStream);
+                    pduDataStream.reset();
+                    //Check first char
+                    if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) ||
+                            (END_STRING_FLAG == firstValue)) {
+                        //Text-String (extension-charset)
+                        byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        try {
+                            int charsetInt = CharacterSets.getMibEnumValue(
+                                    new String(charsetStr));
+                            map.put(PduPart.P_CHARSET, charsetInt);
+                        } catch (UnsupportedEncodingException e) {
+                            // Not a well-known charset, use "*".
+                            Log.e(LOG_TAG, Arrays.toString(charsetStr), e);
+                            map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET);
+                        }
+                    } else {
+                        //Well-known-charset
+                        int charset = (int) parseIntegerValue(pduDataStream);
+                        if (map != null) {
+                            map.put(PduPart.P_CHARSET, charset);
+                        }
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf
+                     * A name for multipart object SHALL be encoded using name-parameter
+                     * for Content-Type header in WSP multipart headers.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * name = Text-String
+                     */
+                case PduPart.P_DEP_NAME:
+                case PduPart.P_NAME:
+                    byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if ((null != name) && (null != map)) {
+                        map.put(PduPart.P_NAME, name);
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+                default:
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "Not supported Content-Type parameter");
+                    }
+                if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                    Log.e(LOG_TAG, "Corrupt Content-Type");
+                } else {
+                    lastLen = 0;
+                }
+                break;
+            }
+        }
+
+        if (0 != lastLen) {
+            Log.e(LOG_TAG, "Corrupt Content-Type");
+        }
+    }
+
+    /**
+     * Parse content type.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param map to store parameters in Content-Type header field
+     * @return Content-Type value
+     */
+    protected static byte[] parseContentType(ByteArrayInputStream pduDataStream,
+            HashMap<Integer, Object> map) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Content-type-value = Constrained-media | Content-general-form
+         * Content-general-form = Value-length Media-type
+         * Media-type = (Well-known-media | Extension-Media) *(Parameter)
+         */
+        assert(null != pduDataStream);
+
+        byte[] contentType = null;
+        pduDataStream.mark(1);
+        int temp = pduDataStream.read();
+        assert(-1 != temp);
+        pduDataStream.reset();
+
+        int cur = (temp & 0xFF);
+
+        if (cur < TEXT_MIN) {
+            int length = parseValueLength(pduDataStream);
+            int startPos = pduDataStream.available();
+            pduDataStream.mark(1);
+            temp = pduDataStream.read();
+            assert(-1 != temp);
+            pduDataStream.reset();
+            int first = (temp & 0xFF);
+
+            if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) {
+                contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+            } else if (first > TEXT_MAX) {
+                int index = parseShortInteger(pduDataStream);
+
+                if (index < PduContentTypes.contentTypes.length) { //well-known type
+                    contentType = (PduContentTypes.contentTypes[index]).getBytes();
+                } else {
+                    pduDataStream.reset();
+                    contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                }
+            } else {
+                Log.e(LOG_TAG, "Corrupt content-type");
+                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
+            }
+
+            int endPos = pduDataStream.available();
+            int parameterLen = length - (startPos - endPos);
+            if (parameterLen > 0) {//have parameters
+                parseContentTypeParams(pduDataStream, map, parameterLen);
+            }
+
+            if (parameterLen < 0) {
+                Log.e(LOG_TAG, "Corrupt MMS message");
+                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
+            }
+        } else if (cur <= TEXT_MAX) {
+            contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+        } else {
+            contentType =
+                (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes();
+        }
+
+        return contentType;
+    }
+
+    /**
+     * Parse part's headers.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param part to store the header informations of the part
+     * @param length length of the headers
+     * @return true if parse successfully, false otherwise
+     */
+    protected boolean parsePartHeaders(ByteArrayInputStream pduDataStream,
+            PduPart part, int length) {
+        assert(null != pduDataStream);
+        assert(null != part);
+        assert(length > 0);
+
+        /**
+         * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.
+         * A name for multipart object SHALL be encoded using name-parameter
+         * for Content-Type header in WSP multipart headers.
+         * In decoding, name-parameter of Content-Type SHALL be used if available.
+         * If name-parameter of Content-Type is not available,
+         * filename parameter of Content-Disposition header SHALL be used if available.
+         * If neither name-parameter of Content-Type header nor filename parameter
+         * of Content-Disposition header is available,
+         * Content-Location header SHALL be used if available.
+         *
+         * Within SMIL part the reference to the media object parts SHALL use
+         * either Content-ID or Content-Location mechanism [RFC2557]
+         * and the corresponding WSP part headers in media object parts
+         * contain the corresponding definitions.
+         */
+        int startPos = pduDataStream.available();
+        int tempPos = 0;
+        int lastLen = length;
+        while(0 < lastLen) {
+            int header = pduDataStream.read();
+            assert(-1 != header);
+            lastLen--;
+
+            if (header > TEXT_MAX) {
+                // Number assigned headers.
+                switch (header) {
+                    case PduPart.P_CONTENT_LOCATION:
+                        /**
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-location-value = Uri-value
+                         */
+                        byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if (null != contentLocation) {
+                            part.setContentLocation(contentLocation);
+                        }
+
+                        tempPos = pduDataStream.available();
+                        lastLen = length - (startPos - tempPos);
+                        break;
+                    case PduPart.P_CONTENT_ID:
+                        /**
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-ID-value = Quoted-string
+                         */
+                        byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING);
+                        if (null != contentId) {
+                            part.setContentId(contentId);
+                        }
+
+                        tempPos = pduDataStream.available();
+                        lastLen = length - (startPos - tempPos);
+                        break;
+                    case PduPart.P_DEP_CONTENT_DISPOSITION:
+                    case PduPart.P_CONTENT_DISPOSITION:
+                        /**
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-disposition-value = Value-length Disposition *(Parameter)
+                         * Disposition = Form-data | Attachment | Inline | Token-text
+                         * Form-data = <Octet 128>
+                         * Attachment = <Octet 129>
+                         * Inline = <Octet 130>
+                         */
+
+                        /*
+                         * some carrier mmsc servers do not support content_disposition
+                         * field correctly
+                         */
+                        if (mParseContentDisposition) {
+                            int len = parseValueLength(pduDataStream);
+                            pduDataStream.mark(1);
+                            int thisStartPos = pduDataStream.available();
+                            int thisEndPos = 0;
+                            int value = pduDataStream.read();
+
+                            if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
+                                part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
+                            } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
+                                part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
+                            } else if (value == PduPart.P_DISPOSITION_INLINE) {
+                                part.setContentDisposition(PduPart.DISPOSITION_INLINE);
+                            } else {
+                                pduDataStream.reset();
+                                /* Token-text */
+                                part.setContentDisposition(parseWapString(pduDataStream
+                                        , TYPE_TEXT_STRING));
+                            }
+
+                            /* get filename parameter and skip other parameters */
+                            thisEndPos = pduDataStream.available();
+                            if (thisStartPos - thisEndPos < len) {
+                                value = pduDataStream.read();
+                                if (value == PduPart.P_FILENAME) { //filename is text-string
+                                    part.setFilename(parseWapString(pduDataStream
+                                            , TYPE_TEXT_STRING));
+                                }
+
+                                /* skip other parameters */
+                                thisEndPos = pduDataStream.available();
+                                if (thisStartPos - thisEndPos < len) {
+                                    int last = len - (thisStartPos - thisEndPos);
+                                    byte[] temp = new byte[last];
+                                    pduDataStream.read(temp, 0, last);
+                                }
+                            }
+
+                            tempPos = pduDataStream.available();
+                            lastLen = length - (startPos - tempPos);
+                        }
+                        break;
+                    default:
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "Not supported Part headers: " + header);
+                        }
+                    if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                        Log.e(LOG_TAG, "Corrupt Part headers");
+                        return false;
+                    }
+                    lastLen = 0;
+                    break;
+                }
+            } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) {
+                // Not assigned header.
+                byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+
+                // Check the header whether it is "Content-Transfer-Encoding".
+                if (true ==
+                    PduPart.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(new String(tempHeader))) {
+                    part.setContentTransferEncoding(tempValue);
+                }
+
+                tempPos = pduDataStream.available();
+                lastLen = length - (startPos - tempPos);
+            } else {
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "Not supported Part headers: " + header);
+                }
+                // Skip all headers of this part.
+                if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                    Log.e(LOG_TAG, "Corrupt Part headers");
+                    return false;
+                }
+                lastLen = 0;
+            }
+        }
+
+        if (0 != lastLen) {
+            Log.e(LOG_TAG, "Corrupt Part headers");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check the position of a specified part.
+     *
+     * @param part the part to be checked
+     * @return part position, THE_FIRST_PART when it's the
+     * first one, THE_LAST_PART when it's the last one.
+     */
+    private static int checkPartPosition(PduPart part) {
+        assert(null != part);
+        if ((null == mTypeParam) &&
+                (null == mStartParam)) {
+            return THE_LAST_PART;
+        }
+
+        /* check part's content-id */
+        if (null != mStartParam) {
+            byte[] contentId = part.getContentId();
+            if (null != contentId) {
+                if (true == Arrays.equals(mStartParam, contentId)) {
+                    return THE_FIRST_PART;
+                }
+            }
+            // This is not the first part, so append to end (keeping the original order)
+            // Check b/19607294 for details of this change
+            return THE_LAST_PART;
+        }
+
+        /* check part's content-type */
+        if (null != mTypeParam) {
+            byte[] contentType = part.getContentType();
+            if (null != contentType) {
+                if (true == Arrays.equals(mTypeParam, contentType)) {
+                    return THE_FIRST_PART;
+                }
+            }
+        }
+
+        return THE_LAST_PART;
+    }
+
+    /**
+     * Check mandatory headers of a pdu.
+     *
+     * @param headers pdu headers
+     * @return true if the pdu has all of the mandatory headers, false otherwise.
+     */
+    protected static boolean checkMandatoryHeader(PduHeaders headers) {
+        if (null == headers) {
+            return false;
+        }
+
+        /* get message type */
+        int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
+
+        /* check Mms-Version field */
+        int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION);
+        if (0 == mmsVersion) {
+            // Every message should have Mms-Version field.
+            return false;
+        }
+
+        /* check mandatory header fields */
+        switch (messageType) {
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                // Content-Type field.
+                byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
+                if (null == srContentType) {
+                    return false;
+                }
+
+                // From field.
+                EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == srFrom) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == srTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
+                // Response-Status field.
+                int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS);
+                if (0 == scResponseStatus) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == scTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                // Content-Location field.
+                byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION);
+                if (null == niContentLocation) {
+                    return false;
+                }
+
+                // Expiry field.
+                long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY);
+                if (-1 == niExpiry) {
+                    return false;
+                }
+
+                // Message-Class field.
+                byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS);
+                if (null == niMessageClass) {
+                    return false;
+                }
+
+                // Message-Size field.
+                long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE);
+                if (-1 == niMessageSize) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == niTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                // Status field.
+                int nriStatus = headers.getOctet(PduHeaders.STATUS);
+                if (0 == nriStatus) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == nriTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                // Content-Type field.
+                byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
+                if (null == rcContentType) {
+                    return false;
+                }
+
+                // Date field.
+                long rcDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == rcDate) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+                // Date field.
+                long diDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == diDate) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == diMessageId) {
+                    return false;
+                }
+
+                // Status field.
+                int diStatus = headers.getOctet(PduHeaders.STATUS);
+                if (0 == diStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == diTo) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                // Transaction-Id field.
+                byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == aiTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
+                // Date field.
+                long roDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == roDate) {
+                    return false;
+                }
+
+                // From field.
+                EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == roFrom) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == roMessageId) {
+                    return false;
+                }
+
+                // Read-Status field.
+                int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
+                if (0 == roReadStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == roTo) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                // From field.
+                EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == rrFrom) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == rrMessageId) {
+                    return false;
+                }
+
+                // Read-Status field.
+                int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
+                if (0 == rrReadStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == rrTo) {
+                    return false;
+                }
+
+                break;
+            default:
+                // Parser doesn't support this message type in this version.
+                return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/PduPart.java b/src/android/support/v7/mms/pdu/PduPart.java
new file mode 100644
index 0000000..b20045e
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/PduPart.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import android.net.Uri;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The pdu part.
+ */
+public class PduPart {
+    /**
+     * Well-Known Parameters.
+     */
+    public static final int P_Q                  = 0x80;
+    public static final int P_CHARSET            = 0x81;
+    public static final int P_LEVEL              = 0x82;
+    public static final int P_TYPE               = 0x83;
+    public static final int P_DEP_NAME           = 0x85;
+    public static final int P_DEP_FILENAME       = 0x86;
+    public static final int P_DIFFERENCES        = 0x87;
+    public static final int P_PADDING            = 0x88;
+    // This value of "TYPE" s used with Content-Type: multipart/related
+    public static final int P_CT_MR_TYPE         = 0x89;
+    public static final int P_DEP_START          = 0x8A;
+    public static final int P_DEP_START_INFO     = 0x8B;
+    public static final int P_DEP_COMMENT        = 0x8C;
+    public static final int P_DEP_DOMAIN         = 0x8D;
+    public static final int P_MAX_AGE            = 0x8E;
+    public static final int P_DEP_PATH           = 0x8F;
+    public static final int P_SECURE             = 0x90;
+    public static final int P_SEC                = 0x91;
+    public static final int P_MAC                = 0x92;
+    public static final int P_CREATION_DATE      = 0x93;
+    public static final int P_MODIFICATION_DATE  = 0x94;
+    public static final int P_READ_DATE          = 0x95;
+    public static final int P_SIZE               = 0x96;
+    public static final int P_NAME               = 0x97;
+    public static final int P_FILENAME           = 0x98;
+    public static final int P_START              = 0x99;
+    public static final int P_START_INFO         = 0x9A;
+    public static final int P_COMMENT            = 0x9B;
+    public static final int P_DOMAIN             = 0x9C;
+    public static final int P_PATH               = 0x9D;
+
+    /**
+     *  Header field names.
+     */
+     public static final int P_CONTENT_TYPE       = 0x91;
+     public static final int P_CONTENT_LOCATION   = 0x8E;
+     public static final int P_CONTENT_ID         = 0xC0;
+     public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
+     public static final int P_CONTENT_DISPOSITION = 0xC5;
+    // The next header is unassigned header, use reserved header(0x48) value.
+     public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
+
+     /**
+      * Content=Transfer-Encoding string.
+      */
+     public static final String CONTENT_TRANSFER_ENCODING =
+             "Content-Transfer-Encoding";
+
+     /**
+      * Value of Content-Transfer-Encoding.
+      */
+     public static final String P_BINARY = "binary";
+     public static final String P_7BIT = "7bit";
+     public static final String P_8BIT = "8bit";
+     public static final String P_BASE64 = "base64";
+     public static final String P_QUOTED_PRINTABLE = "quoted-printable";
+
+     /**
+      * Value of disposition can be set to PduPart when the value is octet in
+      * the PDU.
+      * "from-data" instead of Form-data<Octet 128>.
+      * "attachment" instead of Attachment<Octet 129>.
+      * "inline" instead of Inline<Octet 130>.
+      */
+     static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
+     static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
+     static final byte[] DISPOSITION_INLINE = "inline".getBytes();
+
+     /**
+      * Content-Disposition value.
+      */
+     public static final int P_DISPOSITION_FROM_DATA  = 0x80;
+     public static final int P_DISPOSITION_ATTACHMENT = 0x81;
+     public static final int P_DISPOSITION_INLINE     = 0x82;
+
+     /**
+      * Header of part.
+      */
+     private Map<Integer, Object> mPartHeader = null;
+
+     /**
+      * Data uri.
+      */
+     private Uri mUri = null;
+
+     /**
+      * Part data.
+      */
+     private byte[] mPartData = null;
+
+     private static final String TAG = "PduPart";
+
+     /**
+      * Empty Constructor.
+      */
+     public PduPart() {
+         mPartHeader = new HashMap<Integer, Object>();
+     }
+
+     /**
+      * Set part data. The data are stored as byte array.
+      *
+      * @param data the data
+      */
+     public void setData(byte[] data) {
+         if(data == null) {
+            return;
+        }
+
+         mPartData = new byte[data.length];
+         System.arraycopy(data, 0, mPartData, 0, data.length);
+     }
+
+     /**
+      * @return A copy of the part data or null if the data wasn't set or
+      *         the data is stored as Uri.
+      * @see #getDataUri
+      */
+     public byte[] getData() {
+         if(mPartData == null) {
+            return null;
+         }
+
+         byte[] byteArray = new byte[mPartData.length];
+         System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length);
+         return byteArray;
+     }
+
+    /**
+     * @return The length of the data, if this object have data, else 0.
+     */
+     public int getDataLength() {
+         if(mPartData != null){
+             return mPartData.length;
+         } else {
+             return 0;
+         }
+     }
+
+
+     /**
+      * Set data uri. The data are stored as Uri.
+      *
+      * @param uri the uri
+      */
+     public void setDataUri(Uri uri) {
+         mUri = uri;
+     }
+
+     /**
+      * @return The Uri of the part data or null if the data wasn't set or
+      *         the data is stored as byte array.
+      * @see #getData
+      */
+     public Uri getDataUri() {
+         return mUri;
+     }
+
+     /**
+      * Set Content-id value
+      *
+      * @param contentId the content-id value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setContentId(byte[] contentId) {
+         if((contentId == null) || (contentId.length == 0)) {
+             throw new IllegalArgumentException(
+                     "Content-Id may not be null or empty.");
+         }
+
+         if ((contentId.length > 1)
+                 && ((char) contentId[0] == '<')
+                 && ((char) contentId[contentId.length - 1] == '>')) {
+             mPartHeader.put(P_CONTENT_ID, contentId);
+             return;
+         }
+
+         // Insert beginning '<' and trailing '>' for Content-Id.
+         byte[] buffer = new byte[contentId.length + 2];
+         buffer[0] = (byte) (0xff & '<');
+         buffer[buffer.length - 1] = (byte) (0xff & '>');
+         System.arraycopy(contentId, 0, buffer, 1, contentId.length);
+         mPartHeader.put(P_CONTENT_ID, buffer);
+     }
+
+     /**
+      * Get Content-id value.
+      *
+      * @return the value
+      */
+     public byte[] getContentId() {
+         return (byte[]) mPartHeader.get(P_CONTENT_ID);
+     }
+
+     /**
+      * Set Char-set value.
+      *
+      * @param charset the value
+      */
+     public void setCharset(int charset) {
+         mPartHeader.put(P_CHARSET, charset);
+     }
+
+     /**
+      * Get Char-set value
+      *
+      * @return the charset value. Return 0 if charset was not set.
+      */
+     public int getCharset() {
+         Integer charset = (Integer) mPartHeader.get(P_CHARSET);
+         if(charset == null) {
+             return 0;
+         } else {
+             return charset.intValue();
+         }
+     }
+
+     /**
+      * Set Content-Location value.
+      *
+      * @param contentLocation the value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setContentLocation(byte[] contentLocation) {
+         if(contentLocation == null) {
+             throw new NullPointerException("null content-location");
+         }
+
+         mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
+     }
+
+     /**
+      * Get Content-Location value.
+      *
+      * @return the value
+      *     return PduPart.disposition[0] instead of <Octet 128> (Form-data).
+      *     return PduPart.disposition[1] instead of <Octet 129> (Attachment).
+      *     return PduPart.disposition[2] instead of <Octet 130> (Inline).
+      */
+     public byte[] getContentLocation() {
+         return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
+     }
+
+     /**
+      * Set Content-Disposition value.
+      * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
+      * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
+      * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
+      *
+      * @param contentDisposition the value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setContentDisposition(byte[] contentDisposition) {
+         if(contentDisposition == null) {
+             throw new NullPointerException("null content-disposition");
+         }
+
+         mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
+     }
+
+     /**
+      * Get Content-Disposition value.
+      *
+      * @return the value
+      */
+     public byte[] getContentDisposition() {
+         return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
+     }
+
+     /**
+      *  Set Content-Type value.
+      *
+      *  @param contentType the content type
+      *  @throws NullPointerException if the value is null.
+      */
+     public void setContentType(byte[] contentType) {
+         if(contentType == null) {
+             throw new NullPointerException("null content-type");
+         }
+
+         mPartHeader.put(P_CONTENT_TYPE, contentType);
+     }
+
+     /**
+      * Get Content-Type value of part.
+      *
+      * @return the value
+      */
+     public byte[] getContentType() {
+         return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
+     }
+
+     /**
+      * Set Content-Transfer-Encoding value
+      *
+      * @param contentTransferEncoding the Content-Transfer-Encoding value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setContentTransferEncoding(byte[] contentTransferEncoding) {
+         if(contentTransferEncoding == null) {
+             throw new NullPointerException("null content-transfer-encoding");
+         }
+
+         mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
+     }
+
+     /**
+      * Get Content-Transfer-Encoding value.
+      *
+      * @return the value
+      */
+     public byte[] getContentTransferEncoding() {
+         return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
+     }
+
+     /**
+      * Set Content-type parameter: name.
+      *
+      * @param name the name value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setName(byte[] name) {
+         if(null == name) {
+             throw new NullPointerException("null content-id");
+         }
+
+         mPartHeader.put(P_NAME, name);
+     }
+
+     /**
+      *  Get content-type parameter: name.
+      *
+      *  @return the name
+      */
+     public byte[] getName() {
+         return (byte[]) mPartHeader.get(P_NAME);
+     }
+
+     /**
+      * Get Content-disposition parameter: filename
+      *
+      * @param fileName the filename value
+      * @throws NullPointerException if the value is null.
+      */
+     public void setFilename(byte[] fileName) {
+         if(null == fileName) {
+             throw new NullPointerException("null content-id");
+         }
+
+         mPartHeader.put(P_FILENAME, fileName);
+     }
+
+     /**
+      * Set Content-disposition parameter: filename
+      *
+      * @return the filename
+      */
+     public byte[] getFilename() {
+         return (byte[]) mPartHeader.get(P_FILENAME);
+     }
+
+    public String generateLocation() {
+        // Assumption: At least one of the content-location / name / filename
+        // or content-id should be set. This is guaranteed by the PduParser
+        // for incoming messages and by MM composer for outgoing messages.
+        byte[] location = (byte[]) mPartHeader.get(P_NAME);
+        if(null == location) {
+            location = (byte[]) mPartHeader.get(P_FILENAME);
+
+            if (null == location) {
+                location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
+            }
+        }
+
+        if (null == location) {
+            byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
+            return "cid:" + new String(contentId);
+        } else {
+            return new String(location);
+        }
+    }
+}
+
diff --git a/src/android/support/v7/mms/pdu/QuotedPrintable.java b/src/android/support/v7/mms/pdu/QuotedPrintable.java
new file mode 100644
index 0000000..2e16581
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/QuotedPrintable.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import java.io.ByteArrayOutputStream;
+
+public class QuotedPrintable {
+    private static byte ESCAPE_CHAR = '=';
+
+    /**
+     * Decodes an array quoted-printable characters into an array of original bytes.
+     * Escaped characters are converted back to their original representation.
+     *
+     * <p>
+     * This function implements a subset of
+     * quoted-printable encoding specification (rule #1 and rule #2)
+     * as defined in RFC 1521.
+     * </p>
+     *
+     * @param bytes array of quoted-printable characters
+     * @return array of original bytes,
+     *         null if quoted-printable decoding is unsuccessful.
+     */
+    public static final byte[] decodeQuotedPrintable(byte[] bytes) {
+        if (bytes == null) {
+            return null;
+        }
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        for (int i = 0; i < bytes.length; i++) {
+            int b = bytes[i];
+            if (b == ESCAPE_CHAR) {
+                try {
+                    if('\r' == (char)bytes[i + 1] &&
+                            '\n' == (char)bytes[i + 2]) {
+                        i += 2;
+                        continue;
+                    }
+                    int u = Character.digit((char) bytes[++i], 16);
+                    int l = Character.digit((char) bytes[++i], 16);
+                    if (u == -1 || l == -1) {
+                        return null;
+                    }
+                    buffer.write((char) ((u << 4) + l));
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    return null;
+                }
+            } else {
+                buffer.write(b);
+            }
+        }
+        return buffer.toByteArray();
+    }
+}
diff --git a/src/android/support/v7/mms/pdu/ReadOrigInd.java b/src/android/support/v7/mms/pdu/ReadOrigInd.java
new file mode 100644
index 0000000..c0e37ee
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/ReadOrigInd.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class ReadOrigInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public ReadOrigInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_READ_ORIG_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    ReadOrigInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+       return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-MMS-Read-status value.
+     *
+     * @return the value
+     */
+    public int getReadStatus() {
+        return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Set X-MMS-Read-status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/ReadRecInd.java b/src/android/support/v7/mms/pdu/ReadRecInd.java
new file mode 100644
index 0000000..bd0848c
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/ReadRecInd.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class ReadRecInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-ReadRec.ind pdu.
+     *
+     * @param from the from value
+     * @param messageId the message ID value
+     * @param mmsVersion current viersion of mms
+     * @param readStatus the read status value
+     * @param to the to value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     *         NullPointerException if messageId or to is null.
+     */
+    public ReadRecInd(EncodedStringValue from,
+                      byte[] messageId,
+                      int mmsVersion,
+                      int readStatus,
+                      EncodedStringValue[] to) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
+        setFrom(from);
+        setMessageId(messageId);
+        setMmsVersion(mmsVersion);
+        setTo(to);
+        setReadStatus(readStatus);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    ReadRecInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-MMS-Read-status value.
+     *
+     * @return the value
+     */
+    public int getReadStatus() {
+        return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Set X-MMS-Read-status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/RetrieveConf.java b/src/android/support/v7/mms/pdu/RetrieveConf.java
new file mode 100644
index 0000000..4da42eb
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/RetrieveConf.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+/**
+ * M-Retrive.conf Pdu.
+ */
+public class RetrieveConf extends MultimediaMessagePdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public RetrieveConf() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    RetrieveConf(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Constructor with given headers and body
+     *
+     * @param headers Headers for this PDU.
+     * @param body Body of this PDu.
+     */
+    RetrieveConf(PduHeaders headers, PduBody body) {
+        super(headers, body);
+    }
+
+    /**
+     * Get CC value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getCc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
+    }
+
+    /**
+     * Add a "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addCc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
+    }
+
+    /**
+     * Get Content-type value.
+     *
+     * @return the value
+     */
+    public byte[] getContentType() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Set Content-type value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentType(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+       return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-Mms-Read-Report value.
+     *
+     * @return the value
+     */
+    public int getReadReport() {
+        return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Read-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Get X-Mms-Retrieve-Status value.
+     *
+     * @return the value
+     */
+    public int getRetrieveStatus() {
+        return mPduHeaders.getOctet(PduHeaders.RETRIEVE_STATUS);
+    }
+
+    /**
+     * Set X-Mms-Retrieve-Status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setRetrieveStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.RETRIEVE_STATUS);
+    }
+
+    /**
+     * Get X-Mms-Retrieve-Text value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getRetrieveText() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT);
+    }
+
+    /**
+     * Set X-Mms-Retrieve-Text value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setRetrieveText(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.RETRIEVE_TEXT);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id.
+     *
+     * @return the value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getContentClass() {return 0x00;}
+     *     public void setApplicId(byte value) {}
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public byte getDistributionIndicator() {return 0x00;}
+     *     public void setDistributionIndicator(byte value) {}
+     *
+     *     public PreviouslySentByValue getPreviouslySentBy() {return null;}
+     *     public void setPreviouslySentBy(PreviouslySentByValue value) {}
+     *
+     *     public PreviouslySentDateValue getPreviouslySentDate() {}
+     *     public void setPreviouslySentDate(PreviouslySentDateValue value) {}
+     *
+     *     public MmFlagsValue getMmFlags() {return null;}
+     *     public void setMmFlags(MmFlagsValue value) {}
+     *
+     *     public MmStateValue getMmState() {return null;}
+     *     public void getMmState(MmStateValue value) {}
+     *
+     *     public byte[] getReplaceId() {return 0x00;}
+     *     public void setReplaceId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/SendConf.java b/src/android/support/v7/mms/pdu/SendConf.java
new file mode 100644
index 0000000..94a9abc
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/SendConf.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+public class SendConf extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public SendConf() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_SEND_CONF);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    SendConf(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-Mms-Response-Status.
+     *
+     * @return the value
+     */
+    public int getResponseStatus() {
+        return mPduHeaders.getOctet(PduHeaders.RESPONSE_STATUS);
+    }
+
+    /**
+     * Set X-Mms-Response-Status.
+     *
+     * @param value the values
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setResponseStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.RESPONSE_STATUS);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+            mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *    public byte[] getContentLocation() {return null;}
+     *    public void setContentLocation(byte[] value) {}
+     *
+     *    public EncodedStringValue getResponseText() {return null;}
+     *    public void setResponseText(EncodedStringValue value) {}
+     *
+     *    public byte getStoreStatus() {return 0x00;}
+     *    public void setStoreStatus(byte value) {}
+     *
+     *    public byte[] getStoreStatusText() {return null;}
+     *    public void setStoreStatusText(byte[] value) {}
+     */
+}
diff --git a/src/android/support/v7/mms/pdu/SendReq.java b/src/android/support/v7/mms/pdu/SendReq.java
new file mode 100644
index 0000000..bf3b32c
--- /dev/null
+++ b/src/android/support/v7/mms/pdu/SendReq.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.mms.pdu;
+
+import android.util.Log;
+
+public class SendReq extends MultimediaMessagePdu {
+    private static final String TAG = "SendReq";
+
+    public SendReq() {
+        super();
+
+        try {
+            setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
+            setMmsVersion(PduHeaders.CURRENT_MMS_VERSION);
+            // FIXME: Content-type must be decided according to whether
+            // SMIL part present.
+            setContentType("application/vnd.wap.multipart.related".getBytes());
+            setFrom(new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()));
+            setTransactionId(generateTransactionId());
+        } catch (InvalidHeaderValueException e) {
+            // Impossible to reach here since all headers we set above are valid.
+            Log.e(TAG, "Unexpected InvalidHeaderValueException.", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    private byte[] generateTransactionId() {
+        String transactionId = "T" + Long.toHexString(System.currentTimeMillis());
+        return transactionId.getBytes();
+    }
+
+    /**
+     * Constructor, used when composing a M-Send.req pdu.
+     *
+     * @param contentType the content type value
+     * @param from the from value
+     * @param mmsVersion current viersion of mms
+     * @param transactionId the transaction-id value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     *         NullPointerException if contentType, form or transactionId is null.
+     */
+    public SendReq(byte[] contentType,
+                   EncodedStringValue from,
+                   int mmsVersion,
+                   byte[] transactionId) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
+        setContentType(contentType);
+        setFrom(from);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    SendReq(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Constructor with given headers and body
+     *
+     * @param headers Headers for this PDU.
+     * @param body Body of this PDu.
+     */
+    SendReq(PduHeaders headers, PduBody body) {
+        super(headers, body);
+    }
+
+    /**
+     * Get Bcc value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getBcc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.BCC);
+    }
+
+    /**
+     * Add a "BCC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addBcc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.BCC);
+    }
+
+    /**
+     * Set "BCC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setBcc(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.BCC);
+    }
+
+    /**
+     * Get CC value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getCc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
+    }
+
+    /**
+     * Add a "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addCc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
+    }
+
+    /**
+     * Set "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setCc(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.CC);
+    }
+
+    /**
+     * Get Content-type value.
+     *
+     * @return the value
+     */
+    public byte[] getContentType() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Set Content-type value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentType(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Get X-Mms-Expiry value.
+     *
+     * Expiry-value = Value-length
+     *      (Absolute-token Date-value | Relative-token Delta-seconds-value)
+     *
+     * @return the value
+     */
+    public long getExpiry() {
+        return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Set X-Mms-Expiry value.
+     *
+     * @param value the value
+     */
+    public void setExpiry(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Get X-Mms-MessageSize value.
+     *
+     * Expiry-value = size of message
+     *
+     * @return the value
+     */
+    public long getMessageSize() {
+        return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Set X-Mms-MessageSize value.
+     *
+     * @param value the value
+     */
+    public void setMessageSize(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Read-Report value.
+     *
+     * @return the value
+     */
+    public int getReadReport() {
+        return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Read-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set "To" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte getAdaptationAllowed() {return 0};
+     *     public void setAdaptationAllowed(btye value) {};
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getContentClass() {return 0x00;}
+     *     public void setApplicId(byte value) {}
+     *
+     *     public long getDeliveryTime() {return 0};
+     *     public void setDeliveryTime(long value) {};
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public MmFlagsValue getMmFlags() {return null;}
+     *     public void setMmFlags(MmFlagsValue value) {}
+     *
+     *     public MmStateValue getMmState() {return null;}
+     *     public void getMmState(MmStateValue value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getStore() {return 0x00;}
+     *     public void setStore(byte value) {}
+     */
+}
diff --git a/src/com/android/messaging/BugleApplication.java b/src/com/android/messaging/BugleApplication.java
new file mode 100644
index 0000000..36f062b
--- /dev/null
+++ b/src/com/android/messaging/BugleApplication.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.Handler;
+import android.os.Looper;
+import androidx.appcompat.mms.CarrierConfigValuesLoader;
+import androidx.appcompat.mms.MmsManager;
+import android.telephony.CarrierConfigManager;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.receiver.SmsReceiver;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.BugleApnSettingsLoader;
+import com.android.messaging.sms.BugleUserAgentInfoLoader;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.Trace;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.lang.Thread.UncaughtExceptionHandler;
+
+/**
+ * The application object
+ */
+public class BugleApplication extends Application implements UncaughtExceptionHandler {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private UncaughtExceptionHandler sSystemUncaughtExceptionHandler;
+    private static boolean sRunningTests = false;
+
+    @VisibleForTesting
+    protected static void setTestsRunning() {
+        sRunningTests = true;
+    }
+
+    /**
+     * @return true if we're running unit tests.
+     */
+    public static boolean isRunningTests() {
+        return sRunningTests;
+    }
+
+    @Override
+    public void onCreate() {
+        Trace.beginSection("app.onCreate");
+        super.onCreate();
+
+        // Note onCreate is called in both test and real application environments
+        if (!sRunningTests) {
+            // Only create the factory if not running tests
+            FactoryImpl.register(getApplicationContext(), this);
+        } else {
+            LogUtil.e(TAG, "BugleApplication.onCreate: FactoryImpl.register skipped for test run");
+        }
+
+        sSystemUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
+        Thread.setDefaultUncaughtExceptionHandler(this);
+        Trace.endSection();
+    }
+
+    @Override
+    public void onConfigurationChanged(final Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        // Update conversation drawables when changing writing systems
+        // (Right-To-Left / Left-To-Right)
+        ConversationDrawables.get().updateDrawables();
+    }
+
+    // Called by the "real" factory from FactoryImpl.register() (i.e. not run in tests)
+    public void initializeSync(final Factory factory) {
+        Trace.beginSection("app.initializeSync");
+        final Context context = factory.getApplicationContext();
+        final BugleGservices bugleGservices = factory.getBugleGservices();
+        final BuglePrefs buglePrefs = factory.getApplicationPrefs();
+        final DataModel dataModel = factory.getDataModel();
+        final CarrierConfigValuesLoader carrierConfigValuesLoader =
+                factory.getCarrierConfigValuesLoader();
+
+        maybeStartProfiling();
+
+        BugleApplication.updateAppConfig(context);
+
+        // Initialize MMS lib
+        initMmsLib(context, bugleGservices, carrierConfigValuesLoader);
+        // Initialize APN database
+        ApnDatabase.initializeAppContext(context);
+        // Fixup messages in flight if we crashed and send any pending
+        dataModel.onApplicationCreated();
+        // Register carrier config change receiver
+        if (OsUtil.isAtLeastM()) {
+            registerCarrierConfigChangeReceiver(context);
+        }
+
+        Trace.endSection();
+    }
+
+    private static void registerCarrierConfigChangeReceiver(final Context context) {
+        context.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                LogUtil.i(TAG, "Carrier config changed. Reloading MMS config.");
+                MmsConfig.loadAsync();
+            }
+        }, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED),
+        Context.RECEIVER_EXPORTED/*UNAUDITED*/);
+    }
+
+    private static void initMmsLib(final Context context, final BugleGservices bugleGservices,
+            final CarrierConfigValuesLoader carrierConfigValuesLoader) {
+        MmsManager.setApnSettingsLoader(new BugleApnSettingsLoader(context));
+        MmsManager.setCarrierConfigValuesLoader(carrierConfigValuesLoader);
+        MmsManager.setUserAgentInfoLoader(new BugleUserAgentInfoLoader(context));
+        MmsManager.setUseWakeLock(true);
+        // If Gservices is configured not to use mms api, force MmsManager to always use
+        // legacy mms sending logic
+        MmsManager.setForceLegacyMms(!bugleGservices.getBoolean(
+                BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
+                BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT));
+        bugleGservices.registerForChanges(new Runnable() {
+            @Override
+            public void run() {
+                MmsManager.setForceLegacyMms(!bugleGservices.getBoolean(
+                        BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
+                        BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT));
+            }
+        });
+    }
+
+    public static void updateAppConfig(final Context context) {
+        // Make sure we set the correct state for the SMS/MMS receivers
+        SmsReceiver.updateSmsReceiveHandler(context);
+    }
+
+    // Called from thread started in FactoryImpl.register() (i.e. not run in tests)
+    public void initializeAsync(final Factory factory) {
+        // Handle shared prefs upgrade & Load MMS Configuration
+        Trace.beginSection("app.initializeAsync");
+        maybeHandleSharedPrefsUpgrade(factory);
+        MmsConfig.load();
+        Trace.endSection();
+    }
+
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "BugleApplication.onLowMemory");
+        }
+        Factory.get().reclaimMemory();
+    }
+
+    @Override
+    public void uncaughtException(final Thread thread, final Throwable ex) {
+        final boolean background = getMainLooper().getThread() != thread;
+        if (background) {
+            LogUtil.e(TAG, "Uncaught exception in background thread " + thread, ex);
+
+            final Handler handler = new Handler(getMainLooper());
+            handler.post(new Runnable() {
+
+                @Override
+                public void run() {
+                    sSystemUncaughtExceptionHandler.uncaughtException(thread, ex);
+                }
+            });
+        } else {
+            sSystemUncaughtExceptionHandler.uncaughtException(thread, ex);
+        }
+    }
+
+    private void maybeStartProfiling() {
+        // App startup profiling support. To use it:
+        //  adb shell setprop log.tag.BugleProfile DEBUG
+        //  #   Start the app, wait for a 30s, download trace file:
+        //  adb pull /data/data/com.android.messaging/cache/startup.trace /tmp
+        //  # Open trace file (using adt/tools/traceview)
+        if (android.util.Log.isLoggable(LogUtil.PROFILE_TAG, android.util.Log.DEBUG)) {
+            // Start method tracing with a big enough buffer and let it run for 30s.
+            // Note we use a logging tag as we don't want to wait for gservices to start up.
+            final File file = DebugUtils.getDebugFile("startup.trace", true);
+            if (file != null) {
+                android.os.Debug.startMethodTracing(file.getAbsolutePath(), 160 * 1024 * 1024);
+                new Handler(Looper.getMainLooper()).postDelayed(
+                       new Runnable() {
+                            @Override
+                            public void run() {
+                                android.os.Debug.stopMethodTracing();
+                                // Allow world to see trace file
+                                DebugUtils.ensureReadable(file);
+                                LogUtil.d(LogUtil.PROFILE_TAG, "Tracing complete - "
+                                     + file.getAbsolutePath());
+                            }
+                        }, 30000);
+            }
+        }
+    }
+
+    private void maybeHandleSharedPrefsUpgrade(final Factory factory) {
+        final int existingVersion = factory.getApplicationPrefs().getInt(
+                BuglePrefsKeys.SHARED_PREFERENCES_VERSION,
+                BuglePrefsKeys.SHARED_PREFERENCES_VERSION_DEFAULT);
+        final int targetVersion = Integer.parseInt(getString(R.string.pref_version));
+        if (targetVersion > existingVersion) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Upgrading shared prefs from " + existingVersion +
+                    " to " + targetVersion);
+            try {
+                // Perform upgrade on application-wide prefs.
+                factory.getApplicationPrefs().onUpgrade(existingVersion, targetVersion);
+                // Perform upgrade on each subscription's prefs.
+                PhoneUtils.forEachActiveSubscription(new PhoneUtils.SubscriptionRunnable() {
+                    @Override
+                    public void runForSubscription(final int subId) {
+                        factory.getSubscriptionPrefs(subId)
+                                .onUpgrade(existingVersion, targetVersion);
+                    }
+                });
+                factory.getApplicationPrefs().putInt(BuglePrefsKeys.SHARED_PREFERENCES_VERSION,
+                        targetVersion);
+            } catch (final Exception ex) {
+                // Upgrade failed. Don't crash the app because we can always fall back to the
+                // default settings.
+                LogUtil.e(LogUtil.BUGLE_TAG, "Failed to upgrade shared prefs", ex);
+            }
+        } else if (targetVersion < existingVersion) {
+            // We don't care about downgrade since real user shouldn't encounter this, so log it
+            // and ignore any prefs migration.
+            LogUtil.e(LogUtil.BUGLE_TAG, "Shared prefs downgrade requested and ignored. " +
+                    "oldVersion = " + existingVersion + ", newVersion = " + targetVersion);
+        }
+    }
+}
diff --git a/src/com/android/messaging/Factory.java b/src/com/android/messaging/Factory.java
new file mode 100644
index 0000000..c542a54
--- /dev/null
+++ b/src/com/android/messaging/Factory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.Context;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.ParticipantRefresh.ContactContentObserver;
+import com.android.messaging.datamodel.media.MediaCacheManager;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.sms.BugleCarrierConfigValuesLoader;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+public abstract class Factory {
+
+    // Making this volatile because on the unit tests, setInstance is called from a unit test
+    // thread, and then it's read on the UI thread.
+    private static volatile Factory sInstance;
+    @VisibleForTesting
+    protected static boolean sRegistered;
+    @VisibleForTesting
+    protected static boolean sInitialized;
+
+    public static Factory get() {
+        return sInstance;
+    }
+
+    protected static void setInstance(final Factory factory) {
+        // Not allowed to call this after real application initialization is complete
+        Assert.isTrue(!sRegistered);
+        Assert.isTrue(!sInitialized);
+        sInstance = factory;
+    }
+    public abstract void onRequiredPermissionsAcquired();
+
+    public abstract Context getApplicationContext();
+    public abstract DataModel getDataModel();
+    public abstract BugleGservices getBugleGservices();
+    public abstract BuglePrefs getApplicationPrefs();
+    public abstract BuglePrefs getSubscriptionPrefs(int subId);
+    public abstract BuglePrefs getWidgetPrefs();
+    public abstract UIIntents getUIIntents();
+    public abstract MemoryCacheManager getMemoryCacheManager();
+    public abstract MediaResourceManager getMediaResourceManager();
+    public abstract MediaCacheManager getMediaCacheManager();
+    public abstract ContactContentObserver getContactContentObserver();
+    public abstract PhoneUtils getPhoneUtils(int subId);
+    public abstract MediaUtil getMediaUtil();
+    public abstract BugleCarrierConfigValuesLoader getCarrierConfigValuesLoader();
+    // Note this needs to run from any thread
+    public abstract void reclaimMemory();
+
+    public abstract void onActivityResume();
+}
diff --git a/src/com/android/messaging/FactoryImpl.java b/src/com/android/messaging/FactoryImpl.java
new file mode 100644
index 0000000..a862308
--- /dev/null
+++ b/src/com/android/messaging/FactoryImpl.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.Context;
+import android.os.Process;
+import android.telephony.SmsManager;
+import android.util.SparseArray;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelImpl;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.ParticipantRefresh.ContactContentObserver;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.media.BugleMediaCacheManager;
+import com.android.messaging.datamodel.media.MediaCacheManager;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.sms.BugleCarrierConfigValuesLoader;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.UIIntentsImpl;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleApplicationPrefs;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesImpl;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BugleSubscriptionPrefs;
+import com.android.messaging.util.BugleWidgetPrefs;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.MediaUtilImpl;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+class FactoryImpl extends Factory {
+    private BugleApplication mApplication;
+    private DataModel mDataModel;
+    private BugleGservices mBugleGservices;
+    private BugleApplicationPrefs mBugleApplicationPrefs;
+    private BugleWidgetPrefs mBugleWidgetPrefs;
+    private Context mApplicationContext;
+    private UIIntents mUIIntents;
+    private MemoryCacheManager mMemoryCacheManager;
+    private MediaResourceManager mMediaResourceManager;
+    private MediaCacheManager mMediaCacheManager;
+    private ContactContentObserver mContactContentObserver;
+    private PhoneUtils mPhoneUtils;
+    private MediaUtil mMediaUtil;
+    private SparseArray<BugleSubscriptionPrefs> mSubscriptionPrefs;
+    private BugleCarrierConfigValuesLoader mCarrierConfigValuesLoader;
+
+    // Cached instance for Pre-L_MR1
+    private static final Object PHONEUTILS_INSTANCE_LOCK = new Object();
+    private static PhoneUtils sPhoneUtilsInstancePreLMR1 = null;
+    // Cached subId->instance for L_MR1 and beyond
+    private static final ConcurrentHashMap<Integer, PhoneUtils> sPhoneUtilsInstanceCacheLMR1 =
+            new ConcurrentHashMap<>();
+
+    private FactoryImpl() {
+    }
+
+    public static Factory register(final Context applicationContext,
+            final BugleApplication application) {
+        // This only gets called once (from BugleApplication.onCreate), but its not called in tests.
+        Assert.isTrue(!sRegistered);
+        Assert.isNull(Factory.get());
+
+        final FactoryImpl factory = new FactoryImpl();
+        Factory.setInstance(factory);
+        sRegistered = true;
+
+        // At this point Factory is published. Services can now get initialized and depend on
+        // Factory.get().
+        factory.mApplication = application;
+        factory.mApplicationContext = applicationContext;
+        factory.mMemoryCacheManager = new MemoryCacheManager();
+        factory.mMediaCacheManager = new BugleMediaCacheManager();
+        factory.mMediaResourceManager = new MediaResourceManager();
+        factory.mBugleGservices = new BugleGservicesImpl(applicationContext);
+        factory.mBugleApplicationPrefs = new BugleApplicationPrefs(applicationContext);
+        factory.mDataModel = new DataModelImpl(applicationContext);
+        factory.mBugleWidgetPrefs = new BugleWidgetPrefs(applicationContext);
+        factory.mUIIntents = new UIIntentsImpl();
+        factory.mContactContentObserver = new ContactContentObserver();
+        factory.mMediaUtil = new MediaUtilImpl();
+        factory.mSubscriptionPrefs = new SparseArray<BugleSubscriptionPrefs>();
+        factory.mCarrierConfigValuesLoader = new BugleCarrierConfigValuesLoader(applicationContext);
+
+        Assert.initializeGservices(factory.mBugleGservices);
+        LogUtil.initializeGservices(factory.mBugleGservices);
+
+        if (OsUtil.hasRequiredPermissions()) {
+            factory.onRequiredPermissionsAcquired();
+        }
+
+        return factory;
+    }
+
+    @Override
+    public void onRequiredPermissionsAcquired() {
+        if (sInitialized) {
+            return;
+        }
+        sInitialized = true;
+
+        mApplication.initializeSync(this);
+
+        final Thread asyncInitialization = new Thread() {
+            @Override
+            public void run() {
+                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                mApplication.initializeAsync(FactoryImpl.this);
+            }
+        };
+        asyncInitialization.start();
+    }
+
+    @Override
+    public Context getApplicationContext() {
+        return mApplicationContext;
+    }
+
+    @Override
+    public DataModel getDataModel() {
+        return mDataModel;
+    }
+
+    @Override
+    public BugleGservices getBugleGservices() {
+        return mBugleGservices;
+    }
+
+    @Override
+    public BuglePrefs getApplicationPrefs() {
+        return mBugleApplicationPrefs;
+    }
+
+    @Override
+    public BuglePrefs getWidgetPrefs() {
+        return mBugleWidgetPrefs;
+    }
+
+    @Override
+    public BuglePrefs getSubscriptionPrefs(int subId) {
+        subId = PhoneUtils.getDefault().getEffectiveSubId(subId);
+        BugleSubscriptionPrefs pref = mSubscriptionPrefs.get(subId);
+        if (pref == null) {
+            synchronized (this) {
+                if ((pref = mSubscriptionPrefs.get(subId)) == null) {
+                    pref = new BugleSubscriptionPrefs(getApplicationContext(), subId);
+                    mSubscriptionPrefs.put(subId, pref);
+                }
+            }
+        }
+        return pref;
+    }
+
+    @Override
+    public UIIntents getUIIntents() {
+        return mUIIntents;
+    }
+
+    @Override
+    public MemoryCacheManager getMemoryCacheManager() {
+        return mMemoryCacheManager;
+    }
+
+    @Override
+    public MediaResourceManager getMediaResourceManager() {
+        return mMediaResourceManager;
+    }
+
+    @Override
+    public MediaCacheManager getMediaCacheManager() {
+        return mMediaCacheManager;
+    }
+
+    @Override
+    public ContactContentObserver getContactContentObserver() {
+        return mContactContentObserver;
+    }
+
+    @Override
+    public PhoneUtils getPhoneUtils(int subId) {
+        if (OsUtil.isAtLeastL_MR1()) {
+            if (subId == ParticipantData.DEFAULT_SELF_SUB_ID) {
+                subId = SmsManager.getDefaultSmsSubscriptionId();
+            }
+            if (subId < 0) {
+                LogUtil.w(LogUtil.BUGLE_TAG, "PhoneUtils.getForLMR1(): invalid subId = " + subId);
+                subId = ParticipantData.DEFAULT_SELF_SUB_ID;
+            }
+            PhoneUtils instance = sPhoneUtilsInstanceCacheLMR1.get(subId);
+            if (instance == null) {
+                instance = new PhoneUtils.PhoneUtilsLMR1(subId);
+                sPhoneUtilsInstanceCacheLMR1.putIfAbsent(subId, instance);
+            }
+            return instance;
+        } else {
+            Assert.isTrue(subId == ParticipantData.DEFAULT_SELF_SUB_ID);
+            if (sPhoneUtilsInstancePreLMR1 == null) {
+                synchronized (PHONEUTILS_INSTANCE_LOCK) {
+                    if (sPhoneUtilsInstancePreLMR1 == null) {
+                        sPhoneUtilsInstancePreLMR1 = new PhoneUtils.PhoneUtilsPreLMR1();
+                    }
+                }
+            }
+            return sPhoneUtilsInstancePreLMR1;
+        }
+    }
+
+    @Override
+    public void reclaimMemory() {
+        mMemoryCacheManager.reclaimMemory();
+    }
+
+    @Override
+    public void onActivityResume() {
+    }
+
+    @Override
+    public MediaUtil getMediaUtil() {
+        return mMediaUtil;
+    }
+
+    @Override
+    public BugleCarrierConfigValuesLoader getCarrierConfigValuesLoader() {
+        return mCarrierConfigValuesLoader;
+    }
+}
diff --git a/src/com/android/messaging/annotation/VisibleForAnimation.java b/src/com/android/messaging/annotation/VisibleForAnimation.java
new file mode 100644
index 0000000..f97d827
--- /dev/null
+++ b/src/com/android/messaging/annotation/VisibleForAnimation.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.annotation;
+
+/**
+ * An annotation for class members that are made visible for Android's ObjectAnimator to work
+ * properly through reflection.
+ */
+public @interface VisibleForAnimation {
+}
diff --git a/src/com/android/messaging/datamodel/BitmapPool.java b/src/com/android/messaging/datamodel/BitmapPool.java
new file mode 100644
index 0000000..1a673ba
--- /dev/null
+++ b/src/com/android/messaging/datamodel/BitmapPool.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import androidx.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.SparseArray;
+
+import com.android.messaging.datamodel.MemoryCacheManager.MemoryCache;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.io.InputStream;
+
+/**
+ * Class for creating / loading / reusing bitmaps. This class allow the user to create a new bitmap,
+ * reuse an bitmap from the pool and to return a bitmap for future reuse.  The pool of bitmaps
+ * allows for faster decode and more efficient memory usage.
+ * Note: consumers should not create BitmapPool directly, but instead get the pool they want from
+ * the BitmapPoolManager.
+ */
+public class BitmapPool implements MemoryCache {
+    public static final int MAX_SUPPORTED_IMAGE_DIMENSION = 0xFFFF;
+
+    protected static final boolean VERBOSE = false;
+
+    /**
+     * Number of reuse failures to skip before reporting.
+     */
+    private static final int FAILED_REPORTING_FREQUENCY = 100;
+
+    /**
+     * Count of reuse failures which have occurred.
+     */
+    private static volatile int sFailedBitmapReuseCount = 0;
+
+    /**
+     * Overall pool data structure which currently only supports rectangular bitmaps. The size of
+     * one of the sides is used to index into the SparseArray.
+     */
+    private final SparseArray<SingleSizePool> mPool;
+    private final Object mPoolLock = new Object();
+    private final String mPoolName;
+    private final int mMaxSize;
+
+    /**
+     * Inner structure which holds a pool of bitmaps all the same size (i.e. all have the same
+     * width as each other and height as each other, but not necessarily the same).
+     */
+    private class SingleSizePool {
+        int mNumItems;
+        final Bitmap[] mBitmaps;
+
+        SingleSizePool(final int maxPoolSize) {
+            mNumItems = 0;
+            mBitmaps = new Bitmap[maxPoolSize];
+        }
+    }
+
+    /**
+     * Creates a pool of reused bitmaps with helper decode methods which will attempt to use the
+     * reclaimed bitmaps. This will help speed up the creation of bitmaps by using already allocated
+     * bitmaps.
+     * @param maxSize The overall max size of the pool. When the pool exceeds this size, all calls
+     * to reclaimBitmap(Bitmap) will result in recycling the bitmap.
+     * @param name Name of the bitmap pool and only used for logging. Can not be null.
+     */
+    BitmapPool(final int maxSize, @NonNull final String name) {
+        Assert.isTrue(maxSize > 0);
+        Assert.isTrue(!TextUtils.isEmpty(name));
+        mPoolName = name;
+        mMaxSize = maxSize;
+        mPool = new SparseArray<SingleSizePool>();
+    }
+
+    @Override
+    public void reclaim() {
+        synchronized (mPoolLock) {
+            for (int p = 0; p < mPool.size(); p++) {
+                final SingleSizePool singleSizePool = mPool.valueAt(p);
+                for (int i = 0; i < singleSizePool.mNumItems; i++) {
+                    singleSizePool.mBitmaps[i].recycle();
+                    singleSizePool.mBitmaps[i] = null;
+                }
+                singleSizePool.mNumItems = 0;
+            }
+            mPool.clear();
+        }
+    }
+
+    /**
+     * Creates a new BitmapFactory.Options.
+     */
+    public static BitmapFactory.Options getBitmapOptionsForPool(final boolean scaled,
+            final int inputDensity, final int targetDensity) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inScaled = scaled;
+        options.inDensity = inputDensity;
+        options.inTargetDensity = targetDensity;
+        options.inSampleSize = 1;
+        options.inJustDecodeBounds = false;
+        options.inMutable = true;
+        return options;
+    }
+
+    /**
+     * @return The pool key for the provided image dimensions or 0 if either width or height is
+     * greater than the max supported image dimension.
+     */
+    private int getPoolKey(final int width, final int height) {
+        if (width > MAX_SUPPORTED_IMAGE_DIMENSION || height > MAX_SUPPORTED_IMAGE_DIMENSION) {
+            return 0;
+        }
+        return (width << 16) | height;
+    }
+
+    /**
+     *
+     * @return A bitmap in the pool with the specified dimensions or null if no bitmap with the
+     * specified dimension is available.
+     */
+    private Bitmap findPoolBitmap(final int width, final int height) {
+        final int poolKey = getPoolKey(width, height);
+        if (poolKey != 0) {
+            synchronized (mPoolLock) {
+                // Take a bitmap from the pool if one is available
+                final SingleSizePool singlePool = mPool.get(poolKey);
+                if (singlePool != null && singlePool.mNumItems > 0) {
+                    singlePool.mNumItems--;
+                    final Bitmap foundBitmap = singlePool.mBitmaps[singlePool.mNumItems];
+                    singlePool.mBitmaps[singlePool.mNumItems] = null;
+                    return foundBitmap;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Internal function to try and find a bitmap in the pool which matches the desired width and
+     * height and then set that in the bitmap options properly.
+     *
+     * TODO: Why do we take a width/height? Shouldn't this already be in the
+     * BitmapFactory.Options instance? Can we assert that they match?
+     * @param optionsTmp The BitmapFactory.Options to update with the bitmap for the system to try
+     * to reuse.
+     * @param width The width of the reusable bitmap.
+     * @param height The height of the reusable bitmap.
+     */
+    private void assignPoolBitmap(final BitmapFactory.Options optionsTmp, final int width,
+            final int height) {
+        if (optionsTmp.inJustDecodeBounds) {
+            return;
+        }
+        optionsTmp.inBitmap = findPoolBitmap(width, height);
+    }
+
+    /**
+     * Load a resource into a bitmap. Uses a bitmap from the pool if possible to reduce memory
+     * turnover.
+     * @param resourceId Resource id to load.
+     * @param resources Application resources. Cannot be null.
+     * @param optionsTmp Should be the same options returned from getBitmapOptionsForPool(). Cannot
+     * be null.
+     * @param width The width of the bitmap.
+     * @param height The height of the bitmap.
+     * @return The decoded Bitmap with the resource drawn in it.
+     */
+    public Bitmap decodeSampledBitmapFromResource(final int resourceId,
+            @NonNull final Resources resources, @NonNull final BitmapFactory.Options optionsTmp,
+            final int width, final int height) {
+        Assert.notNull(resources);
+        Assert.notNull(optionsTmp);
+        Assert.isTrue(width > 0);
+        Assert.isTrue(height > 0);
+        assignPoolBitmap(optionsTmp, width, height);
+        Bitmap b = null;
+        try {
+            b = BitmapFactory.decodeResource(resources, resourceId, optionsTmp);
+        } catch (final IllegalArgumentException e) {
+            // BitmapFactory couldn't decode the file, try again without an inputBufferBitmap.
+            if (optionsTmp.inBitmap != null) {
+                optionsTmp.inBitmap = null;
+                b = BitmapFactory.decodeResource(resources, resourceId, optionsTmp);
+                sFailedBitmapReuseCount++;
+                if (sFailedBitmapReuseCount % FAILED_REPORTING_FREQUENCY == 0) {
+                    LogUtil.w(LogUtil.BUGLE_TAG,
+                            "Pooled bitmap consistently not being reused count = " +
+                            sFailedBitmapReuseCount);
+                }
+            }
+        } catch (final OutOfMemoryError e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Oom decoding resource " + resourceId);
+            reclaim();
+        }
+        return b;
+    }
+
+    /**
+     * Load an input stream into a bitmap. Uses a bitmap from the pool if possible to reduce memory
+     * turnover.
+     * @param inputStream InputStream load. Cannot be null.
+     * @param optionsTmp Should be the same options returned from getBitmapOptionsForPool(). Cannot
+     * be null.
+     * @param width The width of the bitmap.
+     * @param height The height of the bitmap.
+     * @return The decoded Bitmap with the resource drawn in it.
+     */
+    public Bitmap decodeSampledBitmapFromInputStream(@NonNull final InputStream inputStream,
+            @NonNull final BitmapFactory.Options optionsTmp,
+            final int width, final int height) {
+        Assert.notNull(inputStream);
+        Assert.isTrue(width > 0);
+        Assert.isTrue(height > 0);
+        assignPoolBitmap(optionsTmp, width, height);
+        Bitmap b = null;
+        try {
+            b = BitmapFactory.decodeStream(inputStream, null, optionsTmp);
+        } catch (final IllegalArgumentException e) {
+            // BitmapFactory couldn't decode the file, try again without an inputBufferBitmap.
+            if (optionsTmp.inBitmap != null) {
+                optionsTmp.inBitmap = null;
+                b = BitmapFactory.decodeStream(inputStream, null, optionsTmp);
+                sFailedBitmapReuseCount++;
+                if (sFailedBitmapReuseCount % FAILED_REPORTING_FREQUENCY == 0) {
+                    LogUtil.w(LogUtil.BUGLE_TAG,
+                            "Pooled bitmap consistently not being reused count = " +
+                            sFailedBitmapReuseCount);
+                }
+            }
+        } catch (final OutOfMemoryError e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Oom decoding inputStream");
+            reclaim();
+        }
+        return b;
+    }
+
+    /**
+     * Turn encoded bytes into a bitmap. Uses a bitmap from the pool if possible to reduce memory
+     * turnover.
+     * @param bytes Encoded bytes to draw on the bitmap. Cannot be null.
+     * @param optionsTmp The bitmap will set here and the input should be generated from
+     * getBitmapOptionsForPool(). Cannot be null.
+     * @param width The width of the bitmap.
+     * @param height The height of the bitmap.
+     * @return A Bitmap with the encoded bytes drawn in it.
+     */
+    public Bitmap decodeByteArray(@NonNull final byte[] bytes,
+            @NonNull final BitmapFactory.Options optionsTmp, final int width,
+            final int height) throws OutOfMemoryError {
+        Assert.notNull(bytes);
+        Assert.notNull(optionsTmp);
+        Assert.isTrue(width > 0);
+        Assert.isTrue(height > 0);
+        assignPoolBitmap(optionsTmp, width, height);
+        Bitmap b = null;
+        try {
+            b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, optionsTmp);
+        } catch (final IllegalArgumentException e) {
+            if (VERBOSE) {
+                LogUtil.v(LogUtil.BUGLE_TAG, "BitmapPool(" + mPoolName +
+                        ") Unable to use pool bitmap");
+            }
+            // BitmapFactory couldn't decode the file, try again without an inputBufferBitmap.
+            // (i.e. without the bitmap from the pool)
+            if (optionsTmp.inBitmap != null) {
+                optionsTmp.inBitmap = null;
+                b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, optionsTmp);
+                sFailedBitmapReuseCount++;
+                if (sFailedBitmapReuseCount % FAILED_REPORTING_FREQUENCY == 0) {
+                    LogUtil.w(LogUtil.BUGLE_TAG,
+                            "Pooled bitmap consistently not being reused count = " +
+                            sFailedBitmapReuseCount);
+                }
+            }
+        }
+        return b;
+    }
+
+    /**
+     * Creates a bitmap with the given size, this will reuse a bitmap in the pool, if one is
+     * available, otherwise this will create a new one.
+     * @param width The desired width of the bitmap.
+     * @param height The desired height of the bitmap.
+     * @return A bitmap with the desired width and height, this maybe a reused bitmap from the pool.
+     */
+    public Bitmap createOrReuseBitmap(final int width, final int height) {
+        Bitmap b = findPoolBitmap(width, height);
+        if (b == null) {
+            b = createBitmap(width, height);
+        }
+        return b;
+    }
+
+    /**
+     * This will create a new bitmap regardless of pool state.
+     * @param width The desired width of the bitmap.
+     * @param height The desired height of the bitmap.
+     * @return A bitmap with the desired width and height.
+     */
+    private Bitmap createBitmap(final int width, final int height) {
+        return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+    }
+
+    /**
+     * Called when a bitmap is finished being used so that it can be used for another bitmap in the
+     * future or recycled. Any bitmaps returned should not be used by the caller again.
+     * @param b The bitmap to return to the pool for future usage or recycled. This cannot be null.
+     */
+    public void reclaimBitmap(@NonNull final Bitmap b) {
+        Assert.notNull(b);
+        final int poolKey = getPoolKey(b.getWidth(), b.getHeight());
+        if (poolKey == 0 || !b.isMutable()) {
+            // Unsupported image dimensions or a immutable bitmap.
+            b.recycle();
+            return;
+        }
+        synchronized (mPoolLock) {
+            SingleSizePool singleSizePool = mPool.get(poolKey);
+            if (singleSizePool == null) {
+                singleSizePool = new SingleSizePool(mMaxSize);
+                mPool.append(poolKey, singleSizePool);
+            }
+            if (singleSizePool.mNumItems < singleSizePool.mBitmaps.length) {
+                singleSizePool.mBitmaps[singleSizePool.mNumItems] = b;
+                singleSizePool.mNumItems++;
+            } else {
+                b.recycle();
+            }
+        }
+    }
+
+    /**
+     * @return whether the pool is full for a given width and height.
+     */
+    public boolean isFull(final int width, final int height) {
+        final int poolKey = getPoolKey(width, height);
+        synchronized (mPoolLock) {
+            final SingleSizePool singleSizePool = mPool.get(poolKey);
+            if (singleSizePool != null &&
+                    singleSizePool.mNumItems >= singleSizePool.mBitmaps.length) {
+                return true;
+            }
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/BoundCursorLoader.java b/src/com/android/messaging/datamodel/BoundCursorLoader.java
new file mode 100644
index 0000000..84d38e6
--- /dev/null
+++ b/src/com/android/messaging/datamodel/BoundCursorLoader.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.net.Uri;
+
+/**
+ * Extension to basic cursor loader that has an attached binding id
+ */
+public class BoundCursorLoader extends CursorLoader {
+    private final String mBindingId;
+
+    /**
+     * Create cursor loader for associated binding id
+     */
+    public BoundCursorLoader(final String bindingId, final Context context, final Uri uri,
+            final String[] projection, final String selection, final String[] selectionArgs,
+            final String sortOrder) {
+        super(context, uri, projection, selection, selectionArgs, sortOrder);
+        mBindingId = bindingId;
+    }
+
+    /**
+     * Binding id associated with this loader - consume can check to verify data still valid
+     * @return
+     */
+    public String getBindingId() {
+        return mBindingId;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/BugleDatabaseOperations.java b/src/com/android/messaging/datamodel/BugleDatabaseOperations.java
new file mode 100644
index 0000000..c4e5fb8
--- /dev/null
+++ b/src/com/android/messaging/datamodel/BugleDatabaseOperations.java
@@ -0,0 +1,1924 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDoneException;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import androidx.collection.ArrayMap;
+import androidx.collection.SimpleArrayMap;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.ParticipantRefresh.ConversationParticipantsQuery;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.UriUtil;
+import com.android.messaging.widget.WidgetConversationProvider;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import javax.annotation.Nullable;
+
+
+/**
+ * This class manages updating our local database
+ */
+public class BugleDatabaseOperations {
+
+    private static final String TAG = LogUtil.BUGLE_DATABASE_TAG;
+
+    // Global cache of phone numbers -> participant id mapping since this call is expensive.
+    private static final ArrayMap<String, String> sNormalizedPhoneNumberToParticipantIdCache =
+            new ArrayMap<String, String>();
+
+    /**
+     * Convert list of recipient strings (email/phone number) into list of ConversationParticipants
+     *
+     * @param recipients The recipient list
+     * @param refSubId The subId used to normalize phone numbers in the recipients
+     */
+    static ArrayList<ParticipantData> getConversationParticipantsFromRecipients(
+            final List<String> recipients, final int refSubId) {
+        // Generate a list of partially formed participants
+        final ArrayList<ParticipantData> participants = new
+                ArrayList<ParticipantData>();
+
+        if (recipients != null) {
+            for (final String recipient : recipients) {
+                participants.add(ParticipantData.getFromRawPhoneBySimLocale(recipient, refSubId));
+            }
+        }
+        return participants;
+    }
+
+    /**
+     * Sanitize a given list of conversation participants by de-duping and stripping out self
+     * phone number in group conversation.
+     */
+    @DoesNotRunOnMainThread
+    public static void sanitizeConversationParticipants(final List<ParticipantData> participants) {
+        Assert.isNotMainThread();
+        if (participants.size() > 0) {
+            // First remove redundant phone numbers
+            final HashSet<String> recipients = new HashSet<String>();
+            for (int i = participants.size() - 1; i >= 0; i--) {
+                final String recipient = participants.get(i).getNormalizedDestination();
+                if (!recipients.contains(recipient)) {
+                    recipients.add(recipient);
+                } else {
+                    participants.remove(i);
+                }
+            }
+            if (participants.size() > 1) {
+                // Remove self phone number from group conversation.
+                final HashSet<String> selfNumbers =
+                        PhoneUtils.getDefault().getNormalizedSelfNumbers();
+                int removed = 0;
+                // Do this two-pass scan to avoid unnecessary memory allocation.
+                // Prescan to count the self numbers in the list
+                for (final ParticipantData p : participants) {
+                    if (selfNumbers.contains(p.getNormalizedDestination())) {
+                        removed++;
+                    }
+                }
+                // If all are self numbers, maybe that's what the user wants, just leave
+                // the participants as is. Otherwise, do another scan to remove self numbers.
+                if (removed < participants.size()) {
+                    for (int i = participants.size() - 1; i >= 0; i--) {
+                        final String recipient = participants.get(i).getNormalizedDestination();
+                        if (selfNumbers.contains(recipient)) {
+                            participants.remove(i);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Convert list of ConversationParticipants into recipient strings (email/phone number)
+     */
+    @DoesNotRunOnMainThread
+    public static ArrayList<String> getRecipientsFromConversationParticipants(
+            final List<ParticipantData> participants) {
+        Assert.isNotMainThread();
+        // First find the thread id for this list of participants.
+        final ArrayList<String> recipients = new ArrayList<String>();
+
+        for (final ParticipantData participant : participants) {
+            recipients.add(participant.getSendDestination());
+        }
+        return recipients;
+    }
+
+    /**
+     * Get or create a conversation based on the message's thread id
+     *
+     * NOTE: There are phones on which you can't get the recipients from the thread id for SMS
+     * until you have a message, so use getOrCreateConversationFromRecipient instead.
+     *
+     * TODO: Should this be in MMS/SMS code?
+     *
+     * @param db the database
+     * @param threadId The message's thread
+     * @param senderBlocked Flag whether sender of message is in blocked people list
+     * @param refSubId The reference subId for canonicalize phone numbers
+     * @return conversationId
+     */
+    @DoesNotRunOnMainThread
+    public static String getOrCreateConversationFromThreadId(final DatabaseWrapper db,
+            final long threadId, final boolean senderBlocked, final int refSubId) {
+        Assert.isNotMainThread();
+        final List<String> recipients = MmsUtils.getRecipientsByThread(threadId);
+        final ArrayList<ParticipantData> participants =
+                getConversationParticipantsFromRecipients(recipients, refSubId);
+
+        return getOrCreateConversation(db, threadId, senderBlocked, participants, false, false,
+                null);
+    }
+
+    /**
+     * Get or create a conversation based on provided recipient
+     *
+     * @param db the database
+     * @param threadId The message's thread
+     * @param senderBlocked Flag whether sender of message is in blocked people list
+     * @param recipient recipient for thread
+     * @return conversationId
+     */
+    @DoesNotRunOnMainThread
+    public static String getOrCreateConversationFromRecipient(final DatabaseWrapper db,
+            final long threadId, final boolean senderBlocked, final ParticipantData recipient) {
+        Assert.isNotMainThread();
+        final ArrayList<ParticipantData> recipients = new ArrayList<>(1);
+        recipients.add(recipient);
+        return getOrCreateConversation(db, threadId, senderBlocked, recipients, false, false, null);
+    }
+
+    /**
+     * Get or create a conversation based on provided participants
+     *
+     * @param db the database
+     * @param threadId The message's thread
+     * @param archived Flag whether the conversation should be created archived
+     * @param participants list of conversation participants
+     * @param noNotification If notification should be disabled
+     * @param noVibrate If vibrate on notification should be disabled
+     * @param soundUri If there is custom sound URI
+     * @return a conversation id
+     */
+    @DoesNotRunOnMainThread
+    public static String getOrCreateConversation(final DatabaseWrapper db, final long threadId,
+            final boolean archived, final ArrayList<ParticipantData> participants,
+            boolean noNotification, boolean noVibrate, String soundUri) {
+        Assert.isNotMainThread();
+
+        // Check to see if this conversation is already in out local db cache
+        String conversationId = BugleDatabaseOperations.getExistingConversation(db, threadId,
+                false);
+
+        if (conversationId == null) {
+            final String conversationName = ConversationListItemData.generateConversationName(
+                    participants);
+
+            // Create the conversation with the default self participant which always maps to
+            // the system default subscription.
+            final ParticipantData self = ParticipantData.getSelfParticipant(
+                    ParticipantData.DEFAULT_SELF_SUB_ID);
+
+            db.beginTransaction();
+            try {
+                // Look up the "self" participantId (creating if necessary)
+                final String selfId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+                // Create a new conversation
+                conversationId = BugleDatabaseOperations.createConversationInTransaction(
+                        db, threadId, conversationName, selfId, participants, archived,
+                        noNotification, noVibrate, soundUri);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+        }
+
+        return conversationId;
+    }
+
+    /**
+     * Get a conversation from the local DB based on the message's thread id.
+     *
+     * @param dbWrapper     The database
+     * @param threadId      The message's thread in the SMS database
+     * @param senderBlocked Flag whether sender of message is in blocked people list
+     * @return The existing conversation id or null
+     */
+    @VisibleForTesting
+    @DoesNotRunOnMainThread
+    public static String getExistingConversation(final DatabaseWrapper dbWrapper,
+            final long threadId, final boolean senderBlocked) {
+        Assert.isNotMainThread();
+        String conversationId = null;
+
+        Cursor cursor = null;
+        try {
+            // Look for an existing conversation in the db with this thread id
+            cursor = dbWrapper.rawQuery("SELECT " + ConversationColumns._ID
+                            + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE
+                            + " WHERE " + ConversationColumns.SMS_THREAD_ID + "=" + threadId,
+                    null);
+
+            if (cursor.moveToFirst()) {
+                Assert.isTrue(cursor.getCount() == 1);
+                conversationId = cursor.getString(0);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return conversationId;
+    }
+
+    /**
+     * Get the thread id for an existing conversation from the local DB.
+     *
+     * @param dbWrapper The database
+     * @param conversationId The conversation to look up thread for
+     * @return The thread id. Returns -1 if the conversation was not found or if it was found
+     * but the thread column was NULL.
+     */
+    @DoesNotRunOnMainThread
+    public static long getThreadId(final DatabaseWrapper dbWrapper, final String conversationId) {
+        Assert.isNotMainThread();
+        long threadId = -1;
+
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { ConversationColumns.SMS_THREAD_ID },
+                    ConversationColumns._ID + " =?",
+                    new String[] { conversationId },
+                    null, null, null);
+
+            if (cursor.moveToFirst()) {
+                Assert.isTrue(cursor.getCount() == 1);
+                if (!cursor.isNull(0)) {
+                    threadId = cursor.getLong(0);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return threadId;
+    }
+
+    @DoesNotRunOnMainThread
+    public static boolean isBlockedDestination(final DatabaseWrapper db, final String destination) {
+        Assert.isNotMainThread();
+        return isBlockedParticipant(db, destination, ParticipantColumns.NORMALIZED_DESTINATION);
+    }
+
+    static boolean isBlockedParticipant(final DatabaseWrapper db, final String participantId) {
+        return isBlockedParticipant(db, participantId, ParticipantColumns._ID);
+    }
+
+    static boolean isBlockedParticipant(final DatabaseWrapper db, final String value,
+            final String column) {
+        Cursor cursor = null;
+        try {
+            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    new String[] { ParticipantColumns.BLOCKED },
+                    column + "=? AND " + ParticipantColumns.SUB_ID + "=?",
+                    new String[] { value,
+                    Integer.toString(ParticipantData.OTHER_THAN_SELF_SUB_ID) },
+                    null, null, null);
+
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                return cursor.getInt(0) == 1;
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return false;  // if there's no row, it's not blocked :-)
+    }
+
+    /**
+     * Create a conversation in the local DB based on the message's thread id.
+     *
+     * It's up to the caller to make sure that this is all inside a transaction.  It will return
+     * null if it's not in the local DB.
+     *
+     * @param dbWrapper     The database
+     * @param threadId      The message's thread
+     * @param selfId        The selfId to make default for this conversation
+     * @param archived      Flag whether the conversation should be created archived
+     * @param noNotification If notification should be disabled
+     * @param noVibrate     If vibrate on notification should be disabled
+     * @param soundUri      The customized sound
+     * @return The existing conversation id or new conversation id
+     */
+    static String createConversationInTransaction(final DatabaseWrapper dbWrapper,
+            final long threadId, final String conversationName, final String selfId,
+            final List<ParticipantData> participants, final boolean archived,
+            boolean noNotification, boolean noVibrate, String soundUri) {
+        // We want conversation and participant creation to be atomic
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        boolean hasEmailAddress = false;
+        for (final ParticipantData participant : participants) {
+            Assert.isTrue(!participant.isSelf());
+            if (participant.isEmail()) {
+                hasEmailAddress = true;
+            }
+        }
+
+        // TODO : Conversations state - normal vs. archived
+
+        // Insert a new local conversation for this thread id
+        final ContentValues values = new ContentValues();
+        values.put(ConversationColumns.SMS_THREAD_ID, threadId);
+        // Start with conversation hidden - sending a message or saving a draft will change that
+        values.put(ConversationColumns.SORT_TIMESTAMP, 0L);
+        values.put(ConversationColumns.CURRENT_SELF_ID, selfId);
+        values.put(ConversationColumns.PARTICIPANT_COUNT, participants.size());
+        values.put(ConversationColumns.INCLUDE_EMAIL_ADDRESS, (hasEmailAddress ? 1 : 0));
+        if (archived) {
+            values.put(ConversationColumns.ARCHIVE_STATUS, 1);
+        }
+        if (noNotification) {
+            values.put(ConversationColumns.NOTIFICATION_ENABLED, 0);
+        }
+        if (noVibrate) {
+            values.put(ConversationColumns.NOTIFICATION_VIBRATION, 0);
+        }
+        if (!TextUtils.isEmpty(soundUri)) {
+            values.put(ConversationColumns.NOTIFICATION_SOUND_URI, soundUri);
+        }
+
+        fillParticipantData(values, participants);
+
+        final long conversationRowId = dbWrapper.insert(DatabaseHelper.CONVERSATIONS_TABLE, null,
+                values);
+
+        Assert.isTrue(conversationRowId != -1);
+        if (conversationRowId == -1) {
+            LogUtil.e(TAG, "BugleDatabaseOperations : failed to insert conversation into table");
+            return null;
+        }
+
+        final String conversationId = Long.toString(conversationRowId);
+
+        // Make sure that participants are added for this conversation
+        for (final ParticipantData participant : participants) {
+            // TODO: Use blocking information
+            addParticipantToConversation(dbWrapper, participant, conversationId);
+        }
+
+        // Now fully resolved participants available can update conversation name / avatar.
+        // b/16437575: We cannot use the participants directly, but instead have to call
+        // getParticipantsForConversation() to retrieve the actual participants. This is needed
+        // because the call to addParticipantToConversation() won't fill up the ParticipantData
+        // if the participant already exists in the participant table. For example, say you have
+        // an existing conversation with John. Now if you create a new group conversation with
+        // Jeff & John with only their phone numbers, then when we try to add John's number to the
+        // group conversation, we see that he's already in the participant table, therefore we
+        // short-circuit any steps to actually fill out the ParticipantData for John other than
+        // just returning his participant id. Eventually, the ParticipantData we have is still the
+        // raw data with just the phone number. getParticipantsForConversation(), on the other
+        // hand, will fill out all the info for each participant from the participants table.
+        updateConversationNameAndAvatarInTransaction(dbWrapper, conversationId,
+                getParticipantsForConversation(dbWrapper, conversationId));
+
+        return conversationId;
+    }
+
+    private static void fillParticipantData(final ContentValues values,
+            final List<ParticipantData> participants) {
+        if (participants != null && !participants.isEmpty()) {
+            final Uri avatarUri = AvatarUriUtil.createAvatarUri(participants);
+            values.put(ConversationColumns.ICON, avatarUri.toString());
+
+            long contactId;
+            String lookupKey;
+            String destination;
+            if (participants.size() == 1) {
+                final ParticipantData firstParticipant = participants.get(0);
+                contactId = firstParticipant.getContactId();
+                lookupKey = firstParticipant.getLookupKey();
+                destination = firstParticipant.getNormalizedDestination();
+            } else {
+                contactId = 0;
+                lookupKey = null;
+                destination = null;
+            }
+
+            values.put(ConversationColumns.PARTICIPANT_CONTACT_ID, contactId);
+            values.put(ConversationColumns.PARTICIPANT_LOOKUP_KEY, lookupKey);
+            values.put(ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION, destination);
+        }
+    }
+
+    /**
+     * Delete conversation and associated messages/parts
+     */
+    @DoesNotRunOnMainThread
+    public static boolean deleteConversation(final DatabaseWrapper dbWrapper,
+            final String conversationId, final long cutoffTimestamp) {
+        Assert.isNotMainThread();
+        dbWrapper.beginTransaction();
+        boolean conversationDeleted = false;
+        boolean conversationMessagesDeleted = false;
+        try {
+            // Delete existing messages
+            if (cutoffTimestamp == Long.MAX_VALUE) {
+                // Delete parts and messages
+                dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE,
+                        MessageColumns.CONVERSATION_ID + "=?", new String[] { conversationId });
+                conversationMessagesDeleted = true;
+            } else {
+                // Delete all messages prior to the cutoff
+                dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE,
+                        MessageColumns.CONVERSATION_ID + "=? AND "
+                                + MessageColumns.RECEIVED_TIMESTAMP + "<=?",
+                                new String[] { conversationId, Long.toString(cutoffTimestamp) });
+
+                // Delete any draft message. The delete above may not always include the draft,
+                // because under certain scenarios (e.g. sending messages in progress), the draft
+                // timestamp can be larger than the cutoff time, which is generally the conversation
+                // sort timestamp. Because of how the sms/mms provider works on some newer
+                // devices, it's important that we never delete all the messages in a conversation
+                // without also deleting the conversation itself (see b/20262204 for details).
+                dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE,
+                        MessageColumns.STATUS + "=? AND " + MessageColumns.CONVERSATION_ID + "=?",
+                        new String[] {
+                            Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_DRAFT),
+                            conversationId
+                        });
+
+                // Check to see if there are any messages left in the conversation
+                final long count = dbWrapper.queryNumEntries(DatabaseHelper.MESSAGES_TABLE,
+                        MessageColumns.CONVERSATION_ID + "=?", new String[] { conversationId });
+                conversationMessagesDeleted = (count == 0);
+
+                // Log detail information if there are still messages left in the conversation
+                if (!conversationMessagesDeleted) {
+                    final long maxTimestamp =
+                            getConversationMaxTimestamp(dbWrapper, conversationId);
+                    LogUtil.w(TAG, "BugleDatabaseOperations:"
+                            + " cannot delete all messages in a conversation"
+                            + ", after deletion: count=" + count
+                            + ", max timestamp=" + maxTimestamp
+                            + ", cutoff timestamp=" + cutoffTimestamp);
+                }
+            }
+
+            if (conversationMessagesDeleted) {
+                // Delete conversation row
+                final int count = dbWrapper.delete(DatabaseHelper.CONVERSATIONS_TABLE,
+                        ConversationColumns._ID + "=?", new String[] { conversationId });
+                conversationDeleted = (count > 0);
+            }
+            dbWrapper.setTransactionSuccessful();
+        } finally {
+            dbWrapper.endTransaction();
+        }
+        return conversationDeleted;
+    }
+
+    private static final String MAX_RECEIVED_TIMESTAMP =
+            "MAX(" + MessageColumns.RECEIVED_TIMESTAMP + ")";
+    /**
+     * Get the max received timestamp of a conversation's messages
+     */
+    private static long getConversationMaxTimestamp(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        final Cursor cursor = dbWrapper.query(
+                DatabaseHelper.MESSAGES_TABLE,
+                new String[]{ MAX_RECEIVED_TIMESTAMP },
+                MessageColumns.CONVERSATION_ID + "=?",
+                new String[]{ conversationId },
+                null, null, null);
+        if (cursor != null) {
+            try {
+                if (cursor.moveToFirst()) {
+                    return cursor.getLong(0);
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+        return 0;
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateConversationMetadataInTransaction(final DatabaseWrapper dbWrapper,
+            final String conversationId, final String messageId, final long latestTimestamp,
+            final boolean keepArchived, final String smsServiceCenter,
+            final boolean shouldAutoSwitchSelfId) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+
+        final ContentValues values = new ContentValues();
+        values.put(ConversationColumns.LATEST_MESSAGE_ID, messageId);
+        values.put(ConversationColumns.SORT_TIMESTAMP, latestTimestamp);
+        if (!TextUtils.isEmpty(smsServiceCenter)) {
+            values.put(ConversationColumns.SMS_SERVICE_CENTER, smsServiceCenter);
+        }
+
+        // When the conversation gets updated with new messages, unarchive the conversation unless
+        // the sender is blocked, or we have been told to keep it archived.
+        if (!keepArchived) {
+            values.put(ConversationColumns.ARCHIVE_STATUS, 0);
+        }
+
+        final MessageData message = readMessage(dbWrapper, messageId);
+        addSnippetTextAndPreviewToContentValues(message, false /* showDraft */, values);
+
+        if (shouldAutoSwitchSelfId) {
+            addSelfIdAutoSwitchInfoToContentValues(dbWrapper, message, conversationId, values);
+        }
+
+        // Conversation always exists as this method is called from ActionService only after
+        // reading and if necessary creating the conversation.
+        updateConversationRow(dbWrapper, conversationId, values);
+
+        if (shouldAutoSwitchSelfId && OsUtil.isAtLeastL_MR1()) {
+            // Normally, the draft message compose UI trusts its UI state for providing up-to-date
+            // conversation self id. Therefore, notify UI through local broadcast receiver about
+            // this external change so the change can be properly reflected.
+            UIIntents.get().broadcastConversationSelfIdChange(dbWrapper.getContext(),
+                    conversationId, getConversationSelfId(dbWrapper, conversationId));
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateConversationMetadataInTransaction(final DatabaseWrapper db,
+            final String conversationId, final String messageId, final long latestTimestamp,
+            final boolean keepArchived, final boolean shouldAutoSwitchSelfId) {
+        Assert.isNotMainThread();
+        updateConversationMetadataInTransaction(
+                db, conversationId, messageId, latestTimestamp, keepArchived, null,
+                shouldAutoSwitchSelfId);
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateConversationArchiveStatusInTransaction(final DatabaseWrapper dbWrapper,
+            final String conversationId, final boolean isArchived) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        final ContentValues values = new ContentValues();
+        values.put(ConversationColumns.ARCHIVE_STATUS, isArchived ? 1 : 0);
+        updateConversationRowIfExists(dbWrapper, conversationId, values);
+    }
+
+    static void addSnippetTextAndPreviewToContentValues(final MessageData message,
+            final boolean showDraft, final ContentValues values) {
+        values.put(ConversationColumns.SHOW_DRAFT, showDraft ? 1 : 0);
+        values.put(ConversationColumns.SNIPPET_TEXT, message.getMessageText());
+        values.put(ConversationColumns.SUBJECT_TEXT, message.getMmsSubject());
+
+        String type = null;
+        String uriString = null;
+        for (final MessagePartData part : message.getParts()) {
+            if (part.isAttachment() &&
+                    ContentType.isConversationListPreviewableType(part.getContentType())) {
+                uriString = part.getContentUri().toString();
+                type = part.getContentType();
+                break;
+            }
+        }
+        values.put(ConversationColumns.PREVIEW_CONTENT_TYPE, type);
+        values.put(ConversationColumns.PREVIEW_URI, uriString);
+    }
+
+    /**
+     * Adds self-id auto switch info for a conversation if the last message has a different
+     * subscription than the conversation's.
+     * @return true if self id will need to be changed, false otherwise.
+     */
+    static boolean addSelfIdAutoSwitchInfoToContentValues(final DatabaseWrapper dbWrapper,
+            final MessageData message, final String conversationId, final ContentValues values) {
+        // Only auto switch conversation self for incoming messages.
+        if (!OsUtil.isAtLeastL_MR1() || !message.getIsIncoming()) {
+            return false;
+        }
+
+        final String conversationSelfId = getConversationSelfId(dbWrapper, conversationId);
+        final String messageSelfId = message.getSelfId();
+
+        if (conversationSelfId == null || messageSelfId == null) {
+            return false;
+        }
+
+        // Get the sub IDs in effect for both the message and the conversation and compare them:
+        // 1. If message is unbound (using default sub id), then the message was sent with
+        //    pre-MSIM support. Don't auto-switch because we don't know the subscription for the
+        //    message.
+        // 2. If message is bound,
+        //    i. If conversation is unbound, use the system default sub id as its effective sub.
+        //    ii. If conversation is bound, use its subscription directly.
+        //    Compare the message sub id with the conversation's effective sub id. If they are
+        //    different, auto-switch the conversation to the message's sub.
+        final ParticipantData conversationSelf = getExistingParticipant(dbWrapper,
+                conversationSelfId);
+        final ParticipantData messageSelf = getExistingParticipant(dbWrapper, messageSelfId);
+        if (!messageSelf.isActiveSubscription()) {
+            // Don't switch if the message subscription is no longer active.
+            return false;
+        }
+        final int messageSubId = messageSelf.getSubId();
+        if (messageSubId == ParticipantData.DEFAULT_SELF_SUB_ID) {
+            return false;
+        }
+
+        final int conversationEffectiveSubId =
+                PhoneUtils.getDefault().getEffectiveSubId(conversationSelf.getSubId());
+
+        if (conversationEffectiveSubId != messageSubId) {
+            return addConversationSelfIdToContentValues(dbWrapper, messageSelf.getId(), values);
+        }
+        return false;
+    }
+
+    /**
+     * Adds conversation self id updates to ContentValues given. This performs check on the selfId
+     * to ensure it's valid and active.
+     * @return true if self id will need to be changed, false otherwise.
+     */
+    static boolean addConversationSelfIdToContentValues(final DatabaseWrapper dbWrapper,
+            final String selfId, final ContentValues values) {
+        // Make sure the selfId passed in is valid and active.
+        final String selection = ParticipantColumns._ID + "=? AND " +
+                ParticipantColumns.SIM_SLOT_ID + "<>?";
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    new String[] { ParticipantColumns._ID }, selection,
+                    new String[] { selfId, String.valueOf(ParticipantData.INVALID_SLOT_ID) },
+                    null, null, null);
+
+            if (cursor != null && cursor.getCount() > 0) {
+                values.put(ConversationColumns.CURRENT_SELF_ID, selfId);
+                return true;
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return false;
+    }
+
+    private static void updateConversationDraftSnippetAndPreviewInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId,
+            final MessageData draftMessage) {
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+
+        long sortTimestamp = 0L;
+        Cursor cursor = null;
+        try {
+            // Check to find the latest message in the conversation
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    REFRESH_CONVERSATION_MESSAGE_PROJECTION,
+                    MessageColumns.CONVERSATION_ID + "=?",
+                    new String[]{conversationId}, null, null,
+                    MessageColumns.RECEIVED_TIMESTAMP + " DESC", "1" /* limit */);
+
+            if (cursor.moveToFirst()) {
+                sortTimestamp = cursor.getLong(1);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+
+        final ContentValues values = new ContentValues();
+        if (draftMessage == null || !draftMessage.hasContent()) {
+            values.put(ConversationColumns.SHOW_DRAFT, 0);
+            values.put(ConversationColumns.DRAFT_SNIPPET_TEXT, "");
+            values.put(ConversationColumns.DRAFT_SUBJECT_TEXT, "");
+            values.put(ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE, "");
+            values.put(ConversationColumns.DRAFT_PREVIEW_URI, "");
+        } else {
+            sortTimestamp = Math.max(sortTimestamp, draftMessage.getReceivedTimeStamp());
+            values.put(ConversationColumns.SHOW_DRAFT, 1);
+            values.put(ConversationColumns.DRAFT_SNIPPET_TEXT, draftMessage.getMessageText());
+            values.put(ConversationColumns.DRAFT_SUBJECT_TEXT, draftMessage.getMmsSubject());
+            String type = null;
+            String uriString = null;
+            for (final MessagePartData part : draftMessage.getParts()) {
+                if (part.isAttachment() &&
+                        ContentType.isConversationListPreviewableType(part.getContentType())) {
+                    uriString = part.getContentUri().toString();
+                    type = part.getContentType();
+                    break;
+                }
+            }
+            values.put(ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE, type);
+            values.put(ConversationColumns.DRAFT_PREVIEW_URI, uriString);
+        }
+        values.put(ConversationColumns.SORT_TIMESTAMP, sortTimestamp);
+        // Called in transaction after reading conversation row
+        updateConversationRow(dbWrapper, conversationId, values);
+    }
+
+    @DoesNotRunOnMainThread
+    public static boolean updateConversationRowIfExists(final DatabaseWrapper dbWrapper,
+            final String conversationId, final ContentValues values) {
+        Assert.isNotMainThread();
+        return updateRowIfExists(dbWrapper, DatabaseHelper.CONVERSATIONS_TABLE,
+                ConversationColumns._ID, conversationId, values);
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateConversationRow(final DatabaseWrapper dbWrapper,
+            final String conversationId, final ContentValues values) {
+        Assert.isNotMainThread();
+        final boolean exists = updateConversationRowIfExists(dbWrapper, conversationId, values);
+        Assert.isTrue(exists);
+    }
+
+    @DoesNotRunOnMainThread
+    public static boolean updateMessageRowIfExists(final DatabaseWrapper dbWrapper,
+            final String messageId, final ContentValues values) {
+        Assert.isNotMainThread();
+        return updateRowIfExists(dbWrapper, DatabaseHelper.MESSAGES_TABLE, MessageColumns._ID,
+                messageId, values);
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateMessageRow(final DatabaseWrapper dbWrapper,
+            final String messageId, final ContentValues values) {
+        Assert.isNotMainThread();
+        final boolean exists = updateMessageRowIfExists(dbWrapper, messageId, values);
+        Assert.isTrue(exists);
+    }
+
+    @DoesNotRunOnMainThread
+    public static boolean updatePartRowIfExists(final DatabaseWrapper dbWrapper,
+            final String partId, final ContentValues values) {
+        Assert.isNotMainThread();
+        return updateRowIfExists(dbWrapper, DatabaseHelper.PARTS_TABLE, PartColumns._ID,
+                partId, values);
+    }
+
+    /**
+     * Returns the default conversation name based on its participants.
+     */
+    private static String getDefaultConversationName(final List<ParticipantData> participants) {
+        return ConversationListItemData.generateConversationName(participants);
+    }
+
+    /**
+     * Updates a given conversation's name based on its participants.
+     */
+    @DoesNotRunOnMainThread
+    public static void updateConversationNameAndAvatarInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+
+        final ArrayList<ParticipantData> participants =
+                getParticipantsForConversation(dbWrapper, conversationId);
+        updateConversationNameAndAvatarInTransaction(dbWrapper, conversationId, participants);
+    }
+
+    /**
+     * Updates a given conversation's name based on its participants.
+     */
+    private static void updateConversationNameAndAvatarInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId,
+            final List<ParticipantData> participants) {
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+
+        final ContentValues values = new ContentValues();
+        values.put(ConversationColumns.NAME,
+                getDefaultConversationName(participants));
+
+        // Fill in IS_ENTERPRISE.
+        final boolean hasAnyEnterpriseContact =
+                ConversationListItemData.hasAnyEnterpriseContact(participants);
+        values.put(ConversationColumns.IS_ENTERPRISE, hasAnyEnterpriseContact);
+
+        fillParticipantData(values, participants);
+
+        // Used by background thread when refreshing conversation so conversation could be deleted.
+        updateConversationRowIfExists(dbWrapper, conversationId, values);
+
+        WidgetConversationProvider.notifyConversationRenamed(Factory.get().getApplicationContext(),
+                conversationId);
+    }
+
+    /**
+     * Updates a given conversation's self id.
+     */
+    @DoesNotRunOnMainThread
+    public static void updateConversationSelfIdInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId, final String selfId) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        final ContentValues values = new ContentValues();
+        if (addConversationSelfIdToContentValues(dbWrapper, selfId, values)) {
+            updateConversationRowIfExists(dbWrapper, conversationId, values);
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    public static String getConversationSelfId(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        Assert.isNotMainThread();
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { ConversationColumns.CURRENT_SELF_ID },
+                    ConversationColumns._ID + "=?",
+                    new String[] { conversationId },
+                    null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                return cursor.getString(0);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Frees up memory associated with phone number to participant id matching.
+     */
+    @DoesNotRunOnMainThread
+    public static void clearParticipantIdCache() {
+        Assert.isNotMainThread();
+        synchronized (sNormalizedPhoneNumberToParticipantIdCache) {
+            sNormalizedPhoneNumberToParticipantIdCache.clear();
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    public static ArrayList<String> getRecipientsForConversation(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        Assert.isNotMainThread();
+        final ArrayList<ParticipantData> participants =
+                getParticipantsForConversation(dbWrapper, conversationId);
+
+        final ArrayList<String> recipients = new ArrayList<String>();
+        for (final ParticipantData participant : participants) {
+            recipients.add(participant.getSendDestination());
+        }
+
+        return recipients;
+    }
+
+    @DoesNotRunOnMainThread
+    public static String getSmsServiceCenterForConversation(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        Assert.isNotMainThread();
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { ConversationColumns.SMS_SERVICE_CENTER },
+                    ConversationColumns._ID + "=?",
+                    new String[] { conversationId },
+                    null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                return cursor.getString(0);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    @DoesNotRunOnMainThread
+    public static ParticipantData getExistingParticipant(final DatabaseWrapper dbWrapper,
+            final String participantId) {
+        Assert.isNotMainThread();
+        ParticipantData participant = null;
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantData.ParticipantsQuery.PROJECTION,
+                    ParticipantColumns._ID + " =?",
+                    new String[] { participantId }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                participant = ParticipantData.getFromCursor(cursor);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return participant;
+    }
+
+    public static int getSelfSubscriptionId(final DatabaseWrapper dbWrapper,
+            final String selfParticipantId) {
+        final ParticipantData selfParticipant = BugleDatabaseOperations.getExistingParticipant(
+                dbWrapper, selfParticipantId);
+        if (selfParticipant != null) {
+            Assert.isTrue(selfParticipant.isSelf());
+            return selfParticipant.getSubId();
+        }
+        return ParticipantData.DEFAULT_SELF_SUB_ID;
+    }
+
+    @VisibleForTesting
+    @DoesNotRunOnMainThread
+    public static ArrayList<ParticipantData> getParticipantsForConversation(
+            final DatabaseWrapper dbWrapper, final String conversationId) {
+        Assert.isNotMainThread();
+        final ArrayList<ParticipantData> participants =
+                new ArrayList<ParticipantData>();
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantData.ParticipantsQuery.PROJECTION,
+                    ParticipantColumns._ID + " IN ( " + "SELECT "
+                            + ConversationParticipantsColumns.PARTICIPANT_ID + " AS "
+                            + ParticipantColumns._ID
+                            + " FROM " + DatabaseHelper.CONVERSATION_PARTICIPANTS_TABLE
+                            + " WHERE " + ConversationParticipantsColumns.CONVERSATION_ID + " =? )",
+                            new String[] { conversationId }, null, null, null);
+
+            while (cursor.moveToNext()) {
+                participants.add(ParticipantData.getFromCursor(cursor));
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return participants;
+    }
+
+    @DoesNotRunOnMainThread
+    public static MessageData readMessage(final DatabaseWrapper dbWrapper, final String messageId) {
+        Assert.isNotMainThread();
+        final MessageData message = readMessageData(dbWrapper, messageId);
+        if (message != null) {
+            readMessagePartsData(dbWrapper, message, false);
+        }
+        return message;
+    }
+
+    @VisibleForTesting
+    static MessagePartData readMessagePartData(final DatabaseWrapper dbWrapper,
+            final String partId) {
+        MessagePartData messagePartData = null;
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTS_TABLE,
+                    MessagePartData.getProjection(), PartColumns._ID + "=?",
+                    new String[] { partId }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                messagePartData = MessagePartData.createFromCursor(cursor);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return messagePartData;
+    }
+
+    @DoesNotRunOnMainThread
+    public static MessageData readMessageData(final DatabaseWrapper dbWrapper,
+            final Uri smsMessageUri) {
+        Assert.isNotMainThread();
+        MessageData message = null;
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    MessageData.getProjection(), MessageColumns.SMS_MESSAGE_URI + "=?",
+                    new String[] { smsMessageUri.toString() }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                message = new MessageData();
+                message.bind(cursor);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return message;
+    }
+
+    @DoesNotRunOnMainThread
+    public static MessageData readMessageData(final DatabaseWrapper dbWrapper,
+            final String messageId) {
+        Assert.isNotMainThread();
+        MessageData message = null;
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    MessageData.getProjection(), MessageColumns._ID + "=?",
+                    new String[] { messageId }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                message = new MessageData();
+                message.bind(cursor);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return message;
+    }
+
+    /**
+     * Read all the parts for a message
+     * @param dbWrapper database
+     * @param message read parts for this message
+     * @param checkAttachmentFilesExist check each attachment file and only include if file exists
+     */
+    private static void readMessagePartsData(final DatabaseWrapper dbWrapper,
+            final MessageData message, final boolean checkAttachmentFilesExist) {
+        final ContentResolver contentResolver =
+                Factory.get().getApplicationContext().getContentResolver();
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTS_TABLE,
+                    MessagePartData.getProjection(), PartColumns.MESSAGE_ID + "=?",
+                    new String[] { message.getMessageId() }, null, null, null);
+            while (cursor.moveToNext()) {
+                final MessagePartData messagePartData = MessagePartData.createFromCursor(cursor);
+                if (checkAttachmentFilesExist && messagePartData.isAttachment() &&
+                        !UriUtil.isBugleAppResource(messagePartData.getContentUri())) {
+                    try {
+                        // Test that the file exists before adding the attachment to the draft
+                        final ParcelFileDescriptor fileDescriptor =
+                                contentResolver.openFileDescriptor(
+                                        messagePartData.getContentUri(), "r");
+                        if (fileDescriptor != null) {
+                            fileDescriptor.close();
+                            message.addPart(messagePartData);
+                        }
+                    } catch (final IOException e) {
+                        // The attachment's temp storage no longer exists, just ignore the file
+                    } catch (final SecurityException e) {
+                        // Likely thrown by openFileDescriptor due to an expired access grant.
+                        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                            LogUtil.d(LogUtil.BUGLE_TAG, "uri: " + messagePartData.getContentUri());
+                        }
+                    }
+                } else {
+                    message.addPart(messagePartData);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    /**
+     * Write a message part to our local database
+     *
+     * @param dbWrapper     The database
+     * @param messagePart   The message part to insert
+     * @return The row id of the newly inserted part
+     */
+    static String insertNewMessagePartInTransaction(final DatabaseWrapper dbWrapper,
+            final MessagePartData messagePart, final String conversationId) {
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        Assert.isTrue(!TextUtils.isEmpty(messagePart.getMessageId()));
+
+        // Insert a new part row
+        final SQLiteStatement insert = messagePart.getInsertStatement(dbWrapper, conversationId);
+        final long rowNumber = insert.executeInsert();
+
+        Assert.inRange(rowNumber, 0, Long.MAX_VALUE);
+        final String partId = Long.toString(rowNumber);
+
+        // Update the part id
+        messagePart.updatePartId(partId);
+
+        return partId;
+    }
+
+    /**
+     * Insert a message and its parts into the table
+     */
+    @DoesNotRunOnMainThread
+    public static void insertNewMessageInTransaction(final DatabaseWrapper dbWrapper,
+            final MessageData message) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+
+        // Insert message row
+        final SQLiteStatement insert = message.getInsertStatement(dbWrapper);
+        final long rowNumber = insert.executeInsert();
+
+        Assert.inRange(rowNumber, 0, Long.MAX_VALUE);
+        final String messageId = Long.toString(rowNumber);
+        message.updateMessageId(messageId);
+        //  Insert new parts
+        for (final MessagePartData messagePart : message.getParts()) {
+            messagePart.updateMessageId(messageId);
+            insertNewMessagePartInTransaction(dbWrapper, messagePart, message.getConversationId());
+        }
+    }
+
+    /**
+     * Update a message and add its parts into the table
+     */
+    @DoesNotRunOnMainThread
+    public static void updateMessageInTransaction(final DatabaseWrapper dbWrapper,
+            final MessageData message) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        final String messageId = message.getMessageId();
+        // Check message still exists (sms sync or delete might have purged it)
+        final MessageData current = BugleDatabaseOperations.readMessage(dbWrapper, messageId);
+        if (current != null) {
+            // Delete existing message parts)
+            deletePartsForMessage(dbWrapper, message.getMessageId());
+            //  Insert new parts
+            for (final MessagePartData messagePart : message.getParts()) {
+                messagePart.updatePartId(null);
+                messagePart.updateMessageId(message.getMessageId());
+                insertNewMessagePartInTransaction(dbWrapper, messagePart,
+                        message.getConversationId());
+            }
+            //  Update message row
+            final ContentValues values = new ContentValues();
+            message.populate(values);
+            updateMessageRowIfExists(dbWrapper, message.getMessageId(), values);
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateMessageAndPartsInTransaction(final DatabaseWrapper dbWrapper,
+            final MessageData message, final List<MessagePartData> partsToUpdate) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        final ContentValues values = new ContentValues();
+        for (final MessagePartData messagePart : partsToUpdate) {
+            values.clear();
+            messagePart.populate(values);
+            updatePartRowIfExists(dbWrapper, messagePart.getPartId(), values);
+        }
+        values.clear();
+        message.populate(values);
+        updateMessageRowIfExists(dbWrapper, message.getMessageId(), values);
+    }
+
+    /**
+     * Delete all parts for a message
+     */
+    static void deletePartsForMessage(final DatabaseWrapper dbWrapper,
+            final String messageId) {
+        final int cnt = dbWrapper.delete(DatabaseHelper.PARTS_TABLE,
+                PartColumns.MESSAGE_ID + " =?",
+                new String[] { messageId });
+        Assert.inRange(cnt, 0, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Delete one message and update the conversation (if necessary).
+     *
+     * @return number of rows deleted (should be 1 or 0).
+     */
+    @DoesNotRunOnMainThread
+    public static int deleteMessage(final DatabaseWrapper dbWrapper, final String messageId) {
+        Assert.isNotMainThread();
+        dbWrapper.beginTransaction();
+        try {
+            // Read message to find out which conversation it is in
+            final MessageData message = BugleDatabaseOperations.readMessage(dbWrapper, messageId);
+
+            int count = 0;
+            if (message != null) {
+                final String conversationId = message.getConversationId();
+                // Delete message
+                count = dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE,
+                        MessageColumns._ID + "=?", new String[] { messageId });
+
+                if (!deleteConversationIfEmptyInTransaction(dbWrapper, conversationId)) {
+                    // TODO: Should we leave the conversation sort timestamp alone?
+                    refreshConversationMetadataInTransaction(dbWrapper, conversationId,
+                            false/* shouldAutoSwitchSelfId */, false/*archived*/);
+                }
+            }
+            dbWrapper.setTransactionSuccessful();
+            return count;
+        } finally {
+            dbWrapper.endTransaction();
+        }
+    }
+
+    /**
+     * Deletes the conversation if there are zero non-draft messages left.
+     * <p>
+     * This is necessary because the telephony database has a trigger that deletes threads after
+     * their last message is deleted. We need to ensure that if a thread goes away, we also delete
+     * the conversation in Bugle. We don't store draft messages in telephony, so we ignore those
+     * when querying for the # of messages in the conversation.
+     *
+     * @return true if the conversation was deleted
+     */
+    @DoesNotRunOnMainThread
+    public static boolean deleteConversationIfEmptyInTransaction(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        Cursor cursor = null;
+        try {
+            // TODO: The refreshConversationMetadataInTransaction method below uses this
+            // same query; maybe they should share this logic?
+
+            // Check to see if there are any (non-draft) messages in the conversation
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    REFRESH_CONVERSATION_MESSAGE_PROJECTION,
+                    MessageColumns.CONVERSATION_ID + "=? AND " +
+                    MessageColumns.STATUS + "!=" + MessageData.BUGLE_STATUS_OUTGOING_DRAFT,
+                    new String[] { conversationId }, null, null,
+                    MessageColumns.RECEIVED_TIMESTAMP + " DESC", "1" /* limit */);
+            if (cursor.getCount() == 0) {
+                dbWrapper.delete(DatabaseHelper.CONVERSATIONS_TABLE,
+                        ConversationColumns._ID + "=?", new String[] { conversationId });
+                LogUtil.i(TAG,
+                        "BugleDatabaseOperations: Deleted empty conversation " + conversationId);
+                return true;
+            } else {
+                return false;
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    private static final String[] REFRESH_CONVERSATION_MESSAGE_PROJECTION = new String[] {
+        MessageColumns._ID,
+        MessageColumns.RECEIVED_TIMESTAMP,
+        MessageColumns.SENDER_PARTICIPANT_ID
+    };
+
+    /**
+     * Update conversation snippet, timestamp and optionally self id to match latest message in
+     * conversation.
+     */
+    @DoesNotRunOnMainThread
+    public static void refreshConversationMetadataInTransaction(final DatabaseWrapper dbWrapper,
+            final String conversationId, final boolean shouldAutoSwitchSelfId,
+            boolean keepArchived) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        Cursor cursor = null;
+        try {
+            // Check to see if there are any (non-draft) messages in the conversation
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    REFRESH_CONVERSATION_MESSAGE_PROJECTION,
+                    MessageColumns.CONVERSATION_ID + "=? AND " +
+                    MessageColumns.STATUS + "!=" + MessageData.BUGLE_STATUS_OUTGOING_DRAFT,
+                    new String[] { conversationId }, null, null,
+                    MessageColumns.RECEIVED_TIMESTAMP + " DESC", "1" /* limit */);
+
+            if (cursor.moveToFirst()) {
+                // Refresh latest message in conversation
+                final String latestMessageId = cursor.getString(0);
+                final long latestMessageTimestamp = cursor.getLong(1);
+                final String senderParticipantId = cursor.getString(2);
+                final boolean senderBlocked = isBlockedParticipant(dbWrapper, senderParticipantId);
+                updateConversationMetadataInTransaction(dbWrapper, conversationId,
+                        latestMessageId, latestMessageTimestamp, senderBlocked || keepArchived,
+                        shouldAutoSwitchSelfId);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    /**
+     * When moving/removing an existing message update conversation metadata if necessary
+     * @param dbWrapper      db wrapper
+     * @param conversationId conversation to modify
+     * @param messageId      message that is leaving the conversation
+     * @param shouldAutoSwitchSelfId should we try to auto-switch the conversation's self-id as a
+     *        result of this call when we see a new latest message?
+     * @param keepArchived   should we keep the conversation archived despite refresh
+     */
+    @DoesNotRunOnMainThread
+    public static void maybeRefreshConversationMetadataInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId, final String messageId,
+            final boolean shouldAutoSwitchSelfId, final boolean keepArchived) {
+        Assert.isNotMainThread();
+        boolean refresh = true;
+        if (!TextUtils.isEmpty(messageId)) {
+            refresh = false;
+            // Look for an existing conversation in the db with this conversation id
+            Cursor cursor = null;
+            try {
+                cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                        new String[] { ConversationColumns.LATEST_MESSAGE_ID },
+                        ConversationColumns._ID + "=?",
+                        new String[] { conversationId },
+                        null, null, null);
+                Assert.inRange(cursor.getCount(), 0, 1);
+                if (cursor.moveToFirst()) {
+                    refresh = TextUtils.equals(cursor.getString(0), messageId);
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+        if (refresh) {
+            // TODO: I think it is okay to delete the conversation if it is empty...
+            refreshConversationMetadataInTransaction(dbWrapper, conversationId,
+                    shouldAutoSwitchSelfId, keepArchived);
+        }
+    }
+
+
+
+    // SQL statement to query latest message if for particular conversation
+    private static final String QUERY_CONVERSATIONS_LATEST_MESSAGE_SQL = "SELECT "
+            + ConversationColumns.LATEST_MESSAGE_ID + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE
+            + " WHERE " + ConversationColumns._ID + "=? LIMIT 1";
+
+    /**
+     * Note this is not thread safe so callers need to make sure they own the wrapper + statements
+     * while they call this and use the returned value.
+     */
+    @DoesNotRunOnMainThread
+    public static SQLiteStatement getQueryConversationsLatestMessageStatement(
+            final DatabaseWrapper db, final String conversationId) {
+        Assert.isNotMainThread();
+        final SQLiteStatement query = db.getStatementInTransaction(
+                DatabaseWrapper.INDEX_QUERY_CONVERSATIONS_LATEST_MESSAGE,
+                QUERY_CONVERSATIONS_LATEST_MESSAGE_SQL);
+        query.clearBindings();
+        query.bindString(1, conversationId);
+        return query;
+    }
+
+    // SQL statement to query latest message if for particular conversation
+    private static final String QUERY_MESSAGES_LATEST_MESSAGE_SQL = "SELECT "
+            + MessageColumns._ID + " FROM " + DatabaseHelper.MESSAGES_TABLE
+            + " WHERE " + MessageColumns.CONVERSATION_ID + "=? ORDER BY "
+            + MessageColumns.RECEIVED_TIMESTAMP + " DESC LIMIT 1";
+
+    /**
+     * Note this is not thread safe so callers need to make sure they own the wrapper + statements
+     * while they call this and use the returned value.
+     */
+    @DoesNotRunOnMainThread
+    public static SQLiteStatement getQueryMessagesLatestMessageStatement(
+            final DatabaseWrapper db, final String conversationId) {
+        Assert.isNotMainThread();
+        final SQLiteStatement query = db.getStatementInTransaction(
+                DatabaseWrapper.INDEX_QUERY_MESSAGES_LATEST_MESSAGE,
+                QUERY_MESSAGES_LATEST_MESSAGE_SQL);
+        query.clearBindings();
+        query.bindString(1, conversationId);
+        return query;
+    }
+
+    /**
+     * Update conversation metadata if necessary
+     * @param dbWrapper      db wrapper
+     * @param conversationId conversation to modify
+     * @param shouldAutoSwitchSelfId should we try to auto-switch the conversation's self-id as a
+     *                               result of this call when we see a new latest message?
+     * @param keepArchived if the conversation should be kept archived
+     */
+    @DoesNotRunOnMainThread
+    public static void maybeRefreshConversationMetadataInTransaction(
+            final DatabaseWrapper dbWrapper, final String conversationId,
+            final boolean shouldAutoSwitchSelfId, boolean keepArchived) {
+        Assert.isNotMainThread();
+        String currentLatestMessageId = null;
+        String latestMessageId = null;
+        try {
+            final SQLiteStatement currentLatestMessageIdSql =
+                    getQueryConversationsLatestMessageStatement(dbWrapper, conversationId);
+            currentLatestMessageId = currentLatestMessageIdSql.simpleQueryForString();
+
+            final SQLiteStatement latestMessageIdSql =
+                    getQueryMessagesLatestMessageStatement(dbWrapper, conversationId);
+            latestMessageId = latestMessageIdSql.simpleQueryForString();
+        } catch (final SQLiteDoneException e) {
+            LogUtil.e(TAG, "BugleDatabaseOperations: Query for latest message failed", e);
+        }
+
+        if (TextUtils.isEmpty(currentLatestMessageId) ||
+                !TextUtils.equals(currentLatestMessageId, latestMessageId)) {
+            refreshConversationMetadataInTransaction(dbWrapper, conversationId,
+                    shouldAutoSwitchSelfId, keepArchived);
+        }
+    }
+
+    static boolean getConversationExists(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        // Look for an existing conversation in the db with this conversation id
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { /* No projection */},
+                    ConversationColumns._ID + "=?",
+                    new String[] { conversationId },
+                    null, null, null);
+            return cursor.getCount() == 1;
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    /** Preserve parts in message but clear the stored draft */
+    public static final int UPDATE_MODE_CLEAR_DRAFT = 1;
+    /** Add the message as a draft */
+    public static final int UPDATE_MODE_ADD_DRAFT = 2;
+
+    /**
+     * Update draft message for specified conversation
+     * @param dbWrapper       local database (wrapped)
+     * @param conversationId  conversation to update
+     * @param message         Optional message to preserve attachments for (either as draft or for
+     *                        sending)
+     * @param updateMode      either {@link #UPDATE_MODE_CLEAR_DRAFT} or
+     *                        {@link #UPDATE_MODE_ADD_DRAFT}
+     * @return message id of newly written draft (else null)
+     */
+    @DoesNotRunOnMainThread
+    public static String updateDraftMessageData(final DatabaseWrapper dbWrapper,
+            final String conversationId, @Nullable final MessageData message,
+            final int updateMode) {
+        Assert.isNotMainThread();
+        Assert.notNull(conversationId);
+        Assert.inRange(updateMode, UPDATE_MODE_CLEAR_DRAFT, UPDATE_MODE_ADD_DRAFT);
+        String messageId = null;
+        Cursor cursor = null;
+        dbWrapper.beginTransaction();
+        try {
+            // Find all draft parts for the current conversation
+            final SimpleArrayMap<Uri, MessagePartData> currentDraftParts = new SimpleArrayMap<>();
+            cursor = dbWrapper.query(DatabaseHelper.DRAFT_PARTS_VIEW,
+                    MessagePartData.getProjection(),
+                    MessageColumns.CONVERSATION_ID + " =?",
+                    new String[] { conversationId }, null, null, null);
+            while (cursor.moveToNext()) {
+                final MessagePartData part = MessagePartData.createFromCursor(cursor);
+                if (part.isAttachment()) {
+                    currentDraftParts.put(part.getContentUri(), part);
+                }
+            }
+            // Optionally, preserve attachments for "message"
+            final boolean conversationExists = getConversationExists(dbWrapper, conversationId);
+            if (message != null && conversationExists) {
+                for (final MessagePartData part : message.getParts()) {
+                    if (part.isAttachment()) {
+                        currentDraftParts.remove(part.getContentUri());
+                    }
+                }
+            }
+
+            // Delete orphan content
+            for (int index = 0; index < currentDraftParts.size(); index++) {
+                final MessagePartData part = currentDraftParts.valueAt(index);
+                part.destroySync();
+            }
+
+            // Delete existing draft (cascade deletes parts)
+            dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE,
+                    MessageColumns.STATUS + "=? AND " + MessageColumns.CONVERSATION_ID + "=?",
+                    new String[] {
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_DRAFT),
+                        conversationId
+                    });
+
+            // Write new draft
+            if (updateMode == UPDATE_MODE_ADD_DRAFT && message != null
+                    && message.hasContent() && conversationExists) {
+                Assert.equals(MessageData.BUGLE_STATUS_OUTGOING_DRAFT,
+                        message.getStatus());
+
+                // Now add draft to message table
+                insertNewMessageInTransaction(dbWrapper, message);
+                messageId = message.getMessageId();
+            }
+
+            if (conversationExists) {
+                updateConversationDraftSnippetAndPreviewInTransaction(
+                        dbWrapper, conversationId, message);
+
+                if (message != null && message.getSelfId() != null) {
+                    updateConversationSelfIdInTransaction(dbWrapper, conversationId,
+                            message.getSelfId());
+                }
+            }
+
+            dbWrapper.setTransactionSuccessful();
+        } finally {
+            dbWrapper.endTransaction();
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG,
+                    "Updated draft message " + messageId + " for conversation " + conversationId);
+        }
+        return messageId;
+    }
+
+    /**
+     * Read the first draft message associated with this conversation.
+     * If none present create an empty (sms) draft message.
+     */
+    @DoesNotRunOnMainThread
+    public static MessageData readDraftMessageData(final DatabaseWrapper dbWrapper,
+            final String conversationId, final String conversationSelfId) {
+        Assert.isNotMainThread();
+        MessageData message = null;
+        Cursor cursor = null;
+        dbWrapper.beginTransaction();
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.MESSAGES_TABLE,
+                    MessageData.getProjection(),
+                    MessageColumns.STATUS + "=? AND " + MessageColumns.CONVERSATION_ID + "=?",
+                    new String[] {
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_DRAFT),
+                        conversationId
+                    }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                message = new MessageData();
+                message.bindDraft(cursor, conversationSelfId);
+                readMessagePartsData(dbWrapper, message, true);
+                // Disconnect draft parts from DB
+                for (final MessagePartData part : message.getParts()) {
+                    part.updatePartId(null);
+                    part.updateMessageId(null);
+                }
+                message.updateMessageId(null);
+            }
+            dbWrapper.setTransactionSuccessful();
+        } finally {
+            dbWrapper.endTransaction();
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return message;
+    }
+
+    // Internal
+    private static void addParticipantToConversation(final DatabaseWrapper dbWrapper,
+            final ParticipantData participant, final String conversationId) {
+        final String participantId = getOrCreateParticipantInTransaction(dbWrapper, participant);
+        Assert.notNull(participantId);
+
+        // Add the participant to the conversation participants table
+        final ContentValues values = new ContentValues();
+        values.put(ConversationParticipantsColumns.CONVERSATION_ID, conversationId);
+        values.put(ConversationParticipantsColumns.PARTICIPANT_ID, participantId);
+        dbWrapper.insert(DatabaseHelper.CONVERSATION_PARTICIPANTS_TABLE, null, values);
+    }
+
+    /**
+     * Get string used as canonical recipient for participant cache for sub id
+     */
+    private static String getCanonicalRecipientFromSubId(final int subId) {
+        return "SELF(" + subId + ")";
+    }
+
+    /**
+     * Maps from a sub id or phone number to a participant id if there is one.
+     *
+     * @return If the participant is available in our cache, or the DB, this returns the
+     * participant id for the given subid/phone number.  Otherwise it returns null.
+     */
+    @VisibleForTesting
+    private static String getParticipantId(final DatabaseWrapper dbWrapper,
+            final int subId, final String canonicalRecipient) {
+        // First check our memory cache for the participant Id
+        String participantId;
+        synchronized (sNormalizedPhoneNumberToParticipantIdCache) {
+            participantId = sNormalizedPhoneNumberToParticipantIdCache.get(canonicalRecipient);
+        }
+
+        if (participantId != null) {
+            return participantId;
+        }
+
+        // This code will only be executed for incremental additions.
+        Cursor cursor = null;
+        try {
+            if (subId != ParticipantData.OTHER_THAN_SELF_SUB_ID) {
+                // Now look for an existing participant in the db with this sub id.
+                cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                        new String[] {ParticipantColumns._ID},
+                        ParticipantColumns.SUB_ID + "=?",
+                        new String[] { Integer.toString(subId) }, null, null, null);
+            } else {
+                // Look for existing participant with this normalized phone number and no subId.
+                cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                        new String[] {ParticipantColumns._ID},
+                        ParticipantColumns.NORMALIZED_DESTINATION + "=? AND "
+                                + ParticipantColumns.SUB_ID + "=?",
+                                new String[] {canonicalRecipient, Integer.toString(subId)},
+                                null, null, null);
+            }
+
+            if (cursor.moveToFirst()) {
+                // TODO Is this assert correct for multi-sim where a new sim was put in?
+                Assert.isTrue(cursor.getCount() == 1);
+
+                // We found an existing participant in the database
+                participantId = cursor.getString(0);
+
+                synchronized (sNormalizedPhoneNumberToParticipantIdCache) {
+                    // Add it to the cache for next time
+                    sNormalizedPhoneNumberToParticipantIdCache.put(canonicalRecipient,
+                            participantId);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return participantId;
+    }
+
+    @DoesNotRunOnMainThread
+    public static ParticipantData getOrCreateSelf(final DatabaseWrapper dbWrapper,
+            final int subId) {
+        Assert.isNotMainThread();
+        ParticipantData participant = null;
+        dbWrapper.beginTransaction();
+        try {
+            final ParticipantData shell = ParticipantData.getSelfParticipant(subId);
+            final String participantId = getOrCreateParticipantInTransaction(dbWrapper, shell);
+            participant = getExistingParticipant(dbWrapper, participantId);
+            dbWrapper.setTransactionSuccessful();
+        } finally {
+            dbWrapper.endTransaction();
+        }
+        return participant;
+    }
+
+    /**
+     * Lookup and if necessary create a new participant
+     * @param dbWrapper      Database wrapper
+     * @param participant    Participant to find/create
+     * @return participantId ParticipantId for existing or newly created participant
+     */
+    @DoesNotRunOnMainThread
+    public static String getOrCreateParticipantInTransaction(final DatabaseWrapper dbWrapper,
+            final ParticipantData participant) {
+        Assert.isNotMainThread();
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        int subId = ParticipantData.OTHER_THAN_SELF_SUB_ID;
+        String participantId = null;
+        String canonicalRecipient = null;
+        if (participant.isSelf()) {
+            subId = participant.getSubId();
+            canonicalRecipient = getCanonicalRecipientFromSubId(subId);
+        } else {
+            canonicalRecipient = participant.getNormalizedDestination();
+        }
+        Assert.notNull(canonicalRecipient);
+        participantId = getParticipantId(dbWrapper, subId, canonicalRecipient);
+
+        if (participantId != null) {
+            return participantId;
+        }
+
+        if (!participant.isContactIdResolved()) {
+            // Refresh participant's name and avatar with matching contact in CP2.
+            ParticipantRefresh.refreshParticipant(dbWrapper, participant);
+        }
+
+        // Insert the participant into the participants table
+        final ContentValues values = participant.toContentValues();
+        final long participantRow = dbWrapper.insert(DatabaseHelper.PARTICIPANTS_TABLE, null,
+                values);
+        participantId = Long.toString(participantRow);
+        Assert.notNull(canonicalRecipient);
+
+        synchronized (sNormalizedPhoneNumberToParticipantIdCache) {
+            // Now that we've inserted it, add it to our cache
+            sNormalizedPhoneNumberToParticipantIdCache.put(canonicalRecipient, participantId);
+        }
+
+        return participantId;
+    }
+
+    @DoesNotRunOnMainThread
+    public static void updateDestination(final DatabaseWrapper dbWrapper,
+            final String destination, final boolean blocked) {
+        Assert.isNotMainThread();
+        final ContentValues values = new ContentValues();
+        values.put(ParticipantColumns.BLOCKED, blocked ? 1 : 0);
+        dbWrapper.update(DatabaseHelper.PARTICIPANTS_TABLE, values,
+                ParticipantColumns.NORMALIZED_DESTINATION + "=? AND " +
+                        ParticipantColumns.SUB_ID + "=?",
+                new String[] { destination, Integer.toString(
+                        ParticipantData.OTHER_THAN_SELF_SUB_ID) });
+    }
+
+    @DoesNotRunOnMainThread
+    public static String getConversationFromOtherParticipantDestination(
+            final DatabaseWrapper db, final String otherDestination) {
+        Assert.isNotMainThread();
+        Cursor cursor = null;
+        try {
+            cursor = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { ConversationColumns._ID },
+                    ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION + "=?",
+                    new String[] { otherDestination }, null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                return cursor.getString(0);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * Get a list of conversations that contain any of participants specified.
+     */
+    private static HashSet<String> getConversationsForParticipants(
+            final ArrayList<String> participantIds) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final HashSet<String> conversationIds = new HashSet<String>();
+
+        final String selection = ConversationParticipantsColumns.PARTICIPANT_ID + "=?";
+        for (final String participantId : participantIds) {
+            final String[] selectionArgs = new String[] { participantId };
+            final Cursor cursor = db.query(DatabaseHelper.CONVERSATION_PARTICIPANTS_TABLE,
+                    ConversationParticipantsQuery.PROJECTION,
+                    selection, selectionArgs, null, null, null);
+
+            if (cursor != null) {
+                try {
+                    while (cursor.moveToNext()) {
+                        final String conversationId = cursor.getString(
+                                ConversationParticipantsQuery.INDEX_CONVERSATION_ID);
+                        conversationIds.add(conversationId);
+                    }
+                } finally {
+                    cursor.close();
+                }
+            }
+        }
+
+        return conversationIds;
+    }
+
+    /**
+     * Refresh conversation names/avatars based on a list of participants that are changed.
+     */
+    @DoesNotRunOnMainThread
+    public static void refreshConversationsForParticipants(final ArrayList<String> participants) {
+        Assert.isNotMainThread();
+        final HashSet<String> conversationIds = getConversationsForParticipants(participants);
+        if (conversationIds.size() > 0) {
+            for (final String conversationId : conversationIds) {
+                refreshConversation(conversationId);
+            }
+
+            MessagingContentProvider.notifyConversationListChanged();
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Number of conversations refreshed:" + conversationIds.size());
+            }
+        }
+    }
+
+    /**
+     * Refresh conversation names/avatars based on a changed participant.
+     */
+    @DoesNotRunOnMainThread
+    public static void refreshConversationsForParticipant(final String participantId) {
+        Assert.isNotMainThread();
+        final ArrayList<String> participantList = new ArrayList<String>(1);
+        participantList.add(participantId);
+        refreshConversationsForParticipants(participantList);
+    }
+
+    /**
+     * Refresh one conversation.
+     */
+    private static void refreshConversation(final String conversationId) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        db.beginTransaction();
+        try {
+            BugleDatabaseOperations.updateConversationNameAndAvatarInTransaction(db,
+                    conversationId);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        MessagingContentProvider.notifyParticipantsChanged(conversationId);
+        MessagingContentProvider.notifyMessagesChanged(conversationId);
+        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
+    }
+
+    @DoesNotRunOnMainThread
+    public static boolean updateRowIfExists(final DatabaseWrapper db, final String table,
+            final String rowKey, final String rowId, final ContentValues values) {
+        Assert.isNotMainThread();
+        final StringBuilder sb = new StringBuilder();
+        final ArrayList<String> whereValues = new ArrayList<String>(values.size() + 1);
+        whereValues.add(rowId);
+
+        for (final String key : values.keySet()) {
+            if (sb.length() > 0) {
+                sb.append(" OR ");
+            }
+            final Object value = values.get(key);
+            sb.append(key);
+            if (value != null) {
+                sb.append(" IS NOT ?");
+                whereValues.add(value.toString());
+            } else {
+                sb.append(" IS NOT NULL");
+            }
+        }
+
+        final String whereClause = rowKey + "=?" + " AND (" + sb.toString() + ")";
+        final String [] whereValuesArray = whereValues.toArray(new String[whereValues.size()]);
+        final int count = db.update(table, values, whereClause, whereValuesArray);
+        if (count > 1) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Updated more than 1 row " + count + "; " + table +
+                    " for " + rowKey + " = " + rowId + " (deleted?)");
+        }
+        Assert.inRange(count, 0, 1);
+        return (count >= 0);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/BugleNotifications.java b/src/com/android/messaging/datamodel/BugleNotifications.java
new file mode 100644
index 0000000..3faee85
--- /dev/null
+++ b/src/com/android/messaging/datamodel/BugleNotifications.java
@@ -0,0 +1,1221 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Typeface;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationCompat.WearableExtender;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.core.app.RemoteInput;
+import androidx.collection.SimpleArrayMap;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
+import android.text.style.TextAppearanceSpan;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MessageNotificationState.BundledMessageNotificationState;
+import com.android.messaging.datamodel.MessageNotificationState.ConversationLineInfo;
+import com.android.messaging.datamodel.MessageNotificationState.MultiConversationNotificationState;
+import com.android.messaging.datamodel.MessageNotificationState.MultiMessageNotificationState;
+import com.android.messaging.datamodel.action.MarkAsReadAction;
+import com.android.messaging.datamodel.action.MarkAsSeenAction;
+import com.android.messaging.datamodel.action.RedownloadMmsAction;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.media.AvatarRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.MessagePartVideoThumbnailRequestDescriptor;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.datamodel.media.VideoThumbnailRequest;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ConversationIdSet;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.NotificationPlayer;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PendingIntentConstants;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.RingtoneUtil;
+import com.android.messaging.util.ThreadUtil;
+import com.android.messaging.util.UriUtil;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Handle posting, updating and removing all conversation notifications.
+ *
+ * There are currently two main classes of notification and their rules: <p>
+ * 1) Messages - {@link MessageNotificationState}. Only one message notification.
+ * Unread messages across senders and conversations are coalesced.<p>
+ * 2) Failed Messages - {@link MessageNotificationState#checkFailedMesages } Only one failed
+ * message. Multiple failures are coalesced.<p>
+ *
+ * To add a new class of notifications, subclass the NotificationState and add commands which
+ * create one and pass into general creation function.
+ *
+ */
+public class BugleNotifications {
+    // Logging
+    public static final String TAG = LogUtil.BUGLE_NOTIFICATIONS_TAG;
+
+    // Constants to use for update.
+    public static final int UPDATE_NONE = 0;
+    public static final int UPDATE_MESSAGES = 1;
+    public static final int UPDATE_ERRORS = 2;
+    public static final int UPDATE_ALL = UPDATE_MESSAGES + UPDATE_ERRORS;
+
+    // Constants for notification type used for audio and vibration settings.
+    public static final int LOCAL_SMS_NOTIFICATION = 0;
+
+    private static final String SMS_NOTIFICATION_TAG = ":sms:";
+    private static final String SMS_ERROR_NOTIFICATION_TAG = ":error:";
+
+    private static final String WEARABLE_COMPANION_APP_PACKAGE = "com.google.android.wearable.app";
+
+    private static final Set<NotificationState> sPendingNotifications =
+            new HashSet<NotificationState>();
+
+    private static int sWearableImageWidth;
+    private static int sWearableImageHeight;
+    private static int sIconWidth;
+    private static int sIconHeight;
+
+    private static boolean sInitialized = false;
+
+    private static final Object mLock = new Object();
+
+    // sLastMessageDingTime is a map between a conversation id and a time. It's used to keep track
+    // of the time we last dinged a message for this conversation. When messages are coming in
+    // at flurry, we don't want to over-ding the user.
+    private static final SimpleArrayMap<String, Long> sLastMessageDingTime =
+            new SimpleArrayMap<String, Long>();
+    private static int sTimeBetweenDingsMs;
+
+    /**
+     * This is the volume at which to play the observable-conversation notification sound,
+     * expressed as a fraction of the system notification volume.
+     */
+    private static final float OBSERVABLE_CONVERSATION_NOTIFICATION_VOLUME = 0.25f;
+
+    /**
+     * Entry point for posting notifications.
+     * Don't call this on the UI thread.
+     * @param silent If true, no ring will be played. If false, checks global settings before
+     * playing a ringtone
+     * @param coverage Indicates which notification types should be checked. Valid values are
+     * UPDATE_NONE, UPDATE_MESSAGES, UPDATE_ERRORS, or UPDATE_ALL
+     */
+    public static void update(final boolean silent, final int coverage) {
+        update(silent, null /* conversationId */, coverage);
+    }
+
+    /**
+     * Entry point for posting notifications.
+     * Don't call this on the UI thread.
+     * @param silent If true, no ring will be played. If false, checks global settings before
+     * playing a ringtone
+     * @param conversationId Conversation ID where a new message was received
+     * @param coverage Indicates which notification types should be checked. Valid values are
+     * UPDATE_NONE, UPDATE_MESSAGES, UPDATE_ERRORS, or UPDATE_ALL
+     */
+    public static void update(final boolean silent, final String conversationId,
+            final int coverage) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "Update: silent = " + silent
+                    + " conversationId = " + conversationId
+                    + " coverage = " + coverage);
+        }
+    Assert.isNotMainThread();
+        checkInitialized();
+
+        if (!shouldNotify()) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Notifications disabled");
+            }
+            cancel(PendingIntentConstants.SMS_NOTIFICATION_ID);
+            return;
+        } else {
+            if ((coverage & UPDATE_MESSAGES) != 0) {
+                createMessageNotification(silent, conversationId);
+            }
+        }
+        if ((coverage & UPDATE_ERRORS) != 0) {
+            MessageNotificationState.checkFailedMessages();
+        }
+    }
+
+    /**
+     * Cancel all notifications of a certain type.
+     *
+     * @param type Message or error notifications from Constants.
+     */
+    private static synchronized void cancel(final int type) {
+        cancel(type, null, false);
+    }
+
+    /**
+     * Cancel all notifications of a certain type.
+     *
+     * @param type Message or error notifications from Constants.
+     * @param conversationId If set, cancel the notification for this
+     *            conversation only. For message notifications, this only works
+     *            if the notifications are bundled (group children).
+     * @param isBundledNotification True if this notification is part of a
+     *            notification bundle. This only applies to message notifications,
+     *            which are bundled together with other message notifications.
+     */
+    private static synchronized void cancel(final int type, final String conversationId,
+            final boolean isBundledNotification) {
+        final String notificationTag = buildNotificationTag(type, conversationId,
+                isBundledNotification);
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+
+        // Find all pending notifications and cancel them.
+        synchronized (sPendingNotifications) {
+            final Iterator<NotificationState> iter = sPendingNotifications.iterator();
+            while (iter.hasNext()) {
+                final NotificationState notifState = iter.next();
+                if (notifState.mType == type) {
+                    notifState.mCanceled = true;
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "Canceling pending notification");
+                    }
+                    iter.remove();
+                }
+            }
+        }
+        notificationManager.cancel(notificationTag, type);
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "Canceled notifications of type " + type);
+        }
+
+        // Message notifications for multiple conversations can be grouped together (see comment in
+        // createMessageNotification). We need to do bookkeeping to track the current set of
+        // notification group children, including removing them when we cancel notifications).
+        if (type == PendingIntentConstants.SMS_NOTIFICATION_ID) {
+            final Context context = Factory.get().getApplicationContext();
+            final ConversationIdSet groupChildIds = getGroupChildIds(context);
+
+            if (groupChildIds != null && groupChildIds.size() > 0) {
+                // If a conversation is specified, remove just that notification. Otherwise,
+                // we're removing the group summary so clear all children.
+                if (conversationId != null) {
+                    groupChildIds.remove(conversationId);
+                    writeGroupChildIds(context, groupChildIds);
+                } else {
+                    cancelStaleGroupChildren(groupChildIds, null);
+                    // We'll update the group children preference as we cancel each child,
+                    // so we don't need to do it here.
+                }
+            }
+        }
+    }
+
+    /**
+     * Cancels stale notifications from the currently active group of
+     * notifications. If the {@code state} parameter is an instance of
+     * {@link MultiConversationNotificationState} it represents a new
+     * notification group. This method will cancel any notifications that were
+     * in the old group, but not the new one. If the new notification is not a
+     * group, then all existing grouped notifications are cancelled.
+     *
+     * @param previousGroupChildren Conversation ids for the active notification
+     *            group
+     * @param state New notification state
+     */
+    private static void cancelStaleGroupChildren(final ConversationIdSet previousGroupChildren,
+            final NotificationState state) {
+        final ConversationIdSet newChildren = new ConversationIdSet();
+        if (state instanceof MultiConversationNotificationState) {
+            for (final NotificationState child :
+                ((MultiConversationNotificationState) state).mChildren) {
+                if (child.mConversationIds != null) {
+                    newChildren.add(child.mConversationIds.first());
+                }
+            }
+        }
+        for (final String childConversationId : previousGroupChildren) {
+            if (!newChildren.contains(childConversationId)) {
+                cancel(PendingIntentConstants.SMS_NOTIFICATION_ID, childConversationId, true);
+            }
+        }
+    }
+
+    /**
+     * Returns {@code true} if incoming notifications should display a
+     * notification, {@code false} otherwise.
+     *
+     * @return true if the notification should occur
+     */
+    private static boolean shouldNotify() {
+        // If we're not the default sms app, don't put up any notifications.
+        if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
+            return false;
+        }
+
+        // Now check prefs (i.e. settings) to see if the user turned off notifications.
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        final Context context = Factory.get().getApplicationContext();
+        final String prefKey = context.getString(R.string.notifications_enabled_pref_key);
+        final boolean defaultValue = context.getResources().getBoolean(
+                R.bool.notifications_enabled_pref_default);
+        return prefs.getBoolean(prefKey, defaultValue);
+    }
+
+    /**
+     * Returns {@code true} if incoming notifications for the given {@link NotificationState}
+     * should vibrate the device, {@code false} otherwise.
+     *
+     * @return true if vibration should be used
+     */
+    public static boolean shouldVibrate(final NotificationState state) {
+        // The notification should vibrate if the global setting is turned on AND
+        // the per-conversation setting is turned on (default).
+        if (!state.getNotificationVibrate()) {
+            return false;
+        } else {
+            final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+            final Context context = Factory.get().getApplicationContext();
+            final String prefKey = context.getString(R.string.notification_vibration_pref_key);
+            final boolean defaultValue = context.getResources().getBoolean(
+                    R.bool.notification_vibration_pref_default);
+            return prefs.getBoolean(prefKey, defaultValue);
+        }
+    }
+
+    private static Uri getNotificationRingtoneUriForConversationId(final String conversationId) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final ConversationListItemData convData =
+                ConversationListItemData.getExistingConversation(db, conversationId);
+        return RingtoneUtil.getNotificationRingtoneUri(
+                convData != null ? convData.getNotificationSoundUri() : null);
+    }
+
+    /**
+     * Returns a unique tag to identify a notification.
+     *
+     * @param name The tag name (in practice, the type)
+     * @param conversationId The conversation id (optional)
+     */
+    private static String buildNotificationTag(final String name,
+            final String conversationId) {
+        final Context context = Factory.get().getApplicationContext();
+        if (conversationId != null) {
+            return context.getPackageName() + name + ":" + conversationId;
+        } else {
+            return context.getPackageName() + name;
+        }
+    }
+
+    /**
+     * Returns a unique tag to identify a notification.
+     * <p>
+     * This delegates to
+     * {@link #buildNotificationTag(int, String, boolean)} and can be
+     * used when the notification is never bundled (e.g. error notifications).
+     */
+    static String buildNotificationTag(final int type, final String conversationId) {
+        return buildNotificationTag(type, conversationId, false /* bundledNotification */);
+    }
+
+    /**
+     * Returns a unique tag to identify a notification.
+     *
+     * @param type One of the constants in {@link PendingIntentConstants}
+     * @param conversationId The conversation id (where applicable)
+     * @param bundledNotification Set to true if this notification will be
+     *            bundled together with other notifications (e.g. on a wearable
+     *            device).
+     */
+    static String buildNotificationTag(final int type, final String conversationId,
+            final boolean bundledNotification) {
+        String tag = null;
+        switch(type) {
+            case PendingIntentConstants.SMS_NOTIFICATION_ID:
+                if (bundledNotification) {
+                    tag = buildNotificationTag(SMS_NOTIFICATION_TAG, conversationId);
+                } else {
+                    tag = buildNotificationTag(SMS_NOTIFICATION_TAG, null);
+                }
+                break;
+            case PendingIntentConstants.MSG_SEND_ERROR:
+                tag = buildNotificationTag(SMS_ERROR_NOTIFICATION_TAG, null);
+                break;
+        }
+        return tag;
+    }
+
+    private static void checkInitialized() {
+        if (!sInitialized) {
+            final Resources resources = Factory.get().getApplicationContext().getResources();
+            sWearableImageWidth = resources.getDimensionPixelSize(
+                    R.dimen.notification_wearable_image_width);
+            sWearableImageHeight = resources.getDimensionPixelSize(
+                    R.dimen.notification_wearable_image_height);
+            sIconHeight = (int) resources.getDimension(
+                    android.R.dimen.notification_large_icon_height);
+            sIconWidth =
+                    (int) resources.getDimension(android.R.dimen.notification_large_icon_width);
+
+            sInitialized = true;
+        }
+    }
+
+    private static void processAndSend(final NotificationState state, final boolean silent,
+            final boolean softSound) {
+        final Context context = Factory.get().getApplicationContext();
+        final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context);
+        notifBuilder.setCategory(Notification.CATEGORY_MESSAGE);
+        // TODO: Need to fix this for multi conversation notifications to rate limit dings.
+        final String conversationId = state.mConversationIds.first();
+
+
+        final Uri ringtoneUri = RingtoneUtil.getNotificationRingtoneUri(state.getRingtoneUri());
+        // If the notification's conversation is currently observable (focused or in the
+        // conversation list),  then play a notification beep at a low volume and don't display an
+        // actual notification.
+        if (softSound) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "processAndSend: fromConversationId == " +
+                        "sCurrentlyDisplayedConversationId so NOT showing notification," +
+                        " but playing soft sound. conversationId: " + conversationId);
+            }
+            playObservableConversationNotificationSound(ringtoneUri);
+            return;
+        }
+        state.mBaseRequestCode = state.mType;
+
+        // Set the delete intent (except for bundled wearable notifications, which are dismissed
+        // as a group, either from the wearable or when the summary notification is dismissed from
+        // the host device).
+        if (!(state instanceof BundledMessageNotificationState)) {
+            final PendingIntent clearIntent = state.getClearIntent();
+            notifBuilder.setDeleteIntent(clearIntent);
+        }
+
+        updateBuilderAudioVibrate(state, notifBuilder, silent, ringtoneUri, conversationId);
+
+        // Set the content intent
+        PendingIntent destinationIntent;
+        if (state.mConversationIds.size() > 1) {
+            // We have notifications for multiple conversation, go to the conversation list.
+            destinationIntent = UIIntents.get()
+                .getPendingIntentForConversationListActivity(context);
+        } else {
+            // We have a single conversation, go directly to that conversation.
+            destinationIntent = UIIntents.get()
+                    .getPendingIntentForConversationActivity(context,
+                            state.mConversationIds.first(),
+                            null /*draft*/);
+        }
+        notifBuilder.setContentIntent(destinationIntent);
+
+        // TODO: set based on contact coming from a favorite.
+        notifBuilder.setPriority(state.getPriority());
+
+        // Save the state of the notification in-progress so when the avatar is loaded,
+        // we can continue building the notification.
+        final NotificationCompat.Style notifStyle = state.build(notifBuilder);
+        state.mNotificationBuilder = notifBuilder;
+        state.mNotificationStyle = notifStyle;
+        if (!state.mPeople.isEmpty()) {
+            final Bundle people = new Bundle();
+            people.putStringArray(NotificationCompat.EXTRA_PEOPLE,
+                    state.mPeople.toArray(new String[state.mPeople.size()]));
+            notifBuilder.addExtras(people);
+        }
+
+        if (state.mParticipantAvatarsUris != null) {
+            final Uri avatarUri = state.mParticipantAvatarsUris.get(0);
+            final AvatarRequestDescriptor descriptor = new AvatarRequestDescriptor(avatarUri,
+                    sIconWidth, sIconHeight, OsUtil.isAtLeastL());
+            final MediaRequest<ImageResource> imageRequest = descriptor.buildSyncMediaRequest(
+                    context);
+
+            synchronized (sPendingNotifications) {
+                sPendingNotifications.add(state);
+            }
+
+            // Synchronously load the avatar.
+            final ImageResource avatarImage =
+                    MediaResourceManager.get().requestMediaResourceSync(imageRequest);
+            if (avatarImage != null) {
+                ImageResource avatarHiRes = null;
+                try {
+                    if (isWearCompanionAppInstalled()) {
+                        // For Wear users, we need to request a high-res avatar image to use as the
+                        // notification card background. If the sender has a contact photo, we'll
+                        // request the display photo from the Contacts provider. Otherwise, we ask
+                        // the local content provider for a hi-res version of the generic avatar
+                        // (e.g. letter with colored background).
+                        avatarHiRes = requestContactDisplayPhoto(context,
+                                getDisplayPhotoUri(avatarUri));
+                        if (avatarHiRes == null) {
+                            final AvatarRequestDescriptor hiResDesc =
+                                    new AvatarRequestDescriptor(avatarUri,
+                                    sWearableImageWidth,
+                                    sWearableImageHeight,
+                                    false /* cropToCircle */,
+                                    true /* isWearBackground */);
+                            avatarHiRes = MediaResourceManager.get().requestMediaResourceSync(
+                                    hiResDesc.buildSyncMediaRequest(context));
+                        }
+                    }
+
+                    // We have to make copies of the bitmaps to hand to the NotificationManager
+                    // because the bitmap in the ImageResource is managed and will automatically
+                    // get released.
+                    Bitmap avatarBitmap = Bitmap.createBitmap(avatarImage.getBitmap());
+                    Bitmap avatarHiResBitmap = (avatarHiRes != null) ?
+                            Bitmap.createBitmap(avatarHiRes.getBitmap()) : null;
+                    sendNotification(state, avatarBitmap, avatarHiResBitmap);
+                    return;
+                } finally {
+                    avatarImage.release();
+                    if (avatarHiRes != null) {
+                        avatarHiRes.release();
+                    }
+                }
+            }
+        }
+        // We have no avatar. Post the notification anyway.
+        sendNotification(state, null, null);
+    }
+
+    /**
+     * Returns the thumbnailUri from the avatar URI, or null if avatar URI does not have thumbnail.
+     */
+    private static Uri getThumbnailUri(final Uri avatarUri) {
+        Uri localUri = null;
+        final String avatarType = AvatarUriUtil.getAvatarType(avatarUri);
+        if (TextUtils.equals(avatarType, AvatarUriUtil.TYPE_LOCAL_RESOURCE_URI)) {
+            localUri = AvatarUriUtil.getPrimaryUri(avatarUri);
+        } else if (UriUtil.isLocalResourceUri(avatarUri)) {
+            localUri = avatarUri;
+        }
+        if (localUri != null && localUri.getAuthority().equals(ContactsContract.AUTHORITY)) {
+            // Contact photos are of the form: content://com.android.contacts/contacts/123/photo
+            final List<String> pathParts = localUri.getPathSegments();
+            if (pathParts.size() == 3 &&
+                    pathParts.get(2).equals(Contacts.Photo.CONTENT_DIRECTORY)) {
+                return localUri;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the displayPhotoUri from the avatar URI, or null if avatar URI
+     * does not have a displayPhotoUri.
+     */
+    private static Uri getDisplayPhotoUri(final Uri avatarUri) {
+        final Uri thumbnailUri = getThumbnailUri(avatarUri);
+        if (thumbnailUri == null) {
+            return null;
+        }
+        final List<String> originalPaths = thumbnailUri.getPathSegments();
+        final int originalPathsSize = originalPaths.size();
+        final StringBuilder newPathBuilder = new StringBuilder();
+        // Change content://com.android.contacts/contacts("_corp")/123/photo to
+        // content://com.android.contacts/contacts("_corp")/123/display_photo
+        for (int i = 0; i < originalPathsSize; i++) {
+            newPathBuilder.append('/');
+            if (i == 2) {
+                newPathBuilder.append(ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
+            } else {
+                newPathBuilder.append(originalPaths.get(i));
+            }
+        }
+        return thumbnailUri.buildUpon().path(newPathBuilder.toString()).build();
+    }
+
+    private static ImageResource requestContactDisplayPhoto(final Context context,
+            final Uri displayPhotoUri) {
+        final UriImageRequestDescriptor bgDescriptor =
+                new UriImageRequestDescriptor(displayPhotoUri,
+                        sWearableImageWidth,
+                        sWearableImageHeight,
+                        false, /* allowCompression */
+                        true, /* isStatic */
+                        false /* cropToCircle */,
+                        ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                        ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+        return MediaResourceManager.get().requestMediaResourceSync(
+                bgDescriptor.buildSyncMediaRequest(context));
+    }
+
+    private static void createMessageNotification(final boolean silent,
+            final String conversationId) {
+        final NotificationState state = MessageNotificationState.getNotificationState();
+        final boolean softSound = DataModel.get().isNewMessageObservable(conversationId);
+        if (state == null) {
+            cancel(PendingIntentConstants.SMS_NOTIFICATION_ID);
+            if (softSound && !TextUtils.isEmpty(conversationId)) {
+                final Uri ringtoneUri = getNotificationRingtoneUriForConversationId(conversationId);
+                playObservableConversationNotificationSound(ringtoneUri);
+            }
+            return;
+        }
+        processAndSend(state, silent, softSound);
+
+        // The rest of the logic here is for supporting Android Wear devices, specifically for when
+        // we are notifying about multiple conversations. In that case, the Inbox-style summary
+        // notification (which we already processed above) appears on the phone (as it always has),
+        // but wearables show per-conversation notifications, bundled together in a group.
+
+        // It is valid to replace a notification group with another group with fewer conversations,
+        // or even with one notification for a single conversation. In either case, we need to
+        // explicitly cancel any children from the old group which are not being notified about now.
+        final Context context = Factory.get().getApplicationContext();
+        final ConversationIdSet oldGroupChildIds = getGroupChildIds(context);
+        if (oldGroupChildIds != null && oldGroupChildIds.size() > 0) {
+            cancelStaleGroupChildren(oldGroupChildIds, state);
+        }
+
+        // Send per-conversation notifications (if there are multiple conversations).
+        final ConversationIdSet groupChildIds = new ConversationIdSet();
+        if (state instanceof MultiConversationNotificationState) {
+            for (final NotificationState child :
+                ((MultiConversationNotificationState) state).mChildren) {
+                processAndSend(child, true /* silent */, softSound);
+                if (child.mConversationIds != null) {
+                    groupChildIds.add(child.mConversationIds.first());
+                }
+            }
+        }
+
+        // Record the new set of group children.
+        writeGroupChildIds(context, groupChildIds);
+    }
+
+    private static void updateBuilderAudioVibrate(final NotificationState state,
+            final NotificationCompat.Builder notifBuilder, final boolean silent,
+            final Uri ringtoneUri, final String conversationId) {
+        int defaults = Notification.DEFAULT_LIGHTS;
+        if (!silent) {
+            final BuglePrefs prefs = Factory.get().getApplicationPrefs();
+            final long latestNotificationTimestamp = prefs.getLong(
+                    BuglePrefsKeys.LATEST_NOTIFICATION_MESSAGE_TIMESTAMP, Long.MIN_VALUE);
+            final long latestReceivedTimestamp = state.getLatestReceivedTimestamp();
+            prefs.putLong(
+                    BuglePrefsKeys.LATEST_NOTIFICATION_MESSAGE_TIMESTAMP,
+                    Math.max(latestNotificationTimestamp, latestReceivedTimestamp));
+            if (latestReceivedTimestamp > latestNotificationTimestamp) {
+                synchronized (mLock) {
+                    // Find out the last time we dinged for this conversation
+                    Long lastTime = sLastMessageDingTime.get(conversationId);
+                    if (sTimeBetweenDingsMs == 0) {
+                        sTimeBetweenDingsMs = BugleGservices.get().getInt(
+                                BugleGservicesKeys.NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS,
+                                BugleGservicesKeys.NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS_DEFAULT) *
+                                    1000;
+                    }
+                    if (lastTime == null
+                            || SystemClock.elapsedRealtime() - lastTime > sTimeBetweenDingsMs) {
+                        sLastMessageDingTime.put(conversationId, SystemClock.elapsedRealtime());
+                        notifBuilder.setSound(ringtoneUri);
+                        if (shouldVibrate(state)) {
+                            defaults |= Notification.DEFAULT_VIBRATE;
+                        }
+                    }
+                }
+            }
+        }
+        notifBuilder.setDefaults(defaults);
+    }
+
+    // TODO: this doesn't seem to be defined in NotificationCompat yet. Temporarily
+    // define it here until it makes its way from Notification -> NotificationCompat.
+    /**
+     * Notification category: incoming direct message (SMS, instant message, etc.).
+     */
+    private static final String CATEGORY_MESSAGE = "msg";
+
+    private static void sendNotification(final NotificationState notificationState,
+            final Bitmap avatarIcon, final Bitmap avatarHiRes) {
+        final Context context = Factory.get().getApplicationContext();
+        if (notificationState.mCanceled) {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "sendNotification: Notification already cancelled; dropping it");
+            }
+            return;
+        }
+
+        synchronized (sPendingNotifications) {
+            if (sPendingNotifications.contains(notificationState)) {
+                sPendingNotifications.remove(notificationState);
+            }
+        }
+
+        notificationState.mNotificationBuilder
+            .setSmallIcon(notificationState.getIcon())
+            .setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
+            .setColor(context.getResources().getColor(R.color.notification_accent_color))
+//            .setPublicVersion(null)    // TODO: when/if we ever support different
+                                         // text on the lockscreen, instead of "contents hidden"
+            .setCategory(CATEGORY_MESSAGE);
+
+        if (avatarIcon != null) {
+            notificationState.mNotificationBuilder.setLargeIcon(avatarIcon);
+        }
+
+        if (notificationState.mParticipantContactUris != null &&
+                notificationState.mParticipantContactUris.size() > 0) {
+            for (final Uri contactUri : notificationState.mParticipantContactUris) {
+                notificationState.mNotificationBuilder.addPerson(contactUri.toString());
+            }
+        }
+
+        final Uri attachmentUri = notificationState.getAttachmentUri();
+        final String attachmentType = notificationState.getAttachmentType();
+        Bitmap attachmentBitmap = null;
+
+        // For messages with photo/video attachment, request an image to show in the notification.
+        if (attachmentUri != null && notificationState.mNotificationStyle != null &&
+                (notificationState.mNotificationStyle instanceof
+                        NotificationCompat.BigPictureStyle) &&
+                        (ContentType.isImageType(attachmentType) ||
+                                ContentType.isVideoType(attachmentType))) {
+            final boolean isVideo = ContentType.isVideoType(attachmentType);
+
+            MediaRequest<ImageResource> imageRequest;
+            if (isVideo) {
+                Assert.isTrue(VideoThumbnailRequest.shouldShowIncomingVideoThumbnails());
+                final MessagePartVideoThumbnailRequestDescriptor videoDescriptor =
+                        new MessagePartVideoThumbnailRequestDescriptor(attachmentUri);
+                imageRequest = videoDescriptor.buildSyncMediaRequest(context);
+            } else {
+                final UriImageRequestDescriptor imageDescriptor =
+                        new UriImageRequestDescriptor(attachmentUri,
+                            sWearableImageWidth,
+                            sWearableImageHeight,
+                            false /* allowCompression */,
+                            true /* isStatic */,
+                            false /* cropToCircle */,
+                            ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                            ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+                imageRequest = imageDescriptor.buildSyncMediaRequest(context);
+            }
+            final ImageResource imageResource =
+                    MediaResourceManager.get().requestMediaResourceSync(imageRequest);
+            if (imageResource != null) {
+                try {
+                    // Copy the bitmap, because the one in the ImageResource is managed by
+                    // MediaResourceManager.
+                    Bitmap imageResourceBitmap = imageResource.getBitmap();
+                    Config config = imageResourceBitmap.getConfig();
+
+                    // Make sure our bitmap has a valid format.
+                    if (config == null) {
+                        config = Bitmap.Config.ARGB_8888;
+                    }
+                    attachmentBitmap = imageResourceBitmap.copy(config, true);
+                } finally {
+                    imageResource.release();
+                }
+            }
+        }
+
+        fireOffNotification(notificationState, attachmentBitmap, avatarIcon, avatarHiRes);
+    }
+
+    private static void fireOffNotification(final NotificationState notificationState,
+            final Bitmap attachmentBitmap, final Bitmap avatarBitmap, Bitmap avatarHiResBitmap) {
+        if (notificationState.mCanceled) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Firing off notification, but notification already canceled");
+            }
+            return;
+        }
+
+        final Context context = Factory.get().getApplicationContext();
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "MMS picture loaded, bitmap: " + attachmentBitmap);
+        }
+
+        final NotificationCompat.Builder notifBuilder = notificationState.mNotificationBuilder;
+        notifBuilder.setStyle(notificationState.mNotificationStyle);
+        notifBuilder.setColor(context.getResources().getColor(R.color.notification_accent_color));
+
+        final WearableExtender wearableExtender = new WearableExtender();
+        setWearableGroupOptions(notifBuilder, notificationState);
+
+        if (avatarHiResBitmap != null) {
+            wearableExtender.setBackground(avatarHiResBitmap);
+        } else if (avatarBitmap != null) {
+            // Nothing to do here; we already set avatarBitmap as the notification icon
+        } else {
+            final Bitmap defaultBackground = BitmapFactory.decodeResource(
+                    context.getResources(), R.drawable.bg_sms);
+            wearableExtender.setBackground(defaultBackground);
+        }
+
+        if (notificationState instanceof MultiMessageNotificationState) {
+            if (attachmentBitmap != null) {
+                // When we've got a picture attachment, we do some switcheroo trickery. When
+                // the notification is expanded, we show the picture as a bigPicture. The small
+                // icon shows the sender's avatar. When that same notification is collapsed, the
+                // picture is shown in the location where the avatar is normally shown. The lines
+                // below make all that happen.
+
+                // Here we're taking the picture attachment and making a small, scaled, center
+                // cropped version of the picture we can stuff into the place where the avatar
+                // goes when the notification is collapsed.
+                final Bitmap smallBitmap = ImageUtils.scaleCenterCrop(attachmentBitmap, sIconWidth,
+                        sIconHeight);
+                ((NotificationCompat.BigPictureStyle) notificationState.mNotificationStyle)
+                    .bigPicture(attachmentBitmap)
+                    .bigLargeIcon(avatarBitmap);
+                notificationState.mNotificationBuilder.setLargeIcon(smallBitmap);
+
+                // Add a wearable page with no visible card so you can more easily see the photo.
+                final NotificationCompat.Builder photoPageNotifBuilder =
+                        new NotificationCompat.Builder(Factory.get().getApplicationContext());
+                final WearableExtender photoPageWearableExtender = new WearableExtender();
+                photoPageWearableExtender.setHintShowBackgroundOnly(true);
+                if (attachmentBitmap != null) {
+                    final Bitmap wearBitmap = ImageUtils.scaleCenterCrop(attachmentBitmap,
+                            sWearableImageWidth, sWearableImageHeight);
+                    photoPageWearableExtender.setBackground(wearBitmap);
+                }
+                photoPageNotifBuilder.extend(photoPageWearableExtender);
+                wearableExtender.addPage(photoPageNotifBuilder.build());
+            }
+
+            maybeAddWearableConversationLog(wearableExtender,
+                    (MultiMessageNotificationState) notificationState);
+            addDownloadMmsAction(notifBuilder, wearableExtender, notificationState);
+            addWearableVoiceReplyAction(wearableExtender, notificationState);
+        }
+
+        // Apply the wearable options and build & post the notification
+        notifBuilder.extend(wearableExtender);
+        doNotify(notifBuilder.build(), notificationState);
+    }
+
+    private static void setWearableGroupOptions(final NotificationCompat.Builder notifBuilder,
+            final NotificationState notificationState) {
+        final String groupKey = "groupkey";
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "Group key (for wearables)=" + groupKey);
+        }
+        if (notificationState instanceof MultiConversationNotificationState) {
+            notifBuilder.setGroup(groupKey).setGroupSummary(true);
+        } else if (notificationState instanceof BundledMessageNotificationState) {
+            final int order = ((BundledMessageNotificationState) notificationState).mGroupOrder;
+            // Convert the order to a zero-padded string ("00", "01", "02", etc).
+            // The Wear library orders notifications within a bundle lexicographically
+            // by the sort key, hence the need for zeroes to preserve the ordering.
+            final String sortKey = String.format(Locale.US, "%02d", order);
+            notifBuilder.setGroup(groupKey).setSortKey(sortKey);
+        }
+    }
+
+    private static void maybeAddWearableConversationLog(
+            final WearableExtender wearableExtender,
+            final MultiMessageNotificationState notificationState) {
+        if (!isWearCompanionAppInstalled()) {
+            return;
+        }
+        final String convId = notificationState.mConversationIds.first();
+        ConversationLineInfo convInfo = notificationState.mConvList.mConvInfos.get(0);
+        final Notification page = MessageNotificationState.buildConversationPageForWearable(
+                convId,
+                convInfo.mParticipantCount);
+        if (page != null) {
+            wearableExtender.addPage(page);
+        }
+    }
+
+    private static void addWearableVoiceReplyAction(
+            final WearableExtender wearableExtender, final NotificationState notificationState) {
+        if (!(notificationState instanceof MultiMessageNotificationState)) {
+            return;
+        }
+        final MultiMessageNotificationState multiMessageNotificationState =
+                (MultiMessageNotificationState) notificationState;
+        final Context context = Factory.get().getApplicationContext();
+
+        final String conversationId = notificationState.mConversationIds.first();
+        final ConversationLineInfo convInfo =
+                multiMessageNotificationState.mConvList.mConvInfos.get(0);
+        final String selfId = convInfo.mSelfParticipantId;
+
+        final boolean requiresMms =
+                MmsSmsUtils.getRequireMmsForEmailAddress(
+                        convInfo.mIncludeEmailAddress, convInfo.mSubId) ||
+                (convInfo.mIsGroup && MmsUtils.groupMmsEnabled(convInfo.mSubId));
+
+        final int requestCode = multiMessageNotificationState.getReplyIntentRequestCode();
+        final PendingIntent replyPendingIntent = UIIntents.get()
+                .getPendingIntentForSendingMessageToConversation(context,
+                        conversationId, selfId, requiresMms, requestCode);
+
+        final int replyLabelRes = requiresMms ? R.string.notification_reply_via_mms :
+            R.string.notification_reply_via_sms;
+
+        final NotificationCompat.Action.Builder actionBuilder =
+                new NotificationCompat.Action.Builder(R.drawable.ic_wear_reply,
+                        context.getString(replyLabelRes), replyPendingIntent);
+        final String[] choices = context.getResources().getStringArray(
+                R.array.notification_reply_choices);
+        final RemoteInput remoteInput = new RemoteInput.Builder(Intent.EXTRA_TEXT).setLabel(
+                context.getString(R.string.notification_reply_prompt)).
+                setChoices(choices)
+                .build();
+        actionBuilder.addRemoteInput(remoteInput);
+        wearableExtender.addAction(actionBuilder.build());
+    }
+
+    private static void addDownloadMmsAction(final NotificationCompat.Builder notifBuilder,
+            final WearableExtender wearableExtender, final NotificationState notificationState) {
+        if (!(notificationState instanceof MultiMessageNotificationState)) {
+            return;
+        }
+        final MultiMessageNotificationState multiMessageNotificationState =
+                (MultiMessageNotificationState) notificationState;
+        final ConversationLineInfo convInfo =
+                multiMessageNotificationState.mConvList.mConvInfos.get(0);
+        if (!convInfo.getDoesLatestMessageNeedDownload()) {
+            return;
+        }
+        final String messageId = convInfo.getLatestMessageId();
+        if (messageId == null) {
+            // No message Id, no download for you
+            return;
+        }
+        final Context context = Factory.get().getApplicationContext();
+        final PendingIntent downloadPendingIntent =
+                RedownloadMmsAction.getPendingIntentForRedownloadMms(context, messageId);
+
+        final NotificationCompat.Action.Builder actionBuilder =
+                new NotificationCompat.Action.Builder(R.drawable.ic_file_download_light,
+                        context.getString(R.string.notification_download_mms),
+                        downloadPendingIntent);
+        final NotificationCompat.Action downloadAction = actionBuilder.build();
+        notifBuilder.addAction(downloadAction);
+
+        // Support the action on a wearable device as well
+        wearableExtender.addAction(downloadAction);
+    }
+
+    private static synchronized void doNotify(final Notification notification,
+            final NotificationState notificationState) {
+        if (notification == null) {
+            return;
+        }
+        final int type = notificationState.mType;
+        final ConversationIdSet conversationIds = notificationState.mConversationIds;
+        final boolean isBundledNotification =
+                (notificationState instanceof BundledMessageNotificationState);
+
+        // Mark the notification as finished
+        notificationState.mCanceled = true;
+
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+        // Only need conversationId for tags with a single conversation.
+        String conversationId = null;
+        if (conversationIds != null && conversationIds.size() == 1) {
+            conversationId = conversationIds.first();
+        }
+        final String notificationTag = buildNotificationTag(type,
+                conversationId, isBundledNotification);
+
+        notification.flags |= Notification.FLAG_AUTO_CANCEL;
+        notification.defaults |= Notification.DEFAULT_LIGHTS;
+
+        notificationManager.notify(notificationTag, type, notification);
+
+        LogUtil.i(TAG, "Notifying for conversation " + conversationId + "; "
+                + "tag = " + notificationTag + ", type = " + type);
+    }
+
+    // This is the message string used in each line of an inboxStyle notification.
+    // TODO: add attachment type
+    static CharSequence formatInboxMessage(final String sender,
+            final CharSequence message, final Uri attachmentUri, final String attachmentType) {
+      final Context context = Factory.get().getApplicationContext();
+      final TextAppearanceSpan notificationSenderSpan = new TextAppearanceSpan(
+              context, R.style.NotificationSenderText);
+
+      final TextAppearanceSpan notificationTertiaryText = new TextAppearanceSpan(
+              context, R.style.NotificationTertiaryText);
+
+      final SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
+      if (!TextUtils.isEmpty(sender)) {
+          spannableStringBuilder.append(sender);
+          spannableStringBuilder.setSpan(notificationSenderSpan, 0, sender.length(), 0);
+      }
+      final String separator = context.getString(R.string.notification_separator);
+
+      if (!TextUtils.isEmpty(message)) {
+          if (spannableStringBuilder.length() > 0) {
+              spannableStringBuilder.append(separator);
+          }
+          final int start = spannableStringBuilder.length();
+          spannableStringBuilder.append(message);
+          spannableStringBuilder.setSpan(notificationTertiaryText, start,
+                  start + message.length(), 0);
+      }
+      if (attachmentUri != null) {
+          if (spannableStringBuilder.length() > 0) {
+              spannableStringBuilder.append(separator);
+          }
+          spannableStringBuilder.append(formatAttachmentTag(null, attachmentType));
+      }
+      return spannableStringBuilder;
+    }
+
+    protected static CharSequence buildColonSeparatedMessage(
+            final String title, final CharSequence content, final Uri attachmentUri,
+            final String attachmentType) {
+        return buildBoldedMessage(title, content, attachmentUri, attachmentType,
+                R.string.notification_ticker_separator);
+    }
+
+    protected static CharSequence buildSpaceSeparatedMessage(
+            final String title, final CharSequence content, final Uri attachmentUri,
+            final String attachmentType) {
+        return buildBoldedMessage(title, content, attachmentUri, attachmentType,
+                R.string.notification_space_separator);
+    }
+
+    /**
+     * buildBoldedMessage - build a formatted message where the title is bold, there's a
+     * separator, then the message.
+     */
+    private static CharSequence buildBoldedMessage(
+            final String title, final CharSequence message, final Uri attachmentUri,
+            final String attachmentType,
+            final int separatorId) {
+        final Context context = Factory.get().getApplicationContext();
+        final SpannableStringBuilder spanBuilder = new SpannableStringBuilder();
+
+        // Boldify the title (which is the sender's name)
+        if (!TextUtils.isEmpty(title)) {
+            spanBuilder.append(title);
+            spanBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, title.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+        if (!TextUtils.isEmpty(message)) {
+            if (spanBuilder.length() > 0) {
+                spanBuilder.append(context.getString(separatorId));
+            }
+            spanBuilder.append(message);
+        }
+        if (attachmentUri != null) {
+            if (spanBuilder.length() > 0) {
+                final String separator = context.getString(R.string.notification_separator);
+                spanBuilder.append(separator);
+            }
+            spanBuilder.append(formatAttachmentTag(null, attachmentType));
+        }
+        return spanBuilder;
+    }
+
+    static CharSequence formatAttachmentTag(final String author, final String attachmentType) {
+        final Context context = Factory.get().getApplicationContext();
+            final TextAppearanceSpan notificationSecondaryText = new TextAppearanceSpan(
+                    context, R.style.NotificationSecondaryText);
+        final SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
+        if (!TextUtils.isEmpty(author)) {
+            final TextAppearanceSpan notificationSenderSpan = new TextAppearanceSpan(
+                    context, R.style.NotificationSenderText);
+            spannableStringBuilder.append(author);
+            spannableStringBuilder.setSpan(notificationSenderSpan, 0, author.length(), 0);
+            final String separator = context.getString(R.string.notification_separator);
+            spannableStringBuilder.append(separator);
+        }
+        final int start = spannableStringBuilder.length();
+        // The default attachment type is an image, since that's what was originally
+        // supported. When there's no content type, assume it's an image.
+        int message = R.string.notification_picture;
+        if (ContentType.isAudioType(attachmentType)) {
+            message = R.string.notification_audio;
+        } else if (ContentType.isVideoType(attachmentType)) {
+            message = R.string.notification_video;
+        } else if (ContentType.isVCardType(attachmentType)) {
+            message = R.string.notification_vcard;
+        }
+        spannableStringBuilder.append(context.getText(message));
+        spannableStringBuilder.setSpan(notificationSecondaryText, start,
+                spannableStringBuilder.length(), 0);
+        return spannableStringBuilder;
+    }
+
+    /**
+     * Play the observable conversation notification sound (it's the regular notification sound, but
+     * played at half-volume)
+     */
+    private static void playObservableConversationNotificationSound(final Uri ringtoneUri) {
+        final Context context = Factory.get().getApplicationContext();
+        final AudioManager audioManager = (AudioManager) context
+                .getSystemService(Context.AUDIO_SERVICE);
+        final boolean silenced =
+                audioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
+        if (silenced) {
+             return;
+        }
+
+        final NotificationPlayer player = new NotificationPlayer(LogUtil.BUGLE_TAG);
+        player.play(ringtoneUri, false,
+                AudioManager.STREAM_NOTIFICATION,
+                OBSERVABLE_CONVERSATION_NOTIFICATION_VOLUME);
+
+        // Stop the sound after five seconds to handle continuous ringtones
+        ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                player.stop();
+            }
+        }, 5000);
+    }
+
+    public static boolean isWearCompanionAppInstalled() {
+        boolean found = false;
+        try {
+            Factory.get().getApplicationContext().getPackageManager()
+                    .getPackageInfo(WEARABLE_COMPANION_APP_PACKAGE, 0);
+            found = true;
+        } catch (final NameNotFoundException e) {
+            // Ignore; found is already false
+        }
+        return found;
+    }
+
+    /**
+     * When we go to the conversation list, call this to mark all messages as seen. That means
+     * we won't show a notification again for the same message.
+     */
+    public static void markAllMessagesAsSeen() {
+        MarkAsSeenAction.markAllAsSeen();
+        resetLastMessageDing(null);     // reset the ding timeout for all conversations
+    }
+
+    /**
+     * When we open a particular conversation, call this to mark all messages as read.
+     */
+    public static void markMessagesAsRead(final String conversationId) {
+        MarkAsReadAction.markAsRead(conversationId);
+        resetLastMessageDing(conversationId);
+    }
+
+    /**
+     * Returns the conversation ids of all active, grouped notifications, or
+     * {code null} if no notifications are currently active and grouped.
+     */
+    private static ConversationIdSet getGroupChildIds(final Context context) {
+        final String prefKey = context.getString(R.string.notifications_group_children_key);
+        final String groupChildIdsText = BuglePrefs.getApplicationPrefs().getString(prefKey, "");
+        if (!TextUtils.isEmpty(groupChildIdsText)) {
+            return ConversationIdSet.createSet(groupChildIdsText);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Records the conversation ids of the currently active grouped notifications.
+     */
+    private static void writeGroupChildIds(final Context context,
+            final ConversationIdSet childIds) {
+        final ConversationIdSet oldChildIds = getGroupChildIds(context);
+        if (childIds.equals(oldChildIds)) {
+            return;
+        }
+        final String prefKey = context.getString(R.string.notifications_group_children_key);
+        BuglePrefs.getApplicationPrefs().putString(prefKey, childIds.getDelimitedString());
+    }
+
+    /**
+     * Reset the timer for a notification ding on a particular conversation or all conversations.
+     */
+    public static void resetLastMessageDing(final String conversationId) {
+        synchronized (mLock) {
+            if (TextUtils.isEmpty(conversationId)) {
+                // reset all conversation dings
+                sLastMessageDingTime.clear();
+            } else {
+                sLastMessageDingTime.remove(conversationId);
+            }
+        }
+    }
+
+    public static void notifyEmergencySmsFailed(final String emergencyNumber,
+            final String conversationId) {
+        final Context context = Factory.get().getApplicationContext();
+
+        final CharSequence line1 = MessageNotificationState.applyWarningTextColor(context,
+                context.getString(R.string.notification_emergency_send_failure_line1,
+                emergencyNumber));
+        final String line2 = context.getString(R.string.notification_emergency_send_failure_line2,
+                emergencyNumber);
+        final PendingIntent destinationIntent = UIIntents.get()
+                .getPendingIntentForConversationActivity(context, conversationId, null /* draft */);
+
+        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+        builder.setTicker(line1)
+                .setContentTitle(line1)
+                .setContentText(line2)
+                .setStyle(new NotificationCompat.BigTextStyle(builder).bigText(line2))
+                .setSmallIcon(R.drawable.ic_failed_light)
+                .setContentIntent(destinationIntent)
+                .setSound(UriUtil.getUriForResourceId(context, R.raw.message_failure));
+
+        final String tag = context.getPackageName() + ":emergency_sms_error";
+        NotificationManagerCompat.from(context).notify(
+                tag,
+                PendingIntentConstants.MSG_SEND_ERROR,
+                builder.build());
+    }
+}
+
diff --git a/src/com/android/messaging/datamodel/BugleRecipientEntry.java b/src/com/android/messaging/datamodel/BugleRecipientEntry.java
new file mode 100644
index 0000000..2a9e5ff
--- /dev/null
+++ b/src/com/android/messaging/datamodel/BugleRecipientEntry.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.ex.chips.RecipientEntry;
+
+/**
+ * An extension of RecipientEntry for Bugle's use since Bugle uses phone numbers to identify
+ * participants / recipients instead of contact ids. This allows the user to send to multiple
+ * phone numbers of the same contact.
+ */
+public class BugleRecipientEntry extends RecipientEntry {
+
+    protected BugleRecipientEntry(final int entryType, final String displayName,
+            final String destination, final int destinationType, final String destinationLabel,
+            final long contactId, final Long directoryId, final long dataId,
+            final Uri photoThumbnailUri, final boolean isFirstLevel, final boolean isValid,
+            final String lookupKey) {
+        super(entryType, displayName, destination, destinationType, destinationLabel, contactId,
+                directoryId, dataId, photoThumbnailUri, isFirstLevel, isValid, lookupKey);
+    }
+
+    public static BugleRecipientEntry constructTopLevelEntry(final String displayName,
+            final int displayNameSource, final String destination, final int destinationType,
+            final String destinationLabel, final long contactId, final Long directoryId,
+            final long dataId, final String thumbnailUriAsString, final boolean isValid,
+            final String lookupKey) {
+        return new BugleRecipientEntry(ENTRY_TYPE_PERSON, displayName, destination, destinationType,
+                destinationLabel, contactId, directoryId, dataId, (thumbnailUriAsString != null
+                ? Uri.parse(thumbnailUriAsString) : null), true, isValid, lookupKey);
+    }
+
+    public static BugleRecipientEntry constructSecondLevelEntry(final String displayName,
+            final int displayNameSource, final String destination, final int destinationType,
+            final String destinationLabel, final long contactId, final Long directoryId,
+            final long dataId, final String thumbnailUriAsString, final boolean isValid,
+            final String lookupKey) {
+        return new BugleRecipientEntry(ENTRY_TYPE_PERSON, displayName, destination, destinationType,
+                destinationLabel, contactId, directoryId, dataId, (thumbnailUriAsString != null
+                ? Uri.parse(thumbnailUriAsString) : null), false, isValid, lookupKey);
+    }
+
+    @Override
+    public boolean isSamePerson(final RecipientEntry entry) {
+        return getDestination() != null && entry.getDestination() != null &&
+                TextUtils.equals(getDestination(), entry.getDestination());
+    }
+}
diff --git a/src/com/android/messaging/datamodel/ConversationImagePartsView.java b/src/com/android/messaging/datamodel/ConversationImagePartsView.java
new file mode 100644
index 0000000..70ba381
--- /dev/null
+++ b/src/com/android/messaging/datamodel/ConversationImagePartsView.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.provider.BaseColumns;
+
+import com.android.ex.photo.provider.PhotoContract.PhotoViewColumns;
+
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.util.ContentType;
+
+/**
+ * View for the image parts for the conversation. It is used to provide the photoviewer with a
+ * a data source for all the photos in a conversation, so that the photoviewer can support paging
+ * through all the photos of the conversation. The columns of the view are a superset of
+ * {@link com.android.ex.photo.provider.PhotoContract.PhotoViewColumns}.
+ */
+public class ConversationImagePartsView {
+    private static final String VIEW_NAME = "conversation_image_parts_view";
+
+    private static final String CREATE_SQL = "CREATE VIEW " +
+            VIEW_NAME + " AS SELECT "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.CONVERSATION_ID
+            + " as " + Columns.CONVERSATION_ID + ", "
+            + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.CONTENT_URI
+            + " as " + Columns.URI + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FULL_NAME
+            + " as " + Columns.SENDER_FULL_NAME + ", "
+            + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.CONTENT_URI
+            + " as " + Columns.CONTENT_URI + ", "
+            // Use NULL as the thumbnail uri
+            + " NULL as " + Columns.THUMBNAIL_URI + ", "
+            + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.CONTENT_TYPE
+            + " as " + Columns.CONTENT_TYPE + ", "
+            //
+            // Columns in addition to those specified by PhotoContract
+            //
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION
+            + " as " + Columns.DISPLAY_DESTINATION + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP
+            + " as " + Columns.RECEIVED_TIMESTAMP + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS
+            + " as " + Columns.STATUS + " "
+
+            + " FROM " + DatabaseHelper.MESSAGES_TABLE + " LEFT JOIN " + DatabaseHelper.PARTS_TABLE
+            + " ON (" + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns._ID
+            + "=" + DatabaseHelper.PARTS_TABLE + "." + PartColumns.MESSAGE_ID + ") "
+            + " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE + " ON ("
+            + DatabaseHelper.MESSAGES_TABLE + '.' +  MessageColumns.SENDER_PARTICIPANT_ID
+            + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns._ID + ")"
+
+            // "content_type like 'image/%'"
+            + " WHERE " + DatabaseHelper.PARTS_TABLE + "." + PartColumns.CONTENT_TYPE
+            + " like '" + ContentType.IMAGE_PREFIX + "%'"
+
+            + " ORDER BY "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP + " ASC, "
+            + DatabaseHelper.PARTS_TABLE + '.' + PartColumns._ID + " ASC";
+
+    static class Columns implements BaseColumns {
+        static final String CONVERSATION_ID = MessageColumns.CONVERSATION_ID;
+        static final String URI = PhotoViewColumns.URI;
+        static final String SENDER_FULL_NAME = PhotoViewColumns.NAME;
+        static final String CONTENT_URI = PhotoViewColumns.CONTENT_URI;
+        static final String THUMBNAIL_URI = PhotoViewColumns.THUMBNAIL_URI;
+        static final String CONTENT_TYPE = PhotoViewColumns.CONTENT_TYPE;
+        // Columns in addition to those specified by PhotoContract
+        static final String DISPLAY_DESTINATION = ParticipantColumns.DISPLAY_DESTINATION;
+        static final String RECEIVED_TIMESTAMP = MessageColumns.RECEIVED_TIMESTAMP;
+        static final String STATUS = MessageColumns.STATUS;
+    }
+
+    public interface PhotoViewQuery {
+        public final String[] PROJECTION = {
+            PhotoViewColumns.URI,
+            PhotoViewColumns.NAME,
+            PhotoViewColumns.CONTENT_URI,
+            PhotoViewColumns.THUMBNAIL_URI,
+            PhotoViewColumns.CONTENT_TYPE,
+            // Columns in addition to those specified by PhotoContract
+            Columns.DISPLAY_DESTINATION,
+            Columns.RECEIVED_TIMESTAMP,
+            Columns.STATUS,
+        };
+
+        public final int INDEX_URI = 0;
+        public final int INDEX_SENDER_FULL_NAME = 1;
+        public final int INDEX_CONTENT_URI = 2;
+        public final int INDEX_THUMBNAIL_URI = 3;
+        public final int INDEX_CONTENT_TYPE = 4;
+        // Columns in addition to those specified by PhotoContract
+        public final int INDEX_DISPLAY_DESTINATION = 5;
+        public final int INDEX_RECEIVED_TIMESTAMP = 6;
+        public final int INDEX_STATUS = 7;
+    }
+
+    static final String getViewName() {
+        return VIEW_NAME;
+    }
+
+    static final String getCreateSql() {
+        return CREATE_SQL;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/CursorQueryData.java b/src/com/android/messaging/datamodel/CursorQueryData.java
new file mode 100644
index 0000000..3e6a656
--- /dev/null
+++ b/src/com/android/messaging/datamodel/CursorQueryData.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+
+import com.android.messaging.util.Assert;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Holds parameters and data (such as content URI) for performing queries on the content provider.
+ * This class could then be used to perform a query using either a BoundCursorLoader or querying
+ * on the content resolver directly.
+ *
+ * This class is used for cases where the way to load a cursor is not fixed. For example,
+ * when using ContactUtil to query for phone numbers, the ContactPickerFragment wants to use
+ * a CursorLoader to asynchronously load the data and tie in nicely with its data binding
+ * paradigm, whereas ContactRecipientAdapter wants to synchronously perform the query on the
+ * worker thread.
+ */
+public class CursorQueryData {
+    protected final Uri mUri;
+    protected final String[] mProjection;
+    protected final String mSelection;
+    protected final String[] mSelectionArgs;
+    protected final String mSortOrder;
+    protected final Context mContext;
+
+    public CursorQueryData(final Context context, final Uri uri, final String[] projection,
+            final String selection, final String[] selectionArgs, final String sortOrder) {
+        mContext = context;
+        mUri = uri;
+        mProjection = projection;
+        mSelection = selection;
+        mSelectionArgs = selectionArgs;
+        mSortOrder = sortOrder;
+    }
+
+    public BoundCursorLoader createBoundCursorLoader(final String bindingId) {
+        return new BoundCursorLoader(bindingId, mContext, mUri, mProjection, mSelection,
+                mSelectionArgs, mSortOrder);
+    }
+
+    public Cursor performSynchronousQuery() {
+        Assert.isNotMainThread();
+        if (mUri == null) {
+            // See {@link #getEmptyQueryData}
+            return null;
+        } else {
+            return mContext.getContentResolver().query(mUri, mProjection, mSelection,
+                    mSelectionArgs, mSortOrder);
+        }
+    }
+
+    @VisibleForTesting
+    public Uri getUri() {
+        return mUri;
+    }
+
+    /**
+     * Representation of an invalid query. {@link #performSynchronousQuery} will return
+     * a null Cursor.
+     */
+    public static CursorQueryData getEmptyQueryData() {
+        return new CursorQueryData(null, null, null, null, null, null);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/DataModel.java b/src/com/android/messaging/datamodel/DataModel.java
new file mode 100644
index 0000000..b606c72
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DataModel.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.action.Action;
+import com.android.messaging.datamodel.action.ActionService;
+import com.android.messaging.datamodel.action.BackgroundWorker;
+import com.android.messaging.datamodel.data.BlockedParticipantsData;
+import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ContactPickerData;
+import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.LaunchConversationData;
+import com.android.messaging.datamodel.data.LaunchConversationData.LaunchConversationDataListener;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantListItemData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
+import com.android.messaging.datamodel.data.PeopleOptionsItemData;
+import com.android.messaging.datamodel.data.SettingsData;
+import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.datamodel.data.VCardContactItemData;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+
+public abstract class DataModel {
+    private String mFocusedConversation;
+    private boolean mConversationListScrolledToNewestConversation;
+
+    public static DataModel get() {
+        return Factory.get().getDataModel();
+    }
+
+    public static final void startActionService(final Action action) {
+        get().getActionService().startAction(action);
+    }
+
+    public static final void scheduleAction(final Action action,
+            final int code, final long delayMs) {
+        get().getActionService().scheduleAction(action, code, delayMs);
+    }
+
+    public abstract ConversationListData createConversationListData(final Context context,
+            final ConversationListDataListener listener, final boolean archivedMode);
+
+    public abstract ConversationData createConversationData(final Context context,
+            final ConversationDataListener listener, final String conversationId);
+
+    public abstract ContactListItemData createContactListItemData();
+
+    public abstract ContactPickerData createContactPickerData(final Context context,
+            final ContactPickerDataListener listener);
+
+    public abstract MediaPickerData createMediaPickerData(final Context context);
+
+    public abstract GalleryGridItemData createGalleryGridItemData();
+
+    public abstract LaunchConversationData createLaunchConversationData(
+            LaunchConversationDataListener listener);
+
+    public abstract PeopleOptionsItemData createPeopleOptionsItemData(final Context context);
+
+    public abstract PeopleAndOptionsData createPeopleAndOptionsData(final String conversationId,
+            final Context context, final PeopleAndOptionsDataListener listener);
+
+    public abstract VCardContactItemData createVCardContactItemData(final Context context,
+            final MessagePartData data);
+
+    public abstract VCardContactItemData createVCardContactItemData(final Context context,
+            final Uri vCardUri);
+
+    public abstract ParticipantListItemData createParticipantListItemData(
+            final ParticipantData participant);
+
+    public abstract BlockedParticipantsData createBlockedParticipantsData(Context context,
+            BlockedParticipantsDataListener listener);
+
+    public abstract SubscriptionListData createSubscriptonListData(Context context);
+
+    public abstract SettingsData createSettingsData(Context context, SettingsDataListener listener);
+
+    public abstract DraftMessageData createDraftMessageData(String conversationId);
+
+    public abstract ActionService getActionService();
+
+    public abstract BackgroundWorker getBackgroundWorkerForActionService();
+
+    @DoesNotRunOnMainThread
+    public abstract DatabaseWrapper getDatabase();
+
+    // Allow DataModel to coordinate with activity lifetime events.
+    public abstract void onActivityResume();
+
+    abstract void onCreateTables(final SQLiteDatabase db);
+
+    public void setFocusedConversation(final String conversationId) {
+        mFocusedConversation = conversationId;
+    }
+
+    public boolean isFocusedConversation(final String conversationId) {
+        return !TextUtils.isEmpty(mFocusedConversation)
+                && TextUtils.equals(mFocusedConversation, conversationId);
+    }
+
+    public void setConversationListScrolledToNewestConversation(
+            final boolean scrolledToNewestConversation) {
+        mConversationListScrolledToNewestConversation = scrolledToNewestConversation;
+    }
+
+    public boolean isConversationListScrolledToNewestConversation() {
+        return mConversationListScrolledToNewestConversation;
+    }
+
+    /**
+     * If a new message is received in the specified conversation, will the user be able to
+     * observe it in some UI within the app?
+     * @param conversationId conversation with the new incoming message
+     */
+    public boolean isNewMessageObservable(final String conversationId) {
+        return isConversationListScrolledToNewestConversation()
+                || isFocusedConversation(conversationId);
+    }
+
+    public abstract void onApplicationCreated();
+
+    public abstract SyncManager getSyncManager();
+}
diff --git a/src/com/android/messaging/datamodel/DataModelException.java b/src/com/android/messaging/datamodel/DataModelException.java
new file mode 100644
index 0000000..7084438
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DataModelException.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+public class DataModelException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    private static final int FIRST = 100;
+
+    // ERRORS GENERATED INTERNALLY BY DATA MODEL.
+
+    // ERRORS RELATED WITH SMS.
+    public static final int ERROR_SMS_TEMPORARY_FAILURE = 116;
+    public static final int ERROR_SMS_PERMANENT_FAILURE = 117;
+    public static final int ERROR_MMS_TEMPORARY_FAILURE = 118;
+    public static final int ERROR_MMS_PERMANENT_UNKNOWN_FAILURE = 119;
+
+    // Request expired.
+    public static final int ERROR_EXPIRED = 120;
+    // Request canceled by user.
+    public static final int ERROR_CANCELED = 121;
+
+    public static final int ERROR_MOBILE_DATA_DISABLED  = 123;
+    public static final int ERROR_MMS_SERVICE_BLOCKED   = 124;
+    public static final int ERROR_MMS_INVALID_ADDRESS   = 125;
+    public static final int ERROR_MMS_NETWORK_PROBLEM   = 126;
+    public static final int ERROR_MMS_MESSAGE_NOT_FOUND = 127;
+    public static final int ERROR_MMS_MESSAGE_FORMAT_CORRUPT = 128;
+    public static final int ERROR_MMS_CONTENT_NOT_ACCEPTED = 129;
+    public static final int ERROR_MMS_MESSAGE_NOT_SUPPORTED = 130;
+    public static final int ERROR_MMS_REPLY_CHARGING_ERROR = 131;
+    public static final int ERROR_MMS_ADDRESS_HIDING_NOT_SUPPORTED = 132;
+    public static final int ERROR_MMS_LACK_OF_PREPAID = 133;
+    public static final int ERROR_MMS_CAN_NOT_PERSIST = 134;
+    public static final int ERROR_MMS_NO_AVAILABLE_APN = 135;
+    public static final int ERROR_MMS_INVALID_MESSAGE_TO_SEND = 136;
+    public static final int ERROR_MMS_INVALID_MESSAGE_RECEIVED = 137;
+    public static final int ERROR_MMS_NO_CONFIGURATION = 138;
+
+    private static final int LAST = 138;
+
+    private final boolean mIsInjection;
+    private final int mErrorCode;
+    private final String mMessage;
+    private final long mBackoff;
+
+    public DataModelException(final int errorCode, final Exception innerException,
+            final long backoff, final boolean injection, final String message) {
+        // Since some of the exceptions passed in may not be serializable, only record message
+        // instead of setting inner exception for Exception class. Otherwise, we will get
+        // serialization issues when we pass ServerRequestException as intent extra later.
+        if (errorCode < FIRST || errorCode > LAST) {
+            throw new IllegalArgumentException("error code out of range: " + errorCode);
+        }
+        mIsInjection = injection;
+        mErrorCode = errorCode;
+        if (innerException != null) {
+            mMessage = innerException.getMessage() + " -- " +
+                    (mIsInjection ? "[INJECTED] -- " : "") + message;
+        } else {
+            mMessage = (mIsInjection ? "[INJECTED] -- " : "") + message;
+        }
+
+        mBackoff = backoff;
+    }
+
+    public DataModelException(final int errorCode) {
+        this(errorCode, null, 0, false, null);
+    }
+
+    public DataModelException(final int errorCode, final Exception innerException) {
+        this(errorCode, innerException, 0, false, null);
+    }
+
+    public DataModelException(final int errorCode, final String message) {
+        this(errorCode, null, 0, false, message);
+    }
+
+    @Override
+    public String getMessage() {
+        return mMessage;
+    }
+
+    public int getErrorCode() {
+        return mErrorCode;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/DataModelImpl.java b/src/com/android/messaging/datamodel/DataModelImpl.java
new file mode 100644
index 0000000..ddb17ff
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DataModelImpl.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.telephony.SubscriptionManager;
+
+import com.android.messaging.datamodel.action.ActionService;
+import com.android.messaging.datamodel.action.BackgroundWorker;
+import com.android.messaging.datamodel.action.FixupMessageStatusOnStartupAction;
+import com.android.messaging.datamodel.action.ProcessPendingMessagesAction;
+import com.android.messaging.datamodel.data.BlockedParticipantsData;
+import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ContactPickerData;
+import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.LaunchConversationData;
+import com.android.messaging.datamodel.data.LaunchConversationData.LaunchConversationDataListener;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantListItemData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
+import com.android.messaging.datamodel.data.PeopleOptionsItemData;
+import com.android.messaging.datamodel.data.SettingsData;
+import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.datamodel.data.VCardContactItemData;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.ConnectivityUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DataModelImpl extends DataModel {
+    private final Context mContext;
+    private final ActionService mActionService;
+    private final BackgroundWorker mDataModelWorker;
+    private final DatabaseHelper mDatabaseHelper;
+    private final SyncManager mSyncManager;
+
+    // Cached ConnectivityUtil instance for Pre-N.
+    private static ConnectivityUtil sConnectivityUtilInstanceCachePreN = null;
+    // Cached ConnectivityUtil subId->instance for N and beyond
+    private static final ConcurrentHashMap<Integer, ConnectivityUtil>
+            sConnectivityUtilInstanceCacheN = new ConcurrentHashMap<>();
+
+    public DataModelImpl(final Context context) {
+        super();
+        mContext = context;
+        mActionService = new ActionService();
+        mDataModelWorker = new BackgroundWorker();
+        mDatabaseHelper = DatabaseHelper.getInstance(context);
+        mSyncManager = new SyncManager();
+    }
+
+    @Override
+    public ConversationListData createConversationListData(final Context context,
+            final ConversationListDataListener listener, final boolean archivedMode) {
+        return new ConversationListData(context, listener, archivedMode);
+    }
+
+    @Override
+    public ConversationData createConversationData(final Context context,
+            final ConversationDataListener listener, final String conversationId) {
+        return new ConversationData(context, listener, conversationId);
+    }
+
+    @Override
+    public ContactListItemData createContactListItemData() {
+        return new ContactListItemData();
+    }
+
+    @Override
+    public ContactPickerData createContactPickerData(final Context context,
+            final ContactPickerDataListener listener) {
+        return new ContactPickerData(context, listener);
+    }
+
+    @Override
+    public BlockedParticipantsData createBlockedParticipantsData(
+            final Context context, final BlockedParticipantsDataListener listener) {
+        return new BlockedParticipantsData(context, listener);
+    }
+
+    @Override
+    public MediaPickerData createMediaPickerData(final Context context) {
+        return new MediaPickerData(context);
+    }
+
+    @Override
+    public GalleryGridItemData createGalleryGridItemData() {
+        return new GalleryGridItemData();
+    }
+
+    @Override
+    public LaunchConversationData createLaunchConversationData(
+            final LaunchConversationDataListener listener) {
+       return new LaunchConversationData(listener);
+    }
+
+    @Override
+    public PeopleOptionsItemData createPeopleOptionsItemData(final Context context) {
+        return new PeopleOptionsItemData(context);
+    }
+
+    @Override
+    public PeopleAndOptionsData createPeopleAndOptionsData(final String conversationId,
+            final Context context, final PeopleAndOptionsDataListener listener) {
+        return new PeopleAndOptionsData(conversationId, context, listener);
+    }
+
+    @Override
+    public VCardContactItemData createVCardContactItemData(final Context context,
+            final MessagePartData data) {
+        return new VCardContactItemData(context, data);
+    }
+
+    @Override
+    public VCardContactItemData createVCardContactItemData(final Context context,
+            final Uri vCardUri) {
+        return new VCardContactItemData(context, vCardUri);
+    }
+
+    @Override
+    public ParticipantListItemData createParticipantListItemData(
+            final ParticipantData participant) {
+        return new ParticipantListItemData(participant);
+    }
+
+    @Override
+    public SubscriptionListData createSubscriptonListData(Context context) {
+        return new SubscriptionListData(context);
+    }
+
+    @Override
+    public SettingsData createSettingsData(Context context, SettingsDataListener listener) {
+        return new SettingsData(context, listener);
+    }
+
+    @Override
+    public DraftMessageData createDraftMessageData(String conversationId) {
+        return new DraftMessageData(conversationId);
+    }
+
+    @Override
+    public ActionService getActionService() {
+        // We need to allow access to this on the UI thread since it's used to start actions.
+        return mActionService;
+    }
+
+    @Override
+    public BackgroundWorker getBackgroundWorkerForActionService() {
+        return mDataModelWorker;
+    }
+
+    @Override
+    @DoesNotRunOnMainThread
+    public DatabaseWrapper getDatabase() {
+        // We prevent the main UI thread from accessing the database since we have to allow
+        // public access to this class to enable sub-packages to access data.
+        Assert.isNotMainThread();
+        return mDatabaseHelper.getDatabase();
+    }
+
+    @Override
+    public SyncManager getSyncManager() {
+        return mSyncManager;
+    }
+
+    @Override
+    void onCreateTables(final SQLiteDatabase db) {
+        LogUtil.w(LogUtil.BUGLE_TAG, "Rebuilt databases: reseting related state");
+        // Clear other things that implicitly reference the DB
+        SyncManager.resetLastSyncTimestamps();
+    }
+
+    @Override
+    public void onActivityResume() {
+        // Perform an incremental sync and register for changes if necessary
+        mSyncManager.updateSyncObserver(mContext);
+
+        // Trigger a participant refresh if needed, we should only need to refresh if there is
+        // contact change while the activity was paused.
+        ParticipantRefresh.refreshParticipantsIfNeeded();
+    }
+
+    @Override
+    public void onApplicationCreated() {
+        if (OsUtil.isAtLeastN()) {
+            createConnectivityUtilForEachActiveSubscription();
+        } else {
+            sConnectivityUtilInstanceCachePreN = new ConnectivityUtil(mContext);
+        }
+
+        FixupMessageStatusOnStartupAction.fixupMessageStatus();
+        ProcessPendingMessagesAction.processFirstPendingMessage();
+        SyncManager.immediateSync();
+
+        if (OsUtil.isAtLeastL_MR1()) {
+            // Start listening for subscription change events for refreshing any data associated
+            // with subscriptions.
+            PhoneUtils.getDefault().toLMr1().registerOnSubscriptionsChangedListener(
+                    new SubscriptionManager.OnSubscriptionsChangedListener() {
+                        @Override
+                        public void onSubscriptionsChanged() {
+                            // TODO: This dynamically changes the mms config that app is
+                            // currently using. It may cause inconsistency in some cases. We need
+                            // to check the usage of mms config and handle the dynamic change
+                            // gracefully
+                            MmsConfig.loadAsync();
+                            ParticipantRefresh.refreshSelfParticipants();
+                            if (OsUtil.isAtLeastN()) {
+                                createConnectivityUtilForEachActiveSubscription();
+                            }
+                        }
+                    });
+        }
+    }
+
+    private void createConnectivityUtilForEachActiveSubscription() {
+        PhoneUtils.forEachActiveSubscription(new PhoneUtils.SubscriptionRunnable() {
+            @Override
+            public void runForSubscription(int subId) {
+                // Create the ConnectivityUtil instance for given subId if absent.
+                if (subId <= ParticipantData.DEFAULT_SELF_SUB_ID) {
+                    subId = PhoneUtils.getDefault().getDefaultSmsSubscriptionId();
+                }
+                if (!sConnectivityUtilInstanceCacheN.containsKey(subId)) {
+                    sConnectivityUtilInstanceCacheN.put(
+                            subId, new ConnectivityUtil(mContext, subId));
+                }
+            }
+        });
+    }
+
+    public static ConnectivityUtil getConnectivityUtil(final int subId) {
+        if (OsUtil.isAtLeastN()) {
+            return sConnectivityUtilInstanceCacheN.get(subId);
+        } else {
+            return sConnectivityUtilInstanceCachePreN;
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/DatabaseHelper.java b/src/com/android/messaging/datamodel/DatabaseHelper.java
new file mode 100644
index 0000000..486973e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DatabaseHelper.java
@@ -0,0 +1,825 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.provider.BaseColumns;
+
+import com.android.messaging.BugleApplication;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * TODO: Open Issues:
+ * - Should we be storing the draft messages in the regular messages table or should we have a
+ *   separate table for drafts to keep the normal messages query as simple as possible?
+ */
+
+/**
+ * Allows access to the SQL database.  This is package private.
+ */
+public class DatabaseHelper extends SQLiteOpenHelper {
+    public static final String DATABASE_NAME = "bugle_db";
+
+    private static final int getDatabaseVersion(final Context context) {
+        return Integer.parseInt(context.getResources().getString(R.string.database_version));
+    }
+
+    /**
+     * Table containing names of all other tables and views.
+     * TODO(rtenneti): Fix the following special SQLLite table name when SQLLite changes.
+     */
+    private static final String PRIMARY_TABLE = "sqlite_master";
+    /** Column containing the name of the tables and views */
+    private static final String[] PRIMARY_COLUMNS = new String[] { "name", };
+
+    // Table names
+    public static final String CONVERSATIONS_TABLE = "conversations";
+    public static final String MESSAGES_TABLE = "messages";
+    public static final String PARTS_TABLE = "parts";
+    public static final String PARTICIPANTS_TABLE = "participants";
+    public static final String CONVERSATION_PARTICIPANTS_TABLE = "conversation_participants";
+
+    // Views
+    static final String DRAFT_PARTS_VIEW = "draft_parts_view";
+
+    // Conversations table schema
+    public static class ConversationColumns implements BaseColumns {
+        /* SMS/MMS Thread ID from the system provider */
+        public static final String SMS_THREAD_ID = "sms_thread_id";
+
+        /* Display name for the conversation */
+        public static final String NAME = "name";
+
+        /* Latest Message ID for the read status to display in conversation list */
+        public static final String LATEST_MESSAGE_ID = "latest_message_id";
+
+        /* Latest text snippet for display in conversation list */
+        public static final String SNIPPET_TEXT = "snippet_text";
+
+        /* Latest text subject for display in conversation list, empty string if none exists */
+        public static final String SUBJECT_TEXT = "subject_text";
+
+        /* Preview Uri */
+        public static final String PREVIEW_URI = "preview_uri";
+
+        /* The preview uri's content type */
+        public static final String PREVIEW_CONTENT_TYPE = "preview_content_type";
+
+        /* If we should display the current draft snippet/preview pair or snippet/preview pair */
+        public static final String SHOW_DRAFT = "show_draft";
+
+        /* Latest draft text subject for display in conversation list, empty string if none exists*/
+        public static final String DRAFT_SUBJECT_TEXT = "draft_subject_text";
+
+        /* Latest draft text snippet for display, empty string if none exists */
+        public static final String DRAFT_SNIPPET_TEXT = "draft_snippet_text";
+
+        /* Draft Preview Uri, empty string if none exists */
+        public static final String DRAFT_PREVIEW_URI = "draft_preview_uri";
+
+        /* The preview uri's content type */
+        public static final String DRAFT_PREVIEW_CONTENT_TYPE = "draft_preview_content_type";
+
+        /* If this conversation is archived */
+        public static final String ARCHIVE_STATUS = "archive_status";
+
+        /* Timestamp for sorting purposes */
+        public static final String SORT_TIMESTAMP = "sort_timestamp";
+
+        /* Last read message timestamp */
+        public static final String LAST_READ_TIMESTAMP = "last_read_timestamp";
+
+        /* Avatar for the conversation. Could be for group of individual */
+        public static final String ICON = "icon";
+
+        /* Participant contact ID if this conversation has a single participant. -1 otherwise */
+        public static final String PARTICIPANT_CONTACT_ID = "participant_contact_id";
+
+        /* Participant lookup key if this conversation has a single participant. null otherwise */
+        public static final String PARTICIPANT_LOOKUP_KEY = "participant_lookup_key";
+
+        /*
+         * Participant's normalized destination if this conversation has a single participant.
+         * null otherwise.
+         */
+        public static final String OTHER_PARTICIPANT_NORMALIZED_DESTINATION =
+                "participant_normalized_destination";
+
+        /* Default self participant for the conversation */
+        public static final String CURRENT_SELF_ID = "current_self_id";
+
+        /* Participant count not including self (so will be 1 for 1:1 or bigger for group) */
+        public static final String PARTICIPANT_COUNT = "participant_count";
+
+        /* Should notifications be enabled for this conversation? */
+        public static final String NOTIFICATION_ENABLED = "notification_enabled";
+
+        /* Notification sound used for the conversation */
+        public static final String NOTIFICATION_SOUND_URI = "notification_sound_uri";
+
+        /* Should vibrations be enabled for the conversation's notification? */
+        public static final String NOTIFICATION_VIBRATION = "notification_vibration";
+
+        /* Conversation recipients include email address */
+        public static final String INCLUDE_EMAIL_ADDRESS = "include_email_addr";
+
+        // Record the last received sms's service center info if it indicates that the reply path
+        // is present (TP-Reply-Path), so that we could use it for the subsequent message to send.
+        // Refer to TS 23.040 D.6 and SmsMessageSender.java in Android Messaging app.
+        public static final String SMS_SERVICE_CENTER = "sms_service_center";
+
+        // A conversation is enterprise if one of the participant is a enterprise contact.
+        public static final String IS_ENTERPRISE = "IS_ENTERPRISE";
+    }
+
+    // Conversation table SQL
+    private static final String CREATE_CONVERSATIONS_TABLE_SQL =
+            "CREATE TABLE " + CONVERSATIONS_TABLE + "("
+                    + ConversationColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    // TODO : Int? Required not default?
+                    + ConversationColumns.SMS_THREAD_ID + " INT DEFAULT(0), "
+                    + ConversationColumns.NAME + " TEXT, "
+                    + ConversationColumns.LATEST_MESSAGE_ID + " INT, "
+                    + ConversationColumns.SNIPPET_TEXT + " TEXT, "
+                    + ConversationColumns.SUBJECT_TEXT + " TEXT, "
+                    + ConversationColumns.PREVIEW_URI + " TEXT, "
+                    + ConversationColumns.PREVIEW_CONTENT_TYPE + " TEXT, "
+                    + ConversationColumns.SHOW_DRAFT + " INT DEFAULT(0), "
+                    + ConversationColumns.DRAFT_SNIPPET_TEXT + " TEXT, "
+                    + ConversationColumns.DRAFT_SUBJECT_TEXT + " TEXT, "
+                    + ConversationColumns.DRAFT_PREVIEW_URI + " TEXT, "
+                    + ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE + " TEXT, "
+                    + ConversationColumns.ARCHIVE_STATUS + " INT DEFAULT(0), "
+                    + ConversationColumns.SORT_TIMESTAMP + " INT DEFAULT(0), "
+                    + ConversationColumns.LAST_READ_TIMESTAMP + " INT DEFAULT(0), "
+                    + ConversationColumns.ICON + " TEXT, "
+                    + ConversationColumns.PARTICIPANT_CONTACT_ID + " INT DEFAULT ( "
+                            + ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED + "), "
+                    + ConversationColumns.PARTICIPANT_LOOKUP_KEY + " TEXT, "
+                    + ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION + " TEXT, "
+                    + ConversationColumns.CURRENT_SELF_ID + " TEXT, "
+                    + ConversationColumns.PARTICIPANT_COUNT + " INT DEFAULT(0), "
+                    + ConversationColumns.NOTIFICATION_ENABLED + " INT DEFAULT(1), "
+                    + ConversationColumns.NOTIFICATION_SOUND_URI + " TEXT, "
+                    + ConversationColumns.NOTIFICATION_VIBRATION + " INT DEFAULT(1), "
+                    + ConversationColumns.INCLUDE_EMAIL_ADDRESS + " INT DEFAULT(0), "
+                    + ConversationColumns.SMS_SERVICE_CENTER + " TEXT ,"
+                    + ConversationColumns.IS_ENTERPRISE + " INT DEFAULT(0)"
+                    + ");";
+
+    private static final String CONVERSATIONS_TABLE_SMS_THREAD_ID_INDEX_SQL =
+            "CREATE INDEX index_" + CONVERSATIONS_TABLE + "_" + ConversationColumns.SMS_THREAD_ID
+            + " ON " +  CONVERSATIONS_TABLE
+            + "(" + ConversationColumns.SMS_THREAD_ID + ")";
+
+    private static final String CONVERSATIONS_TABLE_ARCHIVE_STATUS_INDEX_SQL =
+            "CREATE INDEX index_" + CONVERSATIONS_TABLE + "_" + ConversationColumns.ARCHIVE_STATUS
+            + " ON " +  CONVERSATIONS_TABLE
+            + "(" + ConversationColumns.ARCHIVE_STATUS + ")";
+
+    private static final String CONVERSATIONS_TABLE_SORT_TIMESTAMP_INDEX_SQL =
+            "CREATE INDEX index_" + CONVERSATIONS_TABLE + "_" + ConversationColumns.SORT_TIMESTAMP
+            + " ON " +  CONVERSATIONS_TABLE
+            + "(" + ConversationColumns.SORT_TIMESTAMP + ")";
+
+    // Messages table schema
+    public static class MessageColumns implements BaseColumns {
+        /* conversation id that this message belongs to */
+        public static final String CONVERSATION_ID = "conversation_id";
+
+        /* participant which send this message */
+        public static final String SENDER_PARTICIPANT_ID = "sender_id";
+
+        /* This is bugle's internal status for the message */
+        public static final String STATUS = "message_status";
+
+        /* Type of message: SMS, MMS or MMS notification */
+        public static final String PROTOCOL = "message_protocol";
+
+        /* This is the time that the sender sent the message */
+        public static final String SENT_TIMESTAMP = "sent_timestamp";
+
+        /* Time that we received the message on this device */
+        public static final String RECEIVED_TIMESTAMP = "received_timestamp";
+
+        /* When the message has been seen by a user in a notification */
+        public static final String SEEN = "seen";
+
+        /* When the message has been read by a user */
+        public static final String READ = "read";
+
+        /* participant representing the sim which processed this message */
+        public static final String SELF_PARTICIPANT_ID = "self_id";
+
+        /*
+         * Time when a retry is initiated. This is used to compute the retry window
+         * when we retry sending/downloading a message.
+         */
+        public static final String RETRY_START_TIMESTAMP = "retry_start_timestamp";
+
+        // Columns which map to the SMS provider
+
+        /* Message ID from the platform provider */
+        public static final String SMS_MESSAGE_URI = "sms_message_uri";
+
+        /* The message priority for MMS message */
+        public static final String SMS_PRIORITY = "sms_priority";
+
+        /* The message size for MMS message */
+        public static final String SMS_MESSAGE_SIZE = "sms_message_size";
+
+        /* The subject for MMS message */
+        public static final String MMS_SUBJECT = "mms_subject";
+
+        /* Transaction id for MMS notificaiton */
+        public static final String MMS_TRANSACTION_ID = "mms_transaction_id";
+
+        /* Content location for MMS notificaiton */
+        public static final String MMS_CONTENT_LOCATION = "mms_content_location";
+
+        /* The expiry time (ms) for MMS message */
+        public static final String MMS_EXPIRY = "mms_expiry";
+
+        /* The detailed status (RESPONSE_STATUS or RETRIEVE_STATUS) for MMS message */
+        public static final String RAW_TELEPHONY_STATUS = "raw_status";
+    }
+
+    // Messages table SQL
+    private static final String CREATE_MESSAGES_TABLE_SQL =
+            "CREATE TABLE " + MESSAGES_TABLE + " ("
+                    + MessageColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    + MessageColumns.CONVERSATION_ID + " INT, "
+                    + MessageColumns.SENDER_PARTICIPANT_ID + " INT, "
+                    + MessageColumns.SENT_TIMESTAMP + " INT DEFAULT(0), "
+                    + MessageColumns.RECEIVED_TIMESTAMP + " INT DEFAULT(0), "
+                    + MessageColumns.PROTOCOL + " INT DEFAULT(0), "
+                    + MessageColumns.STATUS + " INT DEFAULT(0), "
+                    + MessageColumns.SEEN + " INT DEFAULT(0), "
+                    + MessageColumns.READ + " INT DEFAULT(0), "
+                    + MessageColumns.SMS_MESSAGE_URI + " TEXT, "
+                    + MessageColumns.SMS_PRIORITY + " INT DEFAULT(0), "
+                    + MessageColumns.SMS_MESSAGE_SIZE + " INT DEFAULT(0), "
+                    + MessageColumns.MMS_SUBJECT + " TEXT, "
+                    + MessageColumns.MMS_TRANSACTION_ID + " TEXT, "
+                    + MessageColumns.MMS_CONTENT_LOCATION + " TEXT, "
+                    + MessageColumns.MMS_EXPIRY + " INT DEFAULT(0), "
+                    + MessageColumns.RAW_TELEPHONY_STATUS + " INT DEFAULT(0), "
+                    + MessageColumns.SELF_PARTICIPANT_ID + " INT, "
+                    + MessageColumns.RETRY_START_TIMESTAMP + " INT DEFAULT(0), "
+                    + "FOREIGN KEY (" + MessageColumns.CONVERSATION_ID + ") REFERENCES "
+                    + CONVERSATIONS_TABLE + "(" + ConversationColumns._ID + ") ON DELETE CASCADE "
+                    + "FOREIGN KEY (" + MessageColumns.SENDER_PARTICIPANT_ID + ") REFERENCES "
+                    + PARTICIPANTS_TABLE + "(" + ParticipantColumns._ID + ") ON DELETE SET NULL "
+                    + "FOREIGN KEY (" + MessageColumns.SELF_PARTICIPANT_ID + ") REFERENCES "
+                    + PARTICIPANTS_TABLE + "(" + ParticipantColumns._ID + ") ON DELETE SET NULL "
+                    + ");";
+
+    // Primary sort index for messages table : by conversation id, status, received timestamp.
+    private static final String MESSAGES_TABLE_SORT_INDEX_SQL =
+            "CREATE INDEX index_" + MESSAGES_TABLE + "_sort ON " +  MESSAGES_TABLE + "("
+                    + MessageColumns.CONVERSATION_ID + ", "
+                    + MessageColumns.STATUS + ", "
+                    + MessageColumns.RECEIVED_TIMESTAMP + ")";
+
+    private static final String MESSAGES_TABLE_STATUS_SEEN_INDEX_SQL =
+            "CREATE INDEX index_" + MESSAGES_TABLE + "_status_seen ON " +  MESSAGES_TABLE + "("
+                    + MessageColumns.STATUS + ", "
+                    + MessageColumns.SEEN + ")";
+
+    // Parts table schema
+    // A part may contain text or a media url, but not both.
+    public static class PartColumns implements BaseColumns {
+        /* message id that this part belongs to */
+        public static final String MESSAGE_ID = "message_id";
+
+        /* conversation id that this part belongs to */
+        public static final String CONVERSATION_ID = "conversation_id";
+
+        /* text for this part */
+        public static final String TEXT = "text";
+
+        /* content uri for this part */
+        public static final String CONTENT_URI = "uri";
+
+        /* content type for this part */
+        public static final String CONTENT_TYPE = "content_type";
+
+        /* cached width for this part (for layout while loading) */
+        public static final String WIDTH = "width";
+
+        /* cached height for this part (for layout while loading) */
+        public static final String HEIGHT = "height";
+
+        /* de-normalized copy of timestamp from the messages table.  This is populated
+         * via an insert trigger on the parts table.
+         */
+        public static final String TIMESTAMP = "timestamp";
+    }
+
+    // Message part table SQL
+    private static final String CREATE_PARTS_TABLE_SQL =
+            "CREATE TABLE " + PARTS_TABLE + "("
+                    + PartColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+                    + PartColumns.MESSAGE_ID + " INT,"
+                    + PartColumns.TEXT + " TEXT,"
+                    + PartColumns.CONTENT_URI + " TEXT,"
+                    + PartColumns.CONTENT_TYPE + " TEXT,"
+                    + PartColumns.WIDTH + " INT DEFAULT("
+                    + MessagingContentProvider.UNSPECIFIED_SIZE + "),"
+                    + PartColumns.HEIGHT + " INT DEFAULT("
+                    + MessagingContentProvider.UNSPECIFIED_SIZE + "),"
+                    + PartColumns.TIMESTAMP + " INT, "
+                    + PartColumns.CONVERSATION_ID + " INT NOT NULL,"
+                    + "FOREIGN KEY (" + PartColumns.MESSAGE_ID + ") REFERENCES "
+                    + MESSAGES_TABLE + "(" + MessageColumns._ID + ") ON DELETE CASCADE "
+                    + "FOREIGN KEY (" + PartColumns.CONVERSATION_ID + ") REFERENCES "
+                    + CONVERSATIONS_TABLE + "(" + ConversationColumns._ID + ") ON DELETE CASCADE "
+                    + ");";
+
+    public static final String CREATE_PARTS_TRIGGER_SQL =
+            "CREATE TRIGGER " + PARTS_TABLE + "_TRIGGER" + " AFTER INSERT ON " + PARTS_TABLE
+            + " FOR EACH ROW "
+            + " BEGIN UPDATE " + PARTS_TABLE
+            + " SET " + PartColumns.TIMESTAMP + "="
+            + " (SELECT received_timestamp FROM " + MESSAGES_TABLE + " WHERE " + MESSAGES_TABLE
+            + "." + MessageColumns._ID + "=" + "NEW." + PartColumns.MESSAGE_ID + ")"
+            + " WHERE " + PARTS_TABLE + "." + PartColumns._ID + "=" + "NEW." + PartColumns._ID
+            + "; END";
+
+    public static final String CREATE_MESSAGES_TRIGGER_SQL =
+            "CREATE TRIGGER " + MESSAGES_TABLE + "_TRIGGER" + " AFTER UPDATE OF "
+            + MessageColumns.RECEIVED_TIMESTAMP + " ON " + MESSAGES_TABLE
+            + " FOR EACH ROW BEGIN UPDATE " + PARTS_TABLE + " SET " + PartColumns.TIMESTAMP
+            + " = NEW." + MessageColumns.RECEIVED_TIMESTAMP + " WHERE " + PARTS_TABLE + "."
+            + PartColumns.MESSAGE_ID + " = NEW." + MessageColumns._ID
+            + "; END;";
+
+    // Primary sort index for parts table : by message_id
+    private static final String PARTS_TABLE_MESSAGE_INDEX_SQL =
+            "CREATE INDEX index_" + PARTS_TABLE + "_message_id ON " + PARTS_TABLE + "("
+                    + PartColumns.MESSAGE_ID + ")";
+
+    // Participants table schema
+    public static class ParticipantColumns implements BaseColumns {
+        /* The subscription id for the sim associated with this self participant.
+         * Introduced in L. For earlier versions will always be default_sub_id (-1).
+         * For multi sim devices (or cases where the sim was changed) single device
+         * may have several different sub_id values */
+        public static final String SUB_ID = "sub_id";
+
+        /* The slot of the active SIM (inserted in the device) for this self-participant. If the
+         * self-participant doesn't correspond to any active SIM, this will be
+         * {@link android.telephony.SubscriptionManager#INVALID_SLOT_ID}.
+         * The column is ignored for all non-self participants.
+         */
+        public static final String SIM_SLOT_ID = "sim_slot_id";
+
+        /* The phone number stored in a standard E164 format if possible.  This is unique for a
+         * given participant.  We can't handle multiple participants with the same phone number
+         * since we don't know which of them a message comes from. This can also be an email
+         * address, in which case this is the same as the displayed address */
+        public static final String NORMALIZED_DESTINATION = "normalized_destination";
+
+        /* The phone number as originally supplied and used for dialing. Not necessarily in E164
+         * format or unique */
+        public static final String SEND_DESTINATION = "send_destination";
+
+        /* The user-friendly formatting of the phone number according to the region setting of
+         * the device when the row was added. */
+        public static final String DISPLAY_DESTINATION = "display_destination";
+
+        /* A string with this participant's full name or a pretty printed phone number */
+        public static final String FULL_NAME = "full_name";
+
+        /* A string with just this participant's first name */
+        public static final String FIRST_NAME = "first_name";
+
+        /* A local URI to an asset for the icon for this participant */
+        public static final String PROFILE_PHOTO_URI = "profile_photo_uri";
+
+        /* Contact id for matching local contact for this participant */
+        public static final String CONTACT_ID = "contact_id";
+
+        /* String that contains hints on how to find contact information in a contact lookup */
+        public static final String LOOKUP_KEY = "lookup_key";
+
+        /* If this participant is blocked */
+        public static final String BLOCKED = "blocked";
+
+        /* The color of the subscription (FOR SELF PARTICIPANTS ONLY) */
+        public static final String SUBSCRIPTION_COLOR = "subscription_color";
+
+        /* The name of the subscription (FOR SELF PARTICIPANTS ONLY) */
+        public static final String SUBSCRIPTION_NAME = "subscription_name";
+
+        /* The exact destination stored in Contacts for this participant */
+        public static final String CONTACT_DESTINATION = "contact_destination";
+    }
+
+    // Participants table SQL
+    private static final String CREATE_PARTICIPANTS_TABLE_SQL =
+            "CREATE TABLE " + PARTICIPANTS_TABLE + "("
+                    + ParticipantColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+                    + ParticipantColumns.SUB_ID + " INT DEFAULT("
+                    + ParticipantData.OTHER_THAN_SELF_SUB_ID + "),"
+                    + ParticipantColumns.SIM_SLOT_ID + " INT DEFAULT("
+                    + ParticipantData.INVALID_SLOT_ID + "),"
+                    + ParticipantColumns.NORMALIZED_DESTINATION + " TEXT,"
+                    + ParticipantColumns.SEND_DESTINATION + " TEXT,"
+                    + ParticipantColumns.DISPLAY_DESTINATION + " TEXT,"
+                    + ParticipantColumns.FULL_NAME + " TEXT,"
+                    + ParticipantColumns.FIRST_NAME + " TEXT,"
+                    + ParticipantColumns.PROFILE_PHOTO_URI + " TEXT, "
+                    + ParticipantColumns.CONTACT_ID + " INT DEFAULT( "
+                    + ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED + "), "
+                    + ParticipantColumns.LOOKUP_KEY + " STRING, "
+                    + ParticipantColumns.BLOCKED + " INT DEFAULT(0), "
+                    + ParticipantColumns.SUBSCRIPTION_NAME + " TEXT, "
+                    + ParticipantColumns.SUBSCRIPTION_COLOR + " INT DEFAULT(0), "
+                    + ParticipantColumns.CONTACT_DESTINATION + " TEXT, "
+                    + "UNIQUE (" + ParticipantColumns.NORMALIZED_DESTINATION + ", "
+                    + ParticipantColumns.SUB_ID + ") ON CONFLICT FAIL" + ");";
+
+    private static final String CREATE_SELF_PARTICIPANT_SQL =
+            "INSERT INTO " + PARTICIPANTS_TABLE
+            + " ( " +  ParticipantColumns.SUB_ID + " ) VALUES ( %s )";
+
+    static String getCreateSelfParticipantSql(int subId) {
+        return String.format(CREATE_SELF_PARTICIPANT_SQL, subId);
+    }
+
+    // Conversation Participants table schema - contains a list of participants excluding the user
+    // in a given conversation.
+    public static class ConversationParticipantsColumns implements BaseColumns {
+        /* participant id of someone in this conversation */
+        public static final String PARTICIPANT_ID = "participant_id";
+
+        /* conversation id that this participant belongs to */
+        public static final String CONVERSATION_ID = "conversation_id";
+    }
+
+    // Conversation Participants table SQL
+    private static final String CREATE_CONVERSATION_PARTICIPANTS_TABLE_SQL =
+            "CREATE TABLE " + CONVERSATION_PARTICIPANTS_TABLE + "("
+                    + ConversationParticipantsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+                    + ConversationParticipantsColumns.CONVERSATION_ID + " INT,"
+                    + ConversationParticipantsColumns.PARTICIPANT_ID + " INT,"
+                    + "UNIQUE (" + ConversationParticipantsColumns.CONVERSATION_ID + ","
+                    + ConversationParticipantsColumns.PARTICIPANT_ID + ") ON CONFLICT FAIL, "
+                    + "FOREIGN KEY (" + ConversationParticipantsColumns.CONVERSATION_ID + ") "
+                    + "REFERENCES " + CONVERSATIONS_TABLE + "(" + ConversationColumns._ID + ")"
+                    + " ON DELETE CASCADE "
+                    + "FOREIGN KEY (" + ConversationParticipantsColumns.PARTICIPANT_ID + ")"
+                    + " REFERENCES " + PARTICIPANTS_TABLE + "(" + ParticipantColumns._ID + "));";
+
+    // Primary access pattern for conversation participants is to look them up for a specific
+    // conversation.
+    private static final String CONVERSATION_PARTICIPANTS_TABLE_CONVERSATION_ID_INDEX_SQL =
+            "CREATE INDEX index_" + CONVERSATION_PARTICIPANTS_TABLE + "_"
+                    + ConversationParticipantsColumns.CONVERSATION_ID
+                    + " ON " +  CONVERSATION_PARTICIPANTS_TABLE
+                    + "(" + ConversationParticipantsColumns.CONVERSATION_ID + ")";
+
+    // View for getting parts which are for draft messages.
+    static final String DRAFT_PARTS_VIEW_SQL = "CREATE VIEW " +
+            DRAFT_PARTS_VIEW + " AS SELECT "
+            + PARTS_TABLE + '.' + PartColumns._ID
+            + " as " + PartColumns._ID + ", "
+            + PARTS_TABLE + '.' + PartColumns.MESSAGE_ID
+            + " as " + PartColumns.MESSAGE_ID + ", "
+            + PARTS_TABLE + '.' + PartColumns.TEXT
+            + " as " + PartColumns.TEXT + ", "
+            + PARTS_TABLE + '.' + PartColumns.CONTENT_URI
+            + " as " + PartColumns.CONTENT_URI + ", "
+            + PARTS_TABLE + '.' + PartColumns.CONTENT_TYPE
+            + " as " + PartColumns.CONTENT_TYPE + ", "
+            + PARTS_TABLE + '.' + PartColumns.WIDTH
+            + " as " + PartColumns.WIDTH + ", "
+            + PARTS_TABLE + '.' + PartColumns.HEIGHT
+            + " as " + PartColumns.HEIGHT + ", "
+            + MESSAGES_TABLE + '.' + MessageColumns.CONVERSATION_ID
+            + " as " + MessageColumns.CONVERSATION_ID + " "
+            + " FROM " + MESSAGES_TABLE + " LEFT JOIN " + PARTS_TABLE + " ON ("
+            + MESSAGES_TABLE + "." + MessageColumns._ID
+            + "=" + PARTS_TABLE + "." + PartColumns.MESSAGE_ID + ")"
+            // Exclude draft messages from main view
+            + " WHERE " + MESSAGES_TABLE + "." + MessageColumns.STATUS
+            + " = " + MessageData.BUGLE_STATUS_OUTGOING_DRAFT;
+
+    // List of all our SQL tables
+    private static final String[] CREATE_TABLE_SQLS = new String[] {
+        CREATE_CONVERSATIONS_TABLE_SQL,
+        CREATE_MESSAGES_TABLE_SQL,
+        CREATE_PARTS_TABLE_SQL,
+        CREATE_PARTICIPANTS_TABLE_SQL,
+        CREATE_CONVERSATION_PARTICIPANTS_TABLE_SQL,
+    };
+
+    // List of all our indices
+    private static final String[] CREATE_INDEX_SQLS = new String[] {
+        CONVERSATIONS_TABLE_SMS_THREAD_ID_INDEX_SQL,
+        CONVERSATIONS_TABLE_ARCHIVE_STATUS_INDEX_SQL,
+        CONVERSATIONS_TABLE_SORT_TIMESTAMP_INDEX_SQL,
+        MESSAGES_TABLE_SORT_INDEX_SQL,
+        MESSAGES_TABLE_STATUS_SEEN_INDEX_SQL,
+        PARTS_TABLE_MESSAGE_INDEX_SQL,
+        CONVERSATION_PARTICIPANTS_TABLE_CONVERSATION_ID_INDEX_SQL,
+    };
+
+    // List of all our SQL triggers
+    private static final String[] CREATE_TRIGGER_SQLS = new String[] {
+            CREATE_PARTS_TRIGGER_SQL,
+            CREATE_MESSAGES_TRIGGER_SQL,
+    };
+
+    // List of all our views
+    private static final String[] CREATE_VIEW_SQLS = new String[] {
+        ConversationListItemData.getConversationListViewSql(),
+        ConversationImagePartsView.getCreateSql(),
+        DRAFT_PARTS_VIEW_SQL,
+    };
+
+    private static final Object sLock = new Object();
+    private final Context mApplicationContext;
+    private static DatabaseHelper sHelperInstance;      // Protected by sLock.
+
+    private final Object mDatabaseWrapperLock = new Object();
+    private DatabaseWrapper mDatabaseWrapper;           // Protected by mDatabaseWrapperLock.
+    private final DatabaseUpgradeHelper mUpgradeHelper = new DatabaseUpgradeHelper();
+
+    /**
+     * Get a (singleton) instance of {@link DatabaseHelper}, creating one if there isn't one yet.
+     * This is the only public method for getting a new instance of the class.
+     * @param context Should be the application context (or something that will live for the
+     * lifetime of the application).
+     * @return The current (or a new) DatabaseHelper instance.
+     */
+    public static DatabaseHelper getInstance(final Context context) {
+        synchronized (sLock) {
+            if (sHelperInstance == null) {
+                sHelperInstance = new DatabaseHelper(context);
+            }
+            return sHelperInstance;
+        }
+    }
+
+    /**
+     * Private constructor, used from {@link #getInstance()}.
+     * @param context Should be the application context (or something that will live for the
+     * lifetime of the application).
+     */
+    private DatabaseHelper(final Context context) {
+        super(context, DATABASE_NAME, null, getDatabaseVersion(context), null);
+        mApplicationContext = context;
+    }
+
+    /**
+     * Test method that always instantiates a new DatabaseHelper instance. This should
+     * be used ONLY by the tests and never by the real application.
+     * @param context Test context.
+     * @return Brand new DatabaseHelper instance.
+     */
+    @VisibleForTesting
+    static DatabaseHelper getNewInstanceForTest(final Context context) {
+        Assert.isTrue(BugleApplication.isRunningTests());
+        return new DatabaseHelper(context);
+    }
+
+    /**
+     * Get the (singleton) instance of @{link DatabaseWrapper}.
+     * <p>The database is always opened as a writeable database.
+     * @return The current (or a new) DatabaseWrapper instance.
+     */
+    @DoesNotRunOnMainThread
+    DatabaseWrapper getDatabase() {
+        // We prevent the main UI thread from accessing the database here since we have to allow
+        // public access to this class to enable sub-packages to access data.
+        Assert.isNotMainThread();
+
+        synchronized (mDatabaseWrapperLock) {
+            if (mDatabaseWrapper == null) {
+                mDatabaseWrapper = new DatabaseWrapper(mApplicationContext, getWritableDatabase());
+            }
+            return mDatabaseWrapper;
+        }
+    }
+
+    @Override
+    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        mUpgradeHelper.onDowngrade(db, oldVersion, newVersion);
+    }
+
+    /**
+     * Drops and recreates all tables.
+     */
+    public static void rebuildTables(final SQLiteDatabase db) {
+        // Drop tables first, then views, and indices.
+        dropAllTables(db);
+        dropAllViews(db);
+        dropAllIndexes(db);
+        dropAllTriggers(db);
+
+        // Recreate the whole database.
+        createDatabase(db);
+    }
+
+    /**
+     * Drop and rebuild a given view.
+     */
+    static void rebuildView(final SQLiteDatabase db, final String viewName,
+            final String createViewSql) {
+        dropView(db, viewName, true /* throwOnFailure */);
+        db.execSQL(createViewSql);
+    }
+
+    private static void dropView(final SQLiteDatabase db, final String viewName,
+            final boolean throwOnFailure) {
+        final String dropPrefix = "DROP VIEW IF EXISTS ";
+        try {
+            db.execSQL(dropPrefix + viewName);
+        } catch (final SQLException ex) {
+            if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                LogUtil.d(LogUtil.BUGLE_TAG, "unable to drop view " + viewName + " "
+                        + ex);
+            }
+
+            if (throwOnFailure) {
+                throw ex;
+            }
+        }
+    }
+
+    public static void rebuildAllViews(final DatabaseWrapper db) {
+        for (final String sql : DatabaseHelper.CREATE_VIEW_SQLS) {
+            db.execSQL(sql);
+        }
+    }
+
+    /**
+     * Drops all user-defined tables from the given database.
+     */
+    private static void dropAllTables(final SQLiteDatabase db) {
+        final Cursor tableCursor =
+                db.query(PRIMARY_TABLE, PRIMARY_COLUMNS, "type='table'", null, null, null, null);
+        if (tableCursor != null) {
+            try {
+                final String dropPrefix = "DROP TABLE IF EXISTS ";
+                while (tableCursor.moveToNext()) {
+                    final String tableName = tableCursor.getString(0);
+
+                    // Skip special tables
+                    if (tableName.startsWith("android_") || tableName.startsWith("sqlite_")) {
+                        continue;
+                    }
+                    try {
+                        db.execSQL(dropPrefix + tableName);
+                    } catch (final SQLException ex) {
+                        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                            LogUtil.d(LogUtil.BUGLE_TAG, "unable to drop table " + tableName + " "
+                                    + ex);
+                        }
+                    }
+                }
+            } finally {
+                tableCursor.close();
+            }
+        }
+    }
+
+    /**
+     * Drops all user-defined triggers from the given database.
+     */
+    private static void dropAllTriggers(final SQLiteDatabase db) {
+        final Cursor triggerCursor =
+                db.query(PRIMARY_TABLE, PRIMARY_COLUMNS, "type='trigger'", null, null, null, null);
+        if (triggerCursor != null) {
+            try {
+                final String dropPrefix = "DROP TRIGGER IF EXISTS ";
+                while (triggerCursor.moveToNext()) {
+                    final String triggerName = triggerCursor.getString(0);
+
+                    // Skip special tables
+                    if (triggerName.startsWith("android_") || triggerName.startsWith("sqlite_")) {
+                        continue;
+                    }
+                    try {
+                        db.execSQL(dropPrefix + triggerName);
+                    } catch (final SQLException ex) {
+                        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                            LogUtil.d(LogUtil.BUGLE_TAG, "unable to drop trigger " + triggerName +
+                                    " " + ex);
+                        }
+                    }
+                }
+            } finally {
+                triggerCursor.close();
+            }
+        }
+    }
+
+    /**
+     * Drops all user-defined views from the given database.
+     */
+    public static void dropAllViews(final SQLiteDatabase db) {
+        final Cursor viewCursor =
+                db.query(PRIMARY_TABLE, PRIMARY_COLUMNS, "type='view'", null, null, null, null);
+        if (viewCursor != null) {
+            try {
+                while (viewCursor.moveToNext()) {
+                    final String viewName = viewCursor.getString(0);
+                    dropView(db, viewName, false /* throwOnFailure */);
+                }
+            } finally {
+                viewCursor.close();
+            }
+        }
+    }
+
+    /**
+     * Drops all user-defined views from the given database.
+     */
+    private static void dropAllIndexes(final SQLiteDatabase db) {
+        final Cursor indexCursor =
+                db.query(PRIMARY_TABLE, PRIMARY_COLUMNS, "type='index'", null, null, null, null);
+        if (indexCursor != null) {
+            try {
+                final String dropPrefix = "DROP INDEX IF EXISTS ";
+                while (indexCursor.moveToNext()) {
+                    final String indexName = indexCursor.getString(0);
+                    try {
+                        db.execSQL(dropPrefix + indexName);
+                    } catch (final SQLException ex) {
+                        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                            LogUtil.d(LogUtil.BUGLE_TAG, "unable to drop index " + indexName + " "
+                                    + ex);
+                        }
+                    }
+                }
+            } finally {
+                indexCursor.close();
+            }
+        }
+    }
+
+    private static void createDatabase(final SQLiteDatabase db) {
+        for (final String sql : CREATE_TABLE_SQLS) {
+            db.execSQL(sql);
+        }
+
+        for (final String sql : CREATE_INDEX_SQLS) {
+            db.execSQL(sql);
+        }
+
+        for (final String sql : CREATE_VIEW_SQLS) {
+            db.execSQL(sql);
+        }
+
+        for (final String sql : CREATE_TRIGGER_SQLS) {
+            db.execSQL(sql);
+        }
+
+        // Enable foreign key constraints
+        db.execSQL("PRAGMA foreign_keys=ON;");
+
+        // Add the default self participant. The default self will be assigned a proper slot id
+        // during participant refresh.
+        db.execSQL(getCreateSelfParticipantSql(ParticipantData.DEFAULT_SELF_SUB_ID));
+
+        DataModel.get().onCreateTables(db);
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        createDatabase(db);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        mUpgradeHelper.doOnUpgrade(db, oldVersion, newVersion);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/DatabaseUpgradeHelper.java b/src/com/android/messaging/datamodel/DatabaseUpgradeHelper.java
new file mode 100644
index 0000000..96aba86
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DatabaseUpgradeHelper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+public class DatabaseUpgradeHelper {
+    private static final String TAG = LogUtil.BUGLE_DATABASE_TAG;
+
+    public void doOnUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        Assert.isTrue(newVersion >= oldVersion);
+        if (oldVersion == newVersion) {
+            return;
+        }
+
+        LogUtil.i(TAG, "Database upgrade started from version " + oldVersion + " to " + newVersion);
+        try {
+            doUpgradeWithExceptions(db, oldVersion, newVersion);
+            LogUtil.i(TAG, "Finished database upgrade");
+        } catch (final Exception ex) {
+            LogUtil.e(TAG, "Failed to perform db upgrade from version " +
+                    oldVersion + " to version " + newVersion, ex);
+            DatabaseHelper.rebuildTables(db);
+        }
+    }
+
+    public void doUpgradeWithExceptions(final SQLiteDatabase db, final int oldVersion,
+            final int newVersion) throws Exception {
+        int currentVersion = oldVersion;
+        if (currentVersion < 2) {
+            currentVersion = upgradeToVersion2(db);
+        }
+        // Rebuild all the views
+        final Context context = Factory.get().getApplicationContext();
+        DatabaseHelper.dropAllViews(db);
+        DatabaseHelper.rebuildAllViews(new DatabaseWrapper(context, db));
+        // Finally, check if we have arrived at the final version.
+        checkAndUpdateVersionAtReleaseEnd(currentVersion, Integer.MAX_VALUE, newVersion);
+    }
+
+    private int upgradeToVersion2(final SQLiteDatabase db) {
+        db.execSQL("ALTER TABLE " + DatabaseHelper.CONVERSATIONS_TABLE + " ADD COLUMN " +
+                DatabaseHelper.ConversationColumns.IS_ENTERPRISE + " INT DEFAULT(0)");
+        LogUtil.i(TAG, "Ugraded database to version 2");
+        return 2;
+    }
+
+    /**
+     * Checks db version correctness at the end of each milestone release. If target database
+     * version lies beyond the version range that the current release may handle, we snap the
+     * current version to the end of the release, so that we may go on to the next release' upgrade
+     * path. Otherwise, if target version is within reach of the current release, but we are not
+     * at the target version, then throw an exception to force a table rebuild.
+     */
+    private int checkAndUpdateVersionAtReleaseEnd(final int currentVersion,
+            final int maxVersionForRelease, final int targetVersion) throws Exception {
+        if (maxVersionForRelease < targetVersion) {
+            // Target version is beyond the current release. Snap to max version for the
+            // current release so we can go on to the upgrade path for the next release.
+            return maxVersionForRelease;
+        }
+
+        // If we are here, this means the current release' upgrade handler should upgrade to
+        // target version...
+        if (currentVersion != targetVersion) {
+            // No more upgrade handlers. So we can't possibly upgrade to the final version.
+            throw new Exception("Missing upgrade handler from version " +
+                    currentVersion + " to version " + targetVersion);
+        }
+        // Upgrade succeeded.
+        return targetVersion;
+    }
+
+    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        DatabaseHelper.rebuildTables(db);
+        LogUtil.e(TAG, "Database downgrade requested for version " +
+                oldVersion + " version " + newVersion + ", forcing db rebuild!");
+    }
+}
diff --git a/src/com/android/messaging/datamodel/DatabaseWrapper.java b/src/com/android/messaging/datamodel/DatabaseWrapper.java
new file mode 100644
index 0000000..c08d5aa
--- /dev/null
+++ b/src/com/android/messaging/datamodel/DatabaseWrapper.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteFullException;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.sqlite.SQLiteStatement;
+import android.util.SparseArray;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+
+import java.util.Locale;
+import java.util.Stack;
+import java.util.regex.Pattern;
+
+public class DatabaseWrapper {
+    private static final String TAG = LogUtil.BUGLE_DATABASE_TAG;
+
+    private final SQLiteDatabase mDatabase;
+    private final Context mContext;
+    private final boolean mLog;
+    /**
+     * Set mExplainQueryPlanRegexp (via {@link BugleGservicesKeys#EXPLAIN_QUERY_PLAN_REGEXP}
+     * to regex matching queries to see query plans. For example, ".*" to show all query plans.
+     */
+    // See
+    private final String mExplainQueryPlanRegexp;
+    private static final int sTimingThreshold = 50;        // in milliseconds
+
+    public static final int INDEX_INSERT_MESSAGE_PART = 0;
+    public static final int INDEX_INSERT_MESSAGE = 1;
+    public static final int INDEX_QUERY_CONVERSATIONS_LATEST_MESSAGE = 2;
+    public static final int INDEX_QUERY_MESSAGES_LATEST_MESSAGE = 3;
+
+    private final SparseArray<SQLiteStatement> mCompiledStatements;
+
+    static class TransactionData {
+        long time;
+        boolean transactionSuccessful;
+    }
+
+    // track transaction on a per thread basis
+    private static ThreadLocal<Stack<TransactionData>> sTransactionDepth =
+            new ThreadLocal<Stack<TransactionData>>() {
+        @Override
+        public Stack<TransactionData> initialValue() {
+            return new Stack<TransactionData>();
+        }
+    };
+
+    private static String[] sFormatStrings = new String[] {
+        "took %d ms to %s",
+        "   took %d ms to %s",
+        "      took %d ms to %s",
+    };
+
+    DatabaseWrapper(final Context context, final SQLiteDatabase db) {
+        mLog = LogUtil.isLoggable(LogUtil.BUGLE_DATABASE_PERF_TAG, LogUtil.VERBOSE);
+        mExplainQueryPlanRegexp = Factory.get().getBugleGservices().getString(
+                BugleGservicesKeys.EXPLAIN_QUERY_PLAN_REGEXP, null);
+        mDatabase = db;
+        mContext = context;
+        mCompiledStatements = new SparseArray<SQLiteStatement>();
+    }
+
+    public SQLiteStatement getStatementInTransaction(final int index, final String statement) {
+        // Use transaction to serialize access to statements
+        Assert.isTrue(mDatabase.inTransaction());
+        SQLiteStatement compiled = mCompiledStatements.get(index);
+        if (compiled == null) {
+            compiled = mDatabase.compileStatement(statement);
+            Assert.isTrue(compiled.toString().contains(statement.trim()));
+            mCompiledStatements.put(index, compiled);
+        }
+        return compiled;
+    }
+
+    private void maybePlayDebugNoise() {
+        DebugUtils.maybePlayDebugNoise(mContext, DebugUtils.DEBUG_SOUND_DB_OP);
+    }
+
+    private static void printTiming(final long t1, final String msg) {
+        final int transactionDepth = sTransactionDepth.get().size();
+        final long t2 = System.currentTimeMillis();
+        final long delta = t2 - t1;
+        if (delta > sTimingThreshold) {
+            LogUtil.v(LogUtil.BUGLE_DATABASE_PERF_TAG, String.format(Locale.US,
+                    sFormatStrings[Math.min(sFormatStrings.length - 1, transactionDepth)],
+                    delta,
+                    msg));
+        }
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    public void beginTransaction() {
+        final long t1 = System.currentTimeMillis();
+
+        // push the current time onto the transaction stack
+        final TransactionData f = new TransactionData();
+        f.time = t1;
+        sTransactionDepth.get().push(f);
+
+        mDatabase.beginTransaction();
+    }
+
+    public void setTransactionSuccessful() {
+        final TransactionData f = sTransactionDepth.get().peek();
+        f.transactionSuccessful = true;
+        mDatabase.setTransactionSuccessful();
+    }
+
+    public void endTransaction() {
+        long t1 = 0;
+        long transactionStartTime = 0;
+        final TransactionData f = sTransactionDepth.get().pop();
+        if (f.transactionSuccessful == false) {
+            LogUtil.w(TAG, "endTransaction without setting successful");
+            for (final StackTraceElement st : (new Exception()).getStackTrace()) {
+                LogUtil.w(TAG, "    " + st.toString());
+            }
+        }
+        if (mLog) {
+            transactionStartTime = f.time;
+            t1 = System.currentTimeMillis();
+        }
+        try {
+            mDatabase.endTransaction();
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to endTransaction", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US,
+                    ">>> endTransaction (total for this transaction: %d)",
+                    (System.currentTimeMillis() - transactionStartTime)));
+        }
+    }
+
+    public void yieldTransaction() {
+        long yieldStartTime = 0;
+        if (mLog) {
+            yieldStartTime = System.currentTimeMillis();
+        }
+        final boolean wasYielded = mDatabase.yieldIfContendedSafely();
+        if (wasYielded && mLog) {
+            printTiming(yieldStartTime, "yieldTransaction");
+        }
+    }
+
+    public void insertWithOnConflict(final String searchTable, final String nullColumnHack,
+            final ContentValues initialValues, final int conflictAlgorithm) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        try {
+            mDatabase.insertWithOnConflict(searchTable, nullColumnHack, initialValues,
+                    conflictAlgorithm);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to insertWithOnConflict", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US,
+                    "insertWithOnConflict with %s", searchTable));
+        }
+    }
+
+    private void explainQueryPlan(final SQLiteQueryBuilder qb, final SQLiteDatabase db,
+            final String[] projection, final String selection,
+            @SuppressWarnings("unused")
+                    final String[] queryArgs,
+            final String groupBy,
+            @SuppressWarnings("unused")
+                    final String having,
+            final String sortOrder, final String limit) {
+        final String queryString = qb.buildQuery(
+                projection,
+                selection,
+                groupBy,
+                null/*having*/,
+                sortOrder,
+                limit);
+        explainQueryPlan(db, queryString, queryArgs);
+    }
+
+    private void explainQueryPlan(final SQLiteDatabase db, final String sql,
+            final String[] queryArgs) {
+        if (!Pattern.matches(mExplainQueryPlanRegexp, sql)) {
+            return;
+        }
+        final Cursor planCursor = db.rawQuery("explain query plan " + sql, queryArgs);
+        try {
+            if (planCursor != null && planCursor.moveToFirst()) {
+                final int detailColumn = planCursor.getColumnIndex("detail");
+                final StringBuilder sb = new StringBuilder();
+                do {
+                    sb.append(planCursor.getString(detailColumn));
+                    sb.append("\n");
+                } while (planCursor.moveToNext());
+                if (sb.length() > 0) {
+                    sb.setLength(sb.length() - 1);
+                }
+                LogUtil.v(TAG, "for query " + sql + "\nplan is: "
+                        + sb.toString());
+            }
+        } catch (final Exception e) {
+            LogUtil.w(TAG, "Query plan failed ", e);
+        } finally {
+            if (planCursor != null) {
+                planCursor.close();
+            }
+        }
+    }
+
+    public Cursor query(final String searchTable, final String[] projection,
+            final String selection, final String[] selectionArgs, final String groupBy,
+            final String having, final String orderBy, final String limit) {
+        if (mExplainQueryPlanRegexp != null) {
+            final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+            qb.setTables(searchTable);
+            explainQueryPlan(qb, mDatabase, projection, selection, selectionArgs,
+                    groupBy, having, orderBy, limit);
+        }
+
+        maybePlayDebugNoise();
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        final Cursor cursor = mDatabase.query(searchTable, projection, selection, selectionArgs,
+                groupBy, having, orderBy, limit);
+        if (mLog) {
+            printTiming(
+                    t1,
+                    String.format(Locale.US, "query %s with %s ==> %d",
+                            searchTable, selection, cursor.getCount()));
+        }
+        return cursor;
+    }
+
+    public Cursor query(final String searchTable, final String[] columns,
+            final String selection, final String[] selectionArgs, final String groupBy,
+            final String having, final String orderBy) {
+        return query(
+                searchTable, columns, selection, selectionArgs,
+                groupBy, having, orderBy, null);
+    }
+
+    public Cursor query(final SQLiteQueryBuilder qb,
+            final String[] projection, final String selection, final String[] queryArgs,
+            final String groupBy, final String having, final String sortOrder, final String limit) {
+        if (mExplainQueryPlanRegexp != null) {
+            explainQueryPlan(qb, mDatabase, projection, selection, queryArgs,
+                    groupBy, having, sortOrder, limit);
+        }
+        maybePlayDebugNoise();
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        final Cursor cursor = qb.query(mDatabase, projection, selection, queryArgs, groupBy,
+                having, sortOrder, limit);
+        if (mLog) {
+            printTiming(
+                    t1,
+                    String.format(Locale.US, "query %s with %s ==> %d",
+                            qb.getTables(), selection, cursor.getCount()));
+        }
+        return cursor;
+    }
+
+    public long queryNumEntries(final String table, final String selection,
+            final String[] selectionArgs) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        final long retval =
+                DatabaseUtils.queryNumEntries(mDatabase, table, selection, selectionArgs);
+        if (mLog){
+            printTiming(
+                    t1,
+                    String.format(Locale.US, "queryNumEntries %s with %s ==> %d", table,
+                            selection, retval));
+        }
+        return retval;
+    }
+
+    public Cursor rawQuery(final String sql, final String[] args) {
+        if (mExplainQueryPlanRegexp != null) {
+            explainQueryPlan(mDatabase, sql, args);
+        }
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        final Cursor cursor = mDatabase.rawQuery(sql, args);
+        if (mLog) {
+            printTiming(
+                    t1,
+                    String.format(Locale.US, "rawQuery %s ==> %d", sql, cursor.getCount()));
+        }
+        return cursor;
+    }
+
+    public int update(final String table, final ContentValues values,
+            final String selection, final String[] selectionArgs) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        int count = 0;
+        try {
+            count = mDatabase.update(table, values, selection, selectionArgs);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to update", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "update %s with %s ==> %d",
+                    table, selection, count));
+        }
+        return count;
+    }
+
+    public int delete(final String table, final String whereClause, final String[] whereArgs) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        int count = 0;
+        try {
+            count = mDatabase.delete(table, whereClause, whereArgs);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to delete", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1,
+                    String.format(Locale.US, "delete from %s with %s ==> %d", table,
+                            whereClause, count));
+        }
+        return count;
+    }
+
+    public long insert(final String table, final String nullColumnHack,
+            final ContentValues values) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        long rowId = -1;
+        try {
+            rowId = mDatabase.insert(table, nullColumnHack, values);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to insert", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "insert to %s", table));
+        }
+        return rowId;
+    }
+
+    public long replace(final String table, final String nullColumnHack,
+            final ContentValues values) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        long rowId = -1;
+        try {
+            rowId = mDatabase.replace(table, nullColumnHack, values);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to replace", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "replace to %s", table));
+        }
+        return rowId;
+    }
+
+    public void setLocale(final Locale locale) {
+        mDatabase.setLocale(locale);
+    }
+
+    public void execSQL(final String sql, final String[] bindArgs) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        try {
+            mDatabase.execSQL(sql, bindArgs);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to execSQL", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "execSQL %s", sql));
+        }
+    }
+
+    public void execSQL(final String sql) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        try {
+            mDatabase.execSQL(sql);
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to execSQL", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "execSQL %s", sql));
+        }
+    }
+
+    public int execSQLUpdateDelete(final String sql) {
+        long t1 = 0;
+        if (mLog) {
+            t1 = System.currentTimeMillis();
+        }
+        maybePlayDebugNoise();
+        final SQLiteStatement statement = mDatabase.compileStatement(sql);
+        int rowsUpdated = 0;
+        try {
+            rowsUpdated = statement.executeUpdateDelete();
+        } catch (SQLiteFullException ex) {
+            LogUtil.e(TAG, "Database full, unable to execSQLUpdateDelete", ex);
+            UiUtils.showToastAtBottom(R.string.db_full);
+        }
+        if (mLog) {
+            printTiming(t1, String.format(Locale.US, "execSQLUpdateDelete %s", sql));
+        }
+        return rowsUpdated;
+    }
+
+    public SQLiteDatabase getDatabase() {
+        return mDatabase;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/FileProvider.java b/src/com/android/messaging/datamodel/FileProvider.java
new file mode 100644
index 0000000..ee332cd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/FileProvider.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Random;
+
+/**
+ * A very simple content provider that can serve files.
+ */
+public abstract class FileProvider extends ContentProvider {
+    // Object to generate random id for temp images.
+    private static final Random RANDOM_ID = new Random();
+
+    abstract File getFile(final String path, final String extension);
+
+    private static final String FILE_EXTENSION_PARAM_KEY = "ext";
+
+    /**
+     * Check if filename conforms to requirement for our provider
+     * @param fileId filename (optionally starting with path character
+     * @return true if filename consists only of digits
+     */
+    protected static boolean isValidFileId(final String fileId) {
+        // Ignore initial "/"
+        for (int index = (fileId.startsWith("/") ? 1 : 0); index < fileId.length(); index++) {
+            final Character c = fileId.charAt(index);
+            if (!Character.isDigit(c)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Create a temp file (to allow writing to that one particular file)
+     * @param file the file to create
+     * @return true if file successfully created
+     */
+    protected static boolean ensureFileExists(final File file) {
+        try {
+            final File parentDir = file.getParentFile();
+            if (parentDir.exists() || parentDir.mkdirs()) {
+                return file.createNewFile();
+            }
+        } catch (final IOException e) {
+            // fail on exceptions creating the file
+        }
+        return false;
+    }
+
+    /**
+     * Build uri for a new temporary file (creating file)
+     * @param authority authority with which to populate uri
+     * @param extension optional file extension
+     * @return unique uri that can be used to write temporary files
+     */
+    protected static Uri buildFileUri(final String authority, final String extension) {
+        final long fileId = Math.abs(RANDOM_ID.nextLong());
+        final Uri.Builder builder = (new Uri.Builder()).authority(authority).scheme(
+                ContentResolver.SCHEME_CONTENT);
+        builder.appendPath(String.valueOf(fileId));
+        if (!TextUtils.isEmpty(extension)) {
+            builder.appendQueryParameter(FILE_EXTENSION_PARAM_KEY, extension);
+        }
+        return builder.build();
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
+        final String fileId = uri.getPath();
+        if (isValidFileId(fileId)) {
+            final File file = getFile(fileId, getExtensionFromUri(uri));
+            return file.delete() ? 1 : 0;
+        }
+        return 0;
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(final Uri uri, final String fileMode)
+            throws FileNotFoundException {
+        final String fileId = uri.getPath();
+        if (isValidFileId(fileId)) {
+            final File file = getFile(fileId, getExtensionFromUri(uri));
+            final int mode =
+                    (TextUtils.equals(fileMode, "r") ? ParcelFileDescriptor.MODE_READ_ONLY :
+                        ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
+            return ParcelFileDescriptor.open(file, mode);
+        }
+        return null;
+    }
+
+    protected static String getExtensionFromUri(final Uri uri) {
+        return uri.getQueryParameter(FILE_EXTENSION_PARAM_KEY);
+    }
+
+    @Override
+    public Cursor query(final Uri uri, final String[] projection, final String selection,
+            final String[] selectionArgs, final String sortOrder) {
+        // Don't support queries.
+        return null;
+    }
+
+    @Override
+    public Uri insert(final Uri uri, final ContentValues values) {
+        // Don't support inserts.
+        return null;
+    }
+
+    @Override
+    public int update(final Uri uri, final ContentValues values, final String selection,
+            final String[] selectionArgs) {
+        // Don't support updates.
+        return 0;
+    }
+
+    @Override
+    public String getType(final Uri uri) {
+        // No need for mime types.
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java b/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java
new file mode 100644
index 0000000..8f65156
--- /dev/null
+++ b/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import androidx.collection.SimpleArrayMap;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * A cursor builder that takes the frequent contacts cursor and aggregate it with the all contacts
+ * cursor to fill in contact details such as phone numbers and strip away invalid contacts.
+ *
+ * Because the frequent contact list depends on the loading of two cursors, it needs to temporarily
+ * store the cursor that it receives with setFrequents() and setAllContacts() calls. Because it
+ * doesn't know which one will be finished first, it always checks whether both cursors are ready
+ * to pull data from and construct the aggregate cursor when it's ready to do so. Note that
+ * this cursor builder doesn't assume ownership of the cursors passed in - it merely references
+ * them and always does a isClosed() check before consuming them. The ownership still belongs to
+ * the loader framework and the cursor may be closed when the UI is torn down.
+ */
+public class FrequentContactsCursorBuilder {
+    private Cursor mAllContactsCursor;
+    private Cursor mFrequentContactsCursor;
+
+    /**
+     * Sets the frequent contacts cursor as soon as it is loaded, or null if it's reset.
+     * @return this builder instance for chained operations
+     */
+    public FrequentContactsCursorBuilder setFrequents(final Cursor frequentContactsCursor) {
+        mFrequentContactsCursor = frequentContactsCursor;
+        return this;
+    }
+
+    /**
+     * Sets the all contacts cursor as soon as it is loaded, or null if it's reset.
+     * @return this builder instance for chained operations
+     */
+    public FrequentContactsCursorBuilder setAllContacts(final Cursor allContactsCursor) {
+        mAllContactsCursor = allContactsCursor;
+        return this;
+    }
+
+    /**
+     * Reset this builder. Must be called when the consumer resets its data.
+     */
+    public void resetBuilder() {
+        mAllContactsCursor = null;
+        mFrequentContactsCursor = null;
+    }
+
+    /**
+     * Attempt to build the cursor records from the frequent and all contacts cursor if they
+     * are both ready to be consumed.
+     * @return the frequent contact cursor if built successfully, or null if it can't be built yet.
+     */
+    public Cursor build() {
+        if (mFrequentContactsCursor != null && mAllContactsCursor != null) {
+            Assert.isTrue(!mFrequentContactsCursor.isClosed());
+            Assert.isTrue(!mAllContactsCursor.isClosed());
+
+            // Frequent contacts cursor has one record per contact, plus it doesn't contain info
+            // such as phone number and type. In order for the records to be usable by Bugle, we
+            // would like to populate it with information from the all contacts cursor.
+            final MatrixCursor retCursor = new MatrixCursor(ContactUtil.PhoneQuery.PROJECTION);
+
+            // First, go through the frequents cursor and take note of all lookup keys and their
+            // corresponding rank in the frequents list.
+            final SimpleArrayMap<String, Integer> lookupKeyToRankMap =
+                    new SimpleArrayMap<String, Integer>();
+            int oldPosition = mFrequentContactsCursor.getPosition();
+            int rank = 0;
+            mFrequentContactsCursor.moveToPosition(-1);
+            while (mFrequentContactsCursor.moveToNext()) {
+                final String lookupKey = mFrequentContactsCursor.getString(
+                        ContactUtil.INDEX_LOOKUP_KEY_FREQUENT);
+                lookupKeyToRankMap.put(lookupKey, rank++);
+            }
+            mFrequentContactsCursor.moveToPosition(oldPosition);
+
+            // Second, go through the all contacts cursor once and retrieve all information
+            // (multiple phone numbers etc.) and store that in an array list. Since the all
+            // contacts list only contains phone contacts, this step will ensure that we filter
+            // out any invalid/email contacts in the frequents list.
+            final ArrayList<Object[]> rows =
+                    new ArrayList<Object[]>(mFrequentContactsCursor.getCount());
+            oldPosition = mAllContactsCursor.getPosition();
+            mAllContactsCursor.moveToPosition(-1);
+            while (mAllContactsCursor.moveToNext()) {
+                final String lookupKey = mAllContactsCursor.getString(ContactUtil.INDEX_LOOKUP_KEY);
+                if (lookupKeyToRankMap.containsKey(lookupKey)) {
+                    final Object[] row = new Object[ContactUtil.PhoneQuery.PROJECTION.length];
+                    row[ContactUtil.INDEX_DATA_ID] =
+                            mAllContactsCursor.getLong(ContactUtil.INDEX_DATA_ID);
+                    row[ContactUtil.INDEX_CONTACT_ID] =
+                            mAllContactsCursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+                    row[ContactUtil.INDEX_LOOKUP_KEY] =
+                            mAllContactsCursor.getString(ContactUtil.INDEX_LOOKUP_KEY);
+                    row[ContactUtil.INDEX_DISPLAY_NAME] =
+                            mAllContactsCursor.getString(ContactUtil.INDEX_DISPLAY_NAME);
+                    row[ContactUtil.INDEX_PHOTO_URI] =
+                            mAllContactsCursor.getString(ContactUtil.INDEX_PHOTO_URI);
+                    row[ContactUtil.INDEX_PHONE_EMAIL] =
+                            mAllContactsCursor.getString(ContactUtil.INDEX_PHONE_EMAIL);
+                    row[ContactUtil.INDEX_PHONE_EMAIL_TYPE] =
+                            mAllContactsCursor.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE);
+                    row[ContactUtil.INDEX_PHONE_EMAIL_LABEL] =
+                            mAllContactsCursor.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL);
+                    rows.add(row);
+                }
+            }
+            mAllContactsCursor.moveToPosition(oldPosition);
+
+            // Now we have a list of rows containing frequent contacts in alphabetical order.
+            // Therefore, sort all the rows according to their actual ranks in the frequents list.
+            Collections.sort(rows, new Comparator<Object[]>() {
+                @Override
+                public int compare(final Object[] lhs, final Object[] rhs) {
+                    final String lookupKeyLhs = (String) lhs[ContactUtil.INDEX_LOOKUP_KEY];
+                    final String lookupKeyRhs = (String) rhs[ContactUtil.INDEX_LOOKUP_KEY];
+                    Assert.isTrue(lookupKeyToRankMap.containsKey(lookupKeyLhs) &&
+                            lookupKeyToRankMap.containsKey(lookupKeyRhs));
+                    final int rankLhs = lookupKeyToRankMap.get(lookupKeyLhs);
+                    final int rankRhs = lookupKeyToRankMap.get(lookupKeyRhs);
+                    if (rankLhs < rankRhs) {
+                        return -1;
+                    } else if (rankLhs > rankRhs) {
+                        return 1;
+                    } else {
+                        // Same rank, so it's two contact records for the same contact.
+                        // Perform secondary sorting on the phone type. Always place
+                        // mobile before everything else.
+                        final int phoneTypeLhs = (int) lhs[ContactUtil.INDEX_PHONE_EMAIL_TYPE];
+                        final int phoneTypeRhs = (int) rhs[ContactUtil.INDEX_PHONE_EMAIL_TYPE];
+                        if (phoneTypeLhs == Phone.TYPE_MOBILE &&
+                                phoneTypeRhs == Phone.TYPE_MOBILE) {
+                            return 0;
+                        } else if (phoneTypeLhs == Phone.TYPE_MOBILE) {
+                            return -1;
+                        } else if (phoneTypeRhs == Phone.TYPE_MOBILE) {
+                            return 1;
+                        } else {
+                            // Use the default sort order, i.e. sort by phoneType value.
+                            return phoneTypeLhs < phoneTypeRhs ? -1 :
+                                    (phoneTypeLhs == phoneTypeRhs ? 0 : 1);
+                        }
+                    }
+                }
+            });
+
+            // Finally, add all the rows to this cursor.
+            for (final Object[] row : rows) {
+                retCursor.addRow(row);
+            }
+            return retCursor;
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/FrequentContactsCursorQueryData.java b/src/com/android/messaging/datamodel/FrequentContactsCursorQueryData.java
new file mode 100644
index 0000000..d1759ad
--- /dev/null
+++ b/src/com/android/messaging/datamodel/FrequentContactsCursorQueryData.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+
+import com.android.messaging.util.FallbackStrategies;
+import com.android.messaging.util.FallbackStrategies.Strategy;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Helper for querying frequent (and/or starred) contacts.
+ */
+public class FrequentContactsCursorQueryData extends CursorQueryData {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static class FrequentContactsCursorLoader extends BoundCursorLoader {
+        private final Uri mOriginalUri;
+
+        FrequentContactsCursorLoader(String bindingId, Context context, Uri uri,
+                String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+            super(bindingId, context, uri, projection, selection, selectionArgs, sortOrder);
+            mOriginalUri = uri;
+        }
+
+        @Override
+        public Cursor loadInBackground() {
+            return FallbackStrategies
+                    .startWith(new PrimaryStrequentContactsQueryStrategy())
+                    .thenTry(new FrequentOnlyContactsQueryStrategy())
+                    .thenTry(new PhoneOnlyStrequentContactsQueryStrategy())
+                    .execute(null);
+        }
+
+        private abstract class StrequentContactsQueryStrategy implements Strategy<Void, Cursor> {
+            @Override
+            public Cursor execute(Void params) throws Exception {
+                final Uri uri = getUri();
+                if (uri != null) {
+                    setUri(uri);
+                }
+                return FrequentContactsCursorLoader.super.loadInBackground();
+            }
+            protected abstract Uri getUri();
+        }
+
+        private class PrimaryStrequentContactsQueryStrategy extends StrequentContactsQueryStrategy {
+            @Override
+            protected Uri getUri() {
+                // Use the original URI requested.
+                return mOriginalUri;
+            }
+        }
+
+        private class FrequentOnlyContactsQueryStrategy extends StrequentContactsQueryStrategy {
+            @Override
+            protected Uri getUri() {
+                // Some phones have a buggy implementation of the Contacts provider which crashes
+                // when we query for strequent (starred+frequent) contacts (b/17991485).
+                // If this happens, switch to just querying for frequent contacts.
+                return Contacts.CONTENT_FREQUENT_URI;
+            }
+        }
+
+        private class PhoneOnlyStrequentContactsQueryStrategy extends
+                StrequentContactsQueryStrategy {
+            @Override
+            protected Uri getUri() {
+                // Some 3rd party ROMs have content provider
+                // implementation where invalid SQL queries are returned for regular strequent
+                // queries. Using strequent_phone_only query as a fallback to display only phone
+                // contacts. This is the last-ditch effort; if this fails, we will display an
+                // empty frequent list (b/18354836).
+                final String strequentQueryParam = OsUtil.isAtLeastL() ?
+                        ContactsContract.STREQUENT_PHONE_ONLY : "strequent_phone_only";
+                // TODO: Handle enterprise contacts post M once contacts provider supports it
+                return Contacts.CONTENT_STREQUENT_URI.buildUpon()
+                        .appendQueryParameter(strequentQueryParam, "true").build();
+            }
+        }
+    }
+
+    public FrequentContactsCursorQueryData(Context context, String[] projection,
+            String selection, String[] selectionArgs, String sortOrder) {
+        // TODO: Handle enterprise contacts post M once contacts provider supports it
+        super(context, Contacts.CONTENT_STREQUENT_URI, projection, selection, selectionArgs,
+                sortOrder);
+    }
+
+    @Override
+    public BoundCursorLoader createBoundCursorLoader(String bindingId) {
+        return new FrequentContactsCursorLoader(bindingId, mContext, mUri, mProjection, mSelection,
+                mSelectionArgs, mSortOrder);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java b/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java
new file mode 100644
index 0000000..1974a5e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.net.Uri;
+import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Files.FileColumns;
+import android.provider.MediaStore.MediaColumns;
+
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.google.common.base.Joiner;
+
+/**
+ * A BoundCursorLoader that reads local media on the device.
+ */
+public class GalleryBoundCursorLoader extends BoundCursorLoader {
+    public static final String MEDIA_SCANNER_VOLUME_EXTERNAL = "external";
+    private static final Uri STORAGE_URI = Files.getContentUri(MEDIA_SCANNER_VOLUME_EXTERNAL);
+    private static final String SORT_ORDER = MediaColumns.DATE_MODIFIED + " DESC";
+    private static final String SELECTION = createSelection(
+            MessagePartData.ACCEPTABLE_GALLERY_MEDIA_TYPES,
+            new Integer[] {
+                FileColumns.MEDIA_TYPE_IMAGE,
+                FileColumns.MEDIA_TYPE_VIDEO,
+                FileColumns.MEDIA_TYPE_AUDIO
+            });
+
+    public GalleryBoundCursorLoader(final String bindingId, final Context context) {
+        super(bindingId, context, STORAGE_URI, GalleryGridItemData.MEDIA_PROJECTION, SELECTION,
+                null, SORT_ORDER);
+    }
+
+    private static String createSelection(final String[] mimeTypes, Integer[] mediaTypes) {
+        return MediaColumns.MIME_TYPE + " IN ('" + Joiner.on("','").join(mimeTypes) + "') AND "
+                + FileColumns.MEDIA_TYPE + " IN (" + Joiner.on(',').join(mediaTypes) + ")";
+    }
+}
diff --git a/src/com/android/messaging/datamodel/MediaScratchFileProvider.java b/src/com/android/messaging/datamodel/MediaScratchFileProvider.java
new file mode 100644
index 0000000..6f21bc5
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MediaScratchFileProvider.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.net.Uri;
+import android.provider.OpenableColumns;
+import androidx.collection.SimpleArrayMap;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * A very simple content provider that can serve media files from our cache directory.
+ */
+public class MediaScratchFileProvider extends FileProvider {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final SimpleArrayMap<Uri, String> sUriToDisplayNameMap =
+            new SimpleArrayMap<Uri, String>();
+
+    @VisibleForTesting
+    public static final String AUTHORITY =
+            "com.android.messaging.datamodel.MediaScratchFileProvider";
+    private static final String MEDIA_SCRATCH_SPACE_DIR = "mediascratchspace";
+
+    public static boolean isMediaScratchSpaceUri(final Uri uri) {
+        if (uri == null) {
+            return false;
+        }
+
+        final List<String> segments = uri.getPathSegments();
+        return (TextUtils.equals(uri.getScheme(), ContentResolver.SCHEME_CONTENT) &&
+                TextUtils.equals(uri.getAuthority(), AUTHORITY) &&
+                segments.size() == 1 && FileProvider.isValidFileId(segments.get(0)));
+    }
+
+    /**
+     * Returns a uri that can be used to access a raw mms file.
+     *
+     * @return the URI for an raw mms file
+     */
+    public static Uri buildMediaScratchSpaceUri(final String extension) {
+        final Uri uri = FileProvider.buildFileUri(AUTHORITY, extension);
+        final File file = getFileWithExtension(uri.getPath(), extension);
+        if (!ensureFileExists(file)) {
+            LogUtil.e(TAG, "Failed to create temp file " + file.getAbsolutePath());
+        }
+        return uri;
+    }
+
+    public static File getFileFromUri(final Uri uri) {
+        Assert.equals(AUTHORITY, uri.getAuthority());
+        return getFileWithExtension(uri.getPath(), getExtensionFromUri(uri));
+    }
+
+    public static Uri.Builder getUriBuilder() {
+        return (new Uri.Builder()).authority(AUTHORITY).scheme(ContentResolver.SCHEME_CONTENT);
+    }
+
+    @Override
+    File getFile(final String path, final String extension) {
+        return getFileWithExtension(path, extension);
+    }
+
+    private static File getFileWithExtension(final String path, final String extension) {
+        final Context context = Factory.get().getApplicationContext();
+        final File filePath = new File(getDirectory(context),
+                TextUtils.isEmpty(extension) ? path : path + "." + extension);
+
+        try {
+            if (!filePath.getCanonicalPath()
+                    .startsWith(getDirectory(context).getCanonicalPath())) {
+                LogUtil.e(TAG, "getFileWithExtension: path "
+                        + filePath.getCanonicalPath()
+                        + " does not start with "
+                        + getDirectory(context).getCanonicalPath());
+                return null;
+            }
+        } catch (IOException e) {
+            LogUtil.e(TAG, "getFileWithExtension: getCanonicalPath failed ", e);
+            return null;
+        }
+        return filePath;
+    }
+
+    private static File getDirectory(final Context context) {
+        return new File(context.getCacheDir(), MEDIA_SCRATCH_SPACE_DIR);
+    }
+
+    @Override
+    public Cursor query(final Uri uri, final String[] projection, final String selection,
+            final String[] selectionArgs, final String sortOrder) {
+        if (projection != null && projection.length > 0 &&
+                TextUtils.equals(projection[0], OpenableColumns.DISPLAY_NAME) &&
+                isMediaScratchSpaceUri(uri)) {
+            // Retrieve the display name associated with a temp file. This is used by the Contacts
+            // ImportVCardActivity to retrieve the name of the contact(s) being imported.
+            String displayName;
+            synchronized (sUriToDisplayNameMap) {
+                displayName = sUriToDisplayNameMap.get(uri);
+            }
+            if (!TextUtils.isEmpty(displayName)) {
+                MatrixCursor cursor =
+                        new MatrixCursor(new String[] { OpenableColumns.DISPLAY_NAME });
+                RowBuilder row = cursor.newRow();
+                row.add(displayName);
+                return cursor;
+            }
+        }
+        return null;
+    }
+
+    public static void addUriToDisplayNameEntry(final Uri scratchFileUri,
+            final String displayName) {
+        if (TextUtils.isEmpty(displayName)) {
+            return;
+        }
+        synchronized (sUriToDisplayNameMap) {
+            sUriToDisplayNameMap.put(scratchFileUri, displayName);
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/MemoryCacheManager.java b/src/com/android/messaging/datamodel/MemoryCacheManager.java
new file mode 100644
index 0000000..0968cff
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MemoryCacheManager.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import com.android.messaging.Factory;
+
+import java.util.HashSet;
+
+/**
+ * Utility abstraction which allows MemoryCaches in an application to register and then when there
+ * is memory pressure provide a callback to reclaim the memory in the caches.
+ */
+public class MemoryCacheManager {
+    private final HashSet<MemoryCache> mMemoryCaches = new HashSet<MemoryCache>();
+    private final Object mMemoryCacheLock = new Object();
+
+    public static MemoryCacheManager get() {
+        return Factory.get().getMemoryCacheManager();
+    }
+
+    /**
+     * Extend this interface to provide a reclaim method on a memory cache.
+     */
+    public interface MemoryCache {
+        void reclaim();
+    }
+
+    /**
+     * Register the memory cache with the application.
+     */
+    public void registerMemoryCache(final MemoryCache cache) {
+        synchronized (mMemoryCacheLock) {
+            mMemoryCaches.add(cache);
+        }
+    }
+
+    /**
+     * Unregister the memory cache with the application.
+     */
+    public void unregisterMemoryCache(final MemoryCache cache) {
+        synchronized (mMemoryCacheLock) {
+            mMemoryCaches.remove(cache);
+        }
+    }
+
+    /**
+     * Reclaim memory in all the memory caches in the application.
+     */
+    @SuppressWarnings("unchecked")
+    public void reclaimMemory() {
+        // We're creating a cache copy in the lock to ensure we're not working on a concurrently
+        // modified set, then reclaim outside of the lock to minimize the time within the lock.
+        final HashSet<MemoryCache> shallowCopy;
+        synchronized (mMemoryCacheLock) {
+            shallowCopy = (HashSet<MemoryCache>) mMemoryCaches.clone();
+        }
+        for (final MemoryCache cache : shallowCopy) {
+            cache.reclaim();
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/MessageNotificationState.java b/src/com/android/messaging/datamodel/MessageNotificationState.java
new file mode 100644
index 0000000..6b858fa
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MessageNotificationState.java
@@ -0,0 +1,1347 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.net.Uri;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationCompat.Builder;
+import androidx.core.app.NotificationCompat.WearableExtender;
+import androidx.core.app.NotificationManagerCompat;
+import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
+import android.text.style.TextAppearanceSpan;
+import android.text.style.URLSpan;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.ConversationParticipantsData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.media.VideoThumbnailRequest;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ConversationIdSet;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PendingIntentConstants;
+import com.android.messaging.util.UriUtil;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Notification building class for conversation messages.
+ *
+ * Message Notifications are built in several stages with several utility classes.
+ * 1) Perform a database query and fill a data structure with information on messages and
+ *    conversations which need to be notified.
+ * 2) Based on the data structure choose an appropriate NotificationState subclass to
+ *    represent all the notifications.
+ *    -- For one or more messages in one conversation: MultiMessageNotificationState.
+ *    -- For multiple messages in multiple conversations: MultiConversationNotificationState
+ *
+ *  A three level structure is used to coalesce the data from the database. From bottom to top:
+ *  1) NotificationLineInfo - A single message that needs to be notified.
+ *  2) ConversationLineInfo - A list of NotificationLineInfo in a single conversation.
+ *  3) ConversationInfoList - A list of ConversationLineInfo and the total number of messages.
+ *
+ *  The createConversationInfoList function performs the query and creates the data structure.
+ */
+public abstract class MessageNotificationState extends NotificationState {
+    // Logging
+    static final String TAG = LogUtil.BUGLE_NOTIFICATIONS_TAG;
+    private static final int MAX_MESSAGES_IN_WEARABLE_PAGE = 20;
+
+    private static final int MAX_CHARACTERS_IN_GROUP_NAME = 30;
+
+    private static final int REPLY_INTENT_REQUEST_CODE_OFFSET = 0;
+    private static final int NUM_EXTRA_REQUEST_CODES_NEEDED = 1;
+    protected String mTickerSender = null;
+    protected CharSequence mTickerText = null;
+    protected String mTitle = null;
+    protected CharSequence mContent = null;
+    protected Uri mAttachmentUri = null;
+    protected String mAttachmentType = null;
+
+    @Override
+    protected Uri getAttachmentUri() {
+        return mAttachmentUri;
+    }
+
+    @Override
+    protected String getAttachmentType() {
+        return mAttachmentType;
+    }
+
+    @Override
+    public int getIcon() {
+        return R.drawable.ic_sms_light;
+    }
+
+    @Override
+    public int getPriority() {
+        // Returning PRIORITY_HIGH causes L to put up a HUD notification. Without it, the ticker
+        // isn't displayed.
+        return Notification.PRIORITY_HIGH;
+    }
+
+    /**
+     * Base class for single notification events for messages. Multiple of these
+     * may be grouped into a single conversation.
+     */
+    static class NotificationLineInfo {
+
+        final int mNotificationType;
+
+        NotificationLineInfo() {
+            mNotificationType = BugleNotifications.LOCAL_SMS_NOTIFICATION;
+        }
+
+        NotificationLineInfo(final int notificationType) {
+            mNotificationType = notificationType;
+        }
+    }
+
+    /**
+     * Information on a single chat message which should be shown in a notification.
+     */
+    static class MessageLineInfo extends NotificationLineInfo {
+        final CharSequence mText;
+        Uri mAttachmentUri;
+        String mAttachmentType;
+        final String mAuthorFullName;
+        final String mAuthorFirstName;
+        boolean mIsManualDownloadNeeded;
+        final String mMessageId;
+
+        MessageLineInfo(final boolean isGroup, final String authorFullName,
+                final String authorFirstName, final CharSequence text, final Uri attachmentUrl,
+                final String attachmentType, final boolean isManualDownloadNeeded,
+                final String messageId) {
+            super(BugleNotifications.LOCAL_SMS_NOTIFICATION);
+            mAuthorFullName = authorFullName;
+            mAuthorFirstName = authorFirstName;
+            mText = text;
+            mAttachmentUri = attachmentUrl;
+            mAttachmentType = attachmentType;
+            mIsManualDownloadNeeded = isManualDownloadNeeded;
+            mMessageId = messageId;
+        }
+    }
+
+    /**
+     * Information on all the notification messages within a single conversation.
+     */
+    static class ConversationLineInfo {
+        // Conversation id of the latest message in the notification for this merged conversation.
+        final String mConversationId;
+
+        // True if this represents a group conversation.
+        final boolean mIsGroup;
+
+        // Name of the group conversation if available.
+        final String mGroupConversationName;
+
+        // True if this conversation's recipients includes one or more email address(es)
+        // (see ConversationColumns.INCLUDE_EMAIL_ADDRESS)
+        final boolean mIncludeEmailAddress;
+
+        // Timestamp of the latest message
+        final long mReceivedTimestamp;
+
+        // Self participant id.
+        final String mSelfParticipantId;
+
+        // List of individual line notifications to be parsed later.
+        final List<NotificationLineInfo> mLineInfos;
+
+        // Total number of messages. Might be different that mLineInfos.size() as the number of
+        // line infos is capped.
+        int mTotalMessageCount;
+
+        // Custom ringtone if set
+        final String mRingtoneUri;
+
+        // Should notification be enabled for this conversation?
+        final boolean mNotificationEnabled;
+
+        // Should notifications vibrate for this conversation?
+        final boolean mNotificationVibrate;
+
+        // Avatar uri of sender
+        final Uri mAvatarUri;
+
+        // Contact uri of sender
+        final Uri mContactUri;
+
+        // Subscription id.
+        final int mSubId;
+
+        // Number of participants
+        final int mParticipantCount;
+
+        public ConversationLineInfo(final String conversationId,
+                final boolean isGroup,
+                final String groupConversationName,
+                final boolean includeEmailAddress,
+                final long receivedTimestamp,
+                final String selfParticipantId,
+                final String ringtoneUri,
+                final boolean notificationEnabled,
+                final boolean notificationVibrate,
+                final Uri avatarUri,
+                final Uri contactUri,
+                final int subId,
+                final int participantCount) {
+            mConversationId = conversationId;
+            mIsGroup = isGroup;
+            mGroupConversationName = groupConversationName;
+            mIncludeEmailAddress = includeEmailAddress;
+            mReceivedTimestamp = receivedTimestamp;
+            mSelfParticipantId = selfParticipantId;
+            mLineInfos = new ArrayList<NotificationLineInfo>();
+            mTotalMessageCount = 0;
+            mRingtoneUri = ringtoneUri;
+            mAvatarUri = avatarUri;
+            mContactUri = contactUri;
+            mNotificationEnabled = notificationEnabled;
+            mNotificationVibrate = notificationVibrate;
+            mSubId = subId;
+            mParticipantCount = participantCount;
+        }
+
+        public int getLatestMessageNotificationType() {
+            final MessageLineInfo messageLineInfo = getLatestMessageLineInfo();
+            if (messageLineInfo == null) {
+                return BugleNotifications.LOCAL_SMS_NOTIFICATION;
+            }
+            return messageLineInfo.mNotificationType;
+        }
+
+        public String getLatestMessageId() {
+            final MessageLineInfo messageLineInfo = getLatestMessageLineInfo();
+            if (messageLineInfo == null) {
+                return null;
+            }
+            return messageLineInfo.mMessageId;
+        }
+
+        public boolean getDoesLatestMessageNeedDownload() {
+            final MessageLineInfo messageLineInfo = getLatestMessageLineInfo();
+            if (messageLineInfo == null) {
+                return false;
+            }
+            return messageLineInfo.mIsManualDownloadNeeded;
+        }
+
+        private MessageLineInfo getLatestMessageLineInfo() {
+            // The latest message is stored at index zero of the message line infos.
+            if (mLineInfos.size() > 0 && mLineInfos.get(0) instanceof MessageLineInfo) {
+                return (MessageLineInfo) mLineInfos.get(0);
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Information on all the notification messages across all conversations.
+     */
+    public static class ConversationInfoList {
+        final int mMessageCount;
+        final List<ConversationLineInfo> mConvInfos;
+        public ConversationInfoList(final int count, final List<ConversationLineInfo> infos) {
+            mMessageCount = count;
+            mConvInfos = infos;
+        }
+    }
+
+    final ConversationInfoList mConvList;
+    private long mLatestReceivedTimestamp;
+
+    private static ConversationIdSet makeConversationIdSet(final ConversationInfoList convList) {
+        ConversationIdSet set = null;
+        if (convList != null && convList.mConvInfos != null && convList.mConvInfos.size() > 0) {
+            set = new ConversationIdSet();
+            for (final ConversationLineInfo info : convList.mConvInfos) {
+                    set.add(info.mConversationId);
+            }
+        }
+        return set;
+    }
+
+    protected MessageNotificationState(final ConversationInfoList convList) {
+        super(makeConversationIdSet(convList));
+        mConvList = convList;
+        mType = PendingIntentConstants.SMS_NOTIFICATION_ID;
+        mLatestReceivedTimestamp = Long.MIN_VALUE;
+        if (convList != null) {
+            for (final ConversationLineInfo info : convList.mConvInfos) {
+                mLatestReceivedTimestamp = Math.max(mLatestReceivedTimestamp,
+                        info.mReceivedTimestamp);
+            }
+        }
+    }
+
+    @Override
+    public long getLatestReceivedTimestamp() {
+        return mLatestReceivedTimestamp;
+    }
+
+    @Override
+    public int getNumRequestCodesNeeded() {
+        // Get additional request codes for the Reply PendingIntent (wearables only)
+        // and the DND PendingIntent.
+        return super.getNumRequestCodesNeeded() + NUM_EXTRA_REQUEST_CODES_NEEDED;
+    }
+
+    private int getBaseExtraRequestCode() {
+        return mBaseRequestCode + super.getNumRequestCodesNeeded();
+    }
+
+    public int getReplyIntentRequestCode() {
+        return getBaseExtraRequestCode() + REPLY_INTENT_REQUEST_CODE_OFFSET;
+    }
+
+    @Override
+    public PendingIntent getClearIntent() {
+        return UIIntents.get().getPendingIntentForClearingNotifications(
+                    Factory.get().getApplicationContext(),
+                    BugleNotifications.UPDATE_MESSAGES,
+                    mConversationIds,
+                    getClearIntentRequestCode());
+    }
+
+    /**
+     * Notification for multiple messages in at least 2 different conversations.
+     */
+    public static class MultiConversationNotificationState extends MessageNotificationState {
+
+        public final List<MessageNotificationState>
+                mChildren = new ArrayList<MessageNotificationState>();
+
+        public MultiConversationNotificationState(
+                final ConversationInfoList convList, final MessageNotificationState state) {
+            super(convList);
+            mAttachmentUri = null;
+            mAttachmentType = null;
+
+            // Pull the ticker title/text from the single notification
+            mTickerSender = state.getTitle();
+            mTitle = Factory.get().getApplicationContext().getResources().getQuantityString(
+                    R.plurals.notification_new_messages,
+                    convList.mMessageCount, convList.mMessageCount);
+            mTickerText = state.mContent;
+
+            // Create child notifications for each conversation,
+            // which will be displayed (only) on a wearable device.
+            for (int i = 0; i < convList.mConvInfos.size(); i++) {
+                final ConversationLineInfo convInfo = convList.mConvInfos.get(i);
+                if (!(convInfo.mLineInfos.get(0) instanceof MessageLineInfo)) {
+                    continue;
+                }
+                setPeopleForConversation(convInfo.mConversationId);
+                final ConversationInfoList list = new ConversationInfoList(
+                        convInfo.mTotalMessageCount, Lists.newArrayList(convInfo));
+                mChildren.add(new BundledMessageNotificationState(list, i));
+            }
+        }
+
+        @Override
+        public int getIcon() {
+            return R.drawable.ic_sms_multi_light;
+        }
+
+        @Override
+        protected NotificationCompat.Style build(final Builder builder) {
+            builder.setContentTitle(mTitle);
+            NotificationCompat.InboxStyle inboxStyle = null;
+            inboxStyle = new NotificationCompat.InboxStyle(builder);
+
+            final Context context = Factory.get().getApplicationContext();
+            // enumeration_comma is defined as ", "
+            final String separator = context.getString(R.string.enumeration_comma);
+            final StringBuilder senders = new StringBuilder();
+            long when = 0;
+            for (int i = 0; i < mConvList.mConvInfos.size(); i++) {
+                final ConversationLineInfo convInfo = mConvList.mConvInfos.get(i);
+                if (convInfo.mReceivedTimestamp > when) {
+                    when = convInfo.mReceivedTimestamp;
+                }
+                String sender;
+                CharSequence text;
+                final NotificationLineInfo lineInfo = convInfo.mLineInfos.get(0);
+                final MessageLineInfo messageLineInfo = (MessageLineInfo) lineInfo;
+                if (convInfo.mIsGroup) {
+                    sender = (convInfo.mGroupConversationName.length() >
+                            MAX_CHARACTERS_IN_GROUP_NAME) ?
+                                    truncateGroupMessageName(convInfo.mGroupConversationName)
+                                    : convInfo.mGroupConversationName;
+                } else {
+                    sender = messageLineInfo.mAuthorFullName;
+                }
+                text = messageLineInfo.mText;
+                mAttachmentUri = messageLineInfo.mAttachmentUri;
+                mAttachmentType = messageLineInfo.mAttachmentType;
+
+                inboxStyle.addLine(BugleNotifications.formatInboxMessage(
+                        sender, text, mAttachmentUri, mAttachmentType));
+                if (sender != null) {
+                    if (senders.length() > 0) {
+                        senders.append(separator);
+                    }
+                    senders.append(sender);
+                }
+            }
+            // for collapsed state
+            mContent = senders;
+            builder.setContentText(senders)
+                .setTicker(getTicker())
+                .setWhen(when);
+
+            return inboxStyle;
+        }
+    }
+
+    /**
+     * Truncate group conversation name to be displayed in the notifications. This either truncates
+     * the entire group name or finds the last comma in the available length and truncates the name
+     * at that point
+     */
+    private static String truncateGroupMessageName(final String conversationName) {
+        int endIndex = MAX_CHARACTERS_IN_GROUP_NAME;
+        for (int i = MAX_CHARACTERS_IN_GROUP_NAME; i >= 0; i--) {
+            // The dividing marker should stay consistent with ConversationListItemData.DIVIDER_TEXT
+            if (conversationName.charAt(i) == ',') {
+                endIndex = i;
+                break;
+            }
+        }
+        return conversationName.substring(0, endIndex) + '\u2026';
+    }
+
+    /**
+     * Notification for multiple messages in a single conversation. Also used if there is a single
+     * message in a single conversation.
+     */
+    public static class MultiMessageNotificationState extends MessageNotificationState {
+
+        public MultiMessageNotificationState(final ConversationInfoList convList) {
+            super(convList);
+            // This conversation has been accepted.
+            final ConversationLineInfo convInfo = convList.mConvInfos.get(0);
+            setAvatarUrlsForConversation(convInfo.mConversationId);
+            setPeopleForConversation(convInfo.mConversationId);
+
+            final Context context = Factory.get().getApplicationContext();
+            MessageLineInfo messageInfo = (MessageLineInfo) convInfo.mLineInfos.get(0);
+            // attached photo
+            mAttachmentUri = messageInfo.mAttachmentUri;
+            mAttachmentType = messageInfo.mAttachmentType;
+            mContent = messageInfo.mText;
+
+            if (mAttachmentUri != null) {
+                // The default attachment type is an image, since that's what was originally
+                // supported. When there's no content type, assume it's an image.
+                int message = R.string.notification_picture;
+                if (ContentType.isAudioType(mAttachmentType)) {
+                    message = R.string.notification_audio;
+                } else if (ContentType.isVideoType(mAttachmentType)) {
+                    message = R.string.notification_video;
+                } else if (ContentType.isVCardType(mAttachmentType)) {
+                    message = R.string.notification_vcard;
+                }
+                final String attachment = context.getString(message);
+                final SpannableStringBuilder spanBuilder = new SpannableStringBuilder();
+                if (!TextUtils.isEmpty(mContent)) {
+                    spanBuilder.append(mContent).append(System.getProperty("line.separator"));
+                }
+                final int start = spanBuilder.length();
+                spanBuilder.append(attachment);
+                spanBuilder.setSpan(new StyleSpan(Typeface.ITALIC), start, spanBuilder.length(),
+                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                mContent = spanBuilder;
+            }
+            if (convInfo.mIsGroup) {
+                // When the message is part of a group, the sender's first name
+                // is prepended to the message, but not for the ticker message.
+                mTickerText = mContent;
+                mTickerSender = messageInfo.mAuthorFullName;
+                // append the bold name to the front of the message
+                mContent = BugleNotifications.buildSpaceSeparatedMessage(
+                        messageInfo.mAuthorFullName, mContent, mAttachmentUri,
+                        mAttachmentType);
+                mTitle = convInfo.mGroupConversationName;
+            } else {
+                // No matter how many messages there are, since this is a 1:1, just
+                // get the author full name from the first one.
+                messageInfo = (MessageLineInfo) convInfo.mLineInfos.get(0);
+                mTitle = messageInfo.mAuthorFullName;
+            }
+        }
+
+        @Override
+        protected NotificationCompat.Style build(final Builder builder) {
+            builder.setContentTitle(mTitle)
+                .setTicker(getTicker());
+
+            NotificationCompat.Style notifStyle = null;
+            final ConversationLineInfo convInfo = mConvList.mConvInfos.get(0);
+            final List<NotificationLineInfo> lineInfos = convInfo.mLineInfos;
+            final int messageCount = lineInfos.size();
+            // At this point, all the messages come from the same conversation. We need to load
+            // the sender's avatar and then finish building the notification on a callback.
+
+            builder.setContentText(mContent);   // for collapsed state
+
+            if (messageCount == 1) {
+                final boolean shouldShowImage = ContentType.isImageType(mAttachmentType)
+                        || (ContentType.isVideoType(mAttachmentType)
+                        && VideoThumbnailRequest.shouldShowIncomingVideoThumbnails());
+                if (mAttachmentUri != null && shouldShowImage) {
+                    // Show "Picture" as the content
+                    final MessageLineInfo messageLineInfo = (MessageLineInfo) lineInfos.get(0);
+                    String authorFirstName = messageLineInfo.mAuthorFirstName;
+
+                    // For the collapsed state, just show "picture" unless this is a
+                    // group conversation. If it's a group, show the sender name and
+                    // "picture".
+                    final CharSequence tickerTag =
+                            BugleNotifications.formatAttachmentTag(authorFirstName,
+                                    mAttachmentType);
+                    // For 1:1 notifications don't show first name in the notification, but
+                    // do show it in the ticker text
+                    CharSequence pictureTag = tickerTag;
+                    if (!convInfo.mIsGroup) {
+                        authorFirstName = null;
+                        pictureTag = BugleNotifications.formatAttachmentTag(authorFirstName,
+                                mAttachmentType);
+                    }
+                    builder.setContentText(pictureTag);
+                    builder.setTicker(tickerTag);
+
+                    notifStyle = new NotificationCompat.BigPictureStyle(builder)
+                        .setSummaryText(BugleNotifications.formatInboxMessage(
+                                authorFirstName,
+                                null, null,
+                                null));  // expanded state, just show sender
+                } else {
+                    notifStyle = new NotificationCompat.BigTextStyle(builder)
+                    .bigText(mContent);
+                }
+            } else {
+                // We've got multiple messages for the same sender.
+                // Starting with the oldest new message, display the full text of each message.
+                // Begin a line for each subsequent message.
+                final SpannableStringBuilder buf = new SpannableStringBuilder();
+
+                for (int i = lineInfos.size() - 1; i >= 0; --i) {
+                    final NotificationLineInfo info = lineInfos.get(i);
+                    final MessageLineInfo messageLineInfo = (MessageLineInfo) info;
+                    mAttachmentUri = messageLineInfo.mAttachmentUri;
+                    mAttachmentType = messageLineInfo.mAttachmentType;
+                    CharSequence text = messageLineInfo.mText;
+                    if (!TextUtils.isEmpty(text) || mAttachmentUri != null) {
+                        if (convInfo.mIsGroup) {
+                            // append the bold name to the front of the message
+                            text = BugleNotifications.buildSpaceSeparatedMessage(
+                                    messageLineInfo.mAuthorFullName, text, mAttachmentUri,
+                                    mAttachmentType);
+                        } else {
+                            text = BugleNotifications.buildSpaceSeparatedMessage(
+                                    null, text, mAttachmentUri, mAttachmentType);
+                        }
+                        buf.append(text);
+                        if (i > 0) {
+                            buf.append('\n');
+                        }
+                    }
+                }
+
+                // Show a single notification -- big style with the text of all the messages
+                notifStyle = new NotificationCompat.BigTextStyle(builder).bigText(buf);
+            }
+            builder.setWhen(convInfo.mReceivedTimestamp);
+            return notifStyle;
+        }
+
+    }
+
+    private static boolean firstNameUsedMoreThanOnce(
+            final HashMap<String, Integer> map, final String firstName) {
+        if (map == null) {
+            return false;
+        }
+        if (firstName == null) {
+            return false;
+        }
+        final Integer count = map.get(firstName);
+        if (count != null) {
+            return count > 1;
+        } else {
+            return false;
+        }
+    }
+
+    private static HashMap<String, Integer> scanFirstNames(final String conversationId) {
+        final Context context = Factory.get().getApplicationContext();
+        final Uri uri =
+                MessagingContentProvider.buildConversationParticipantsUri(conversationId);
+        final ConversationParticipantsData participantsData = new ConversationParticipantsData();
+
+        try (final Cursor participantsCursor = context.getContentResolver().query(
+                    uri, ParticipantData.ParticipantsQuery.PROJECTION, null, null, null)) {
+            participantsData.bind(participantsCursor);
+        }
+
+        final Iterator<ParticipantData> iter = participantsData.iterator();
+
+        final HashMap<String, Integer> firstNames = new HashMap<String, Integer>();
+        boolean seenSelf = false;
+        while (iter.hasNext()) {
+            final ParticipantData participant = iter.next();
+            // Make sure we only add the self participant once
+            if (participant.isSelf()) {
+                if (seenSelf) {
+                    continue;
+                } else {
+                    seenSelf = true;
+                }
+            }
+
+            final String firstName = participant.getFirstName();
+            if (firstName == null) {
+                continue;
+            }
+
+            final int currentCount = firstNames.containsKey(firstName)
+                    ? firstNames.get(firstName)
+                    : 0;
+            firstNames.put(firstName, currentCount + 1);
+        }
+        return firstNames;
+    }
+
+    // Essentially, we're building a list of the past 20 messages for this conversation to display
+    // on the wearable.
+    public static Notification buildConversationPageForWearable(final String conversationId,
+            int participantCount) {
+        final Context context = Factory.get().getApplicationContext();
+
+        // Limit the number of messages to show. We just want enough to provide context for the
+        // notification. Fetch one more than we need, so we can tell if there are more messages
+        // before the one we're showing.
+        // TODO: in the query, a multipart message will contain a row for each part.
+        // We might need a smarter GROUP_BY. On the other hand, we might want to show each of the
+        // parts as separate messages on the wearable.
+        final int limit = MAX_MESSAGES_IN_WEARABLE_PAGE + 1;
+
+        final List<CharSequence> messages = Lists.newArrayList();
+        boolean hasSeenMessagesBeforeNotification = false;
+        Cursor convMessageCursor = null;
+        try {
+            final DatabaseWrapper db = DataModel.get().getDatabase();
+
+            final String[] queryArgs = { conversationId };
+            final String convPageSql = ConversationMessageData.getWearableQuerySql() + " LIMIT " +
+                    limit;
+            convMessageCursor = db.rawQuery(
+                    convPageSql,
+                    queryArgs);
+
+            if (convMessageCursor == null || !convMessageCursor.moveToFirst()) {
+                return null;
+            }
+            final ConversationMessageData convMessageData =
+                    new ConversationMessageData();
+
+            final HashMap<String, Integer> firstNames = scanFirstNames(conversationId);
+            do {
+                convMessageData.bind(convMessageCursor);
+
+                final String authorFullName = convMessageData.getSenderFullName();
+                final String authorFirstName = convMessageData.getSenderFirstName();
+                String text = convMessageData.getText();
+
+                final boolean isSmsPushNotification = convMessageData.getIsMmsNotification();
+
+                // if auto-download was off to show a message to tap to download the message. We
+                // might need to get that working again.
+                if (isSmsPushNotification && text != null) {
+                    text = convertHtmlAndStripUrls(text).toString();
+                }
+                // Skip messages without any content
+                if (TextUtils.isEmpty(text) && !convMessageData.hasAttachments()) {
+                    continue;
+                }
+                // Track whether there are messages prior to the one(s) shown in the notification.
+                if (convMessageData.getIsSeen()) {
+                    hasSeenMessagesBeforeNotification = true;
+                }
+
+                final boolean usedMoreThanOnce = firstNameUsedMoreThanOnce(
+                        firstNames, authorFirstName);
+                String displayName = usedMoreThanOnce ? authorFullName : authorFirstName;
+                if (TextUtils.isEmpty(displayName)) {
+                    if (convMessageData.getIsIncoming()) {
+                        displayName = convMessageData.getSenderDisplayDestination();
+                        if (TextUtils.isEmpty(displayName)) {
+                            displayName = context.getString(R.string.unknown_sender);
+                        }
+                    } else {
+                        displayName = context.getString(R.string.unknown_self_participant);
+                    }
+                }
+
+                Uri attachmentUri = null;
+                String attachmentType = null;
+                final List<MessagePartData> attachments = convMessageData.getAttachments();
+                for (final MessagePartData messagePartData : attachments) {
+                    // Look for the first attachment that's not the text piece.
+                    if (!messagePartData.isText()) {
+                        attachmentUri = messagePartData.getContentUri();
+                        attachmentType = messagePartData.getContentType();
+                        break;
+                    }
+                }
+
+                final CharSequence message = BugleNotifications.buildSpaceSeparatedMessage(
+                        displayName, text, attachmentUri, attachmentType);
+                messages.add(message);
+
+            } while (convMessageCursor.moveToNext());
+        } finally {
+            if (convMessageCursor != null) {
+                convMessageCursor.close();
+            }
+        }
+
+        // If there is no conversation history prior to what is already visible in the main
+        // notification, there's no need to include the conversation log, too.
+        final int maxMessagesInNotification = getMaxMessagesInConversationNotification();
+        if (!hasSeenMessagesBeforeNotification && messages.size() <= maxMessagesInNotification) {
+            return null;
+        }
+
+        final SpannableStringBuilder bigText = new SpannableStringBuilder();
+        // There is at least 1 message prior to the first one that we're going to show.
+        // Indicate this by inserting an ellipsis at the beginning of the conversation log.
+        if (convMessageCursor.getCount() == limit) {
+            bigText.append(context.getString(R.string.ellipsis) + "\n\n");
+            if (messages.size() > MAX_MESSAGES_IN_WEARABLE_PAGE) {
+                messages.remove(messages.size() - 1);
+            }
+        }
+        // Messages are sorted in descending timestamp order, so iterate backwards
+        // to get them back in ascending order for display purposes.
+        for (int i = messages.size() - 1; i >= 0; --i) {
+            bigText.append(messages.get(i));
+            if (i > 0) {
+                bigText.append("\n\n");
+            }
+        }
+        ++participantCount;     // Add in myself
+
+        if (participantCount > 2) {
+            final SpannableString statusText = new SpannableString(
+                    context.getResources().getQuantityString(R.plurals.wearable_participant_count,
+                            participantCount, participantCount));
+            statusText.setSpan(new ForegroundColorSpan(context.getResources().getColor(
+                    R.color.wearable_notification_participants_count)), 0, statusText.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            bigText.append("\n\n").append(statusText);
+        }
+
+        final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context);
+        final NotificationCompat.Style notifStyle =
+                new NotificationCompat.BigTextStyle(notifBuilder).bigText(bigText);
+        notifBuilder.setStyle(notifStyle);
+
+        final WearableExtender wearableExtender = new WearableExtender();
+        wearableExtender.setStartScrollBottom(true);
+        notifBuilder.extend(wearableExtender);
+
+        return notifBuilder.build();
+    }
+
+    /**
+     * Notification for one or more messages in a single conversation, which is bundled together
+     * with notifications for other conversations on a wearable device.
+     */
+    public static class BundledMessageNotificationState extends MultiMessageNotificationState {
+        public int mGroupOrder;
+        public BundledMessageNotificationState(final ConversationInfoList convList,
+                final int groupOrder) {
+            super(convList);
+            mGroupOrder = groupOrder;
+        }
+    }
+
+    /**
+     * Performs a query on the database.
+     */
+    private static ConversationInfoList createConversationInfoList() {
+        // Map key is conversation id. We use LinkedHashMap to ensure that entries are iterated in
+        // the same order they were originally added. We scan unseen messages from newest to oldest,
+        // so the corresponding conversations are added in that order, too.
+        final Map<String, ConversationLineInfo> convLineInfos = new LinkedHashMap<>();
+        int messageCount = 0;
+
+        Cursor convMessageCursor = null;
+        try {
+            final Context context = Factory.get().getApplicationContext();
+            final DatabaseWrapper db = DataModel.get().getDatabase();
+
+            convMessageCursor = db.rawQuery(
+                    ConversationMessageData.getNotificationQuerySql(),
+                    null);
+
+            if (convMessageCursor != null && convMessageCursor.moveToFirst()) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "MessageNotificationState: Found unseen message notifications.");
+                }
+                final ConversationMessageData convMessageData =
+                        new ConversationMessageData();
+
+                HashMap<String, Integer> firstNames = null;
+                String conversationIdForFirstNames = null;
+                String groupConversationName = null;
+                final int maxMessages = getMaxMessagesInConversationNotification();
+
+                do {
+                    convMessageData.bind(convMessageCursor);
+
+                    // First figure out if this is a valid message.
+                    String authorFullName = convMessageData.getSenderFullName();
+                    String authorFirstName = convMessageData.getSenderFirstName();
+                    final String messageText = convMessageData.getText();
+
+                    final String convId = convMessageData.getConversationId();
+                    final String messageId = convMessageData.getMessageId();
+
+                    CharSequence text = messageText;
+                    final boolean isManualDownloadNeeded = convMessageData.getIsMmsNotification();
+                    if (isManualDownloadNeeded) {
+                        // Don't try and convert the text from html if it's sms and not a sms push
+                        // notification.
+                        Assert.equals(MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD,
+                                convMessageData.getStatus());
+                        text = context.getResources().getString(
+                                R.string.message_title_manual_download);
+                    }
+                    ConversationLineInfo currConvInfo = convLineInfos.get(convId);
+                    if (currConvInfo == null) {
+                        final ConversationListItemData convData =
+                                ConversationListItemData.getExistingConversation(db, convId);
+                        if (!convData.getNotificationEnabled()) {
+                            // Skip conversations that have notifications disabled.
+                            continue;
+                        }
+                        final int subId = BugleDatabaseOperations.getSelfSubscriptionId(db,
+                                convData.getSelfId());
+                        groupConversationName = convData.getName();
+                        final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                                convMessageData.getSenderProfilePhotoUri(),
+                                convMessageData.getSenderFullName(),
+                                convMessageData.getSenderNormalizedDestination(),
+                                convMessageData.getSenderContactLookupKey());
+                        currConvInfo = new ConversationLineInfo(convId,
+                                convData.getIsGroup(),
+                                groupConversationName,
+                                convData.getIncludeEmailAddress(),
+                                convMessageData.getReceivedTimeStamp(),
+                                convData.getSelfId(),
+                                convData.getNotificationSoundUri(),
+                                convData.getNotificationEnabled(),
+                                convData.getNotifiationVibrate(),
+                                avatarUri,
+                                convMessageData.getSenderContactLookupUri(),
+                                subId,
+                                convData.getParticipantCount());
+                        convLineInfos.put(convId, currConvInfo);
+                    }
+                    // Prepare the message line
+                    if (currConvInfo.mTotalMessageCount < maxMessages) {
+                        if (currConvInfo.mIsGroup) {
+                            if (authorFirstName == null) {
+                                // authorFullName might be null as well. In that case, we won't
+                                // show an author. That is better than showing all the group
+                                // names again on the 2nd line.
+                                authorFirstName = authorFullName;
+                            }
+                        } else {
+                            // don't recompute this if we don't need to
+                            if (!TextUtils.equals(conversationIdForFirstNames, convId)) {
+                                firstNames = scanFirstNames(convId);
+                                conversationIdForFirstNames = convId;
+                            }
+                            if (firstNames != null) {
+                                final Integer count = firstNames.get(authorFirstName);
+                                if (count != null && count > 1) {
+                                    authorFirstName = authorFullName;
+                                }
+                            }
+
+                            if (authorFullName == null) {
+                                authorFullName = groupConversationName;
+                            }
+                            if (authorFirstName == null) {
+                                authorFirstName = groupConversationName;
+                            }
+                        }
+                        final String subjectText = MmsUtils.cleanseMmsSubject(
+                                context.getResources(),
+                                convMessageData.getMmsSubject());
+                        if (!TextUtils.isEmpty(subjectText)) {
+                            final String subjectLabel =
+                                    context.getString(R.string.subject_label);
+                            final SpannableStringBuilder spanBuilder =
+                                    new SpannableStringBuilder();
+
+                            spanBuilder.append(context.getString(R.string.notification_subject,
+                                    subjectLabel, subjectText));
+                            spanBuilder.setSpan(new TextAppearanceSpan(
+                                    context, R.style.NotificationSubjectText), 0,
+                                    subjectLabel.length(),
+                                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                            if (!TextUtils.isEmpty(text)) {
+                                // Now add the actual message text below the subject header.
+                                spanBuilder.append(System.getProperty("line.separator") + text);
+                            }
+                            text = spanBuilder;
+                        }
+                        // If we've got attachments, find the best one. If one of the messages is
+                        // a photo, save the url so we'll display a big picture notification.
+                        // Otherwise, show the first one we find.
+                        Uri attachmentUri = null;
+                        String attachmentType = null;
+                        final MessagePartData messagePartData =
+                                getMostInterestingAttachment(convMessageData);
+                        if (messagePartData != null) {
+                            attachmentUri = messagePartData.getContentUri();
+                            attachmentType = messagePartData.getContentType();
+                        }
+                        currConvInfo.mLineInfos.add(new MessageLineInfo(currConvInfo.mIsGroup,
+                                authorFullName, authorFirstName, text,
+                                attachmentUri, attachmentType, isManualDownloadNeeded, messageId));
+                    }
+                    messageCount++;
+                    currConvInfo.mTotalMessageCount++;
+                } while (convMessageCursor.moveToNext());
+            }
+        } finally {
+            if (convMessageCursor != null) {
+                convMessageCursor.close();
+            }
+        }
+        if (convLineInfos.isEmpty()) {
+            return null;
+        } else {
+            return new ConversationInfoList(messageCount,
+                    Lists.newLinkedList(convLineInfos.values()));
+        }
+    }
+
+    /**
+     * Scans all the attachments for a message and returns the most interesting one that we'll
+     * show in a notification. By order of importance, in case there are multiple attachments:
+     *      1- an image (because we can show the image as a BigPictureNotification)
+     *      2- a video (because we can show a video frame as a BigPictureNotification)
+     *      3- a vcard
+     *      4- an audio attachment
+     * @return MessagePartData for the most interesting part. Can be null.
+     */
+    private static MessagePartData getMostInterestingAttachment(
+            final ConversationMessageData convMessageData) {
+        final List<MessagePartData> attachments = convMessageData.getAttachments();
+
+        MessagePartData imagePart = null;
+        MessagePartData audioPart = null;
+        MessagePartData vcardPart = null;
+        MessagePartData videoPart = null;
+
+        // 99.99% of the time there will be 0 or 1 part, since receiving slideshows is so
+        // uncommon.
+
+        // Remember the first of each type of part.
+        for (final MessagePartData messagePartData : attachments) {
+            if (messagePartData.isImage() && imagePart == null) {
+                imagePart = messagePartData;
+            }
+            if (messagePartData.isVideo() && videoPart == null) {
+                videoPart = messagePartData;
+            }
+            if (messagePartData.isVCard() && vcardPart == null) {
+                vcardPart = messagePartData;
+            }
+            if (messagePartData.isAudio() && audioPart == null) {
+                audioPart = messagePartData;
+            }
+        }
+        if (imagePart != null) {
+            return imagePart;
+        } else if (videoPart != null) {
+            return videoPart;
+        } else if (audioPart != null) {
+            return audioPart;
+        } else if (vcardPart != null) {
+            return vcardPart;
+        }
+        return null;
+    }
+
+    private static int getMaxMessagesInConversationNotification() {
+        if (!BugleNotifications.isWearCompanionAppInstalled()) {
+            return BugleGservices.get().getInt(
+                    BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION,
+                    BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_DEFAULT);
+        }
+        return BugleGservices.get().getInt(
+                BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE,
+                BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE_DEFAULT);
+    }
+
+    /**
+     * Scans the database for messages that need to go into notifications. Creates the appropriate
+     * MessageNotificationState depending on if there are multiple senders, or
+     * messages from one sender.
+     * @return NotificationState for the notification created.
+     */
+    public static NotificationState getNotificationState() {
+        MessageNotificationState state = null;
+        final ConversationInfoList convList = createConversationInfoList();
+
+        if (convList == null || convList.mConvInfos.size() == 0) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "MessageNotificationState: No unseen notifications");
+            }
+        } else {
+            final ConversationLineInfo convInfo = convList.mConvInfos.get(0);
+            state = new MultiMessageNotificationState(convList);
+
+            if (convList.mConvInfos.size() > 1) {
+                // We've got notifications across multiple conversations. Pass in the notification
+                // we just built of the most recent notification so we can use that to show the
+                // user the new message in the ticker.
+                state = new MultiConversationNotificationState(convList, state);
+            } else {
+                // For now, only show avatars for notifications for a single conversation.
+                if (convInfo.mAvatarUri != null) {
+                    if (state.mParticipantAvatarsUris == null) {
+                        state.mParticipantAvatarsUris = new ArrayList<Uri>(1);
+                    }
+                    state.mParticipantAvatarsUris.add(convInfo.mAvatarUri);
+                }
+                if (convInfo.mContactUri != null) {
+                    if (state.mParticipantContactUris == null) {
+                        state.mParticipantContactUris = new ArrayList<Uri>(1);
+                    }
+                    state.mParticipantContactUris.add(convInfo.mContactUri);
+                }
+            }
+        }
+        if (state != null && LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "MessageNotificationState: Notification state created"
+                    + ", title = "
+                    + (state.mTickerSender != null ? state.mTickerSender : state.mTitle)
+                    + ", content = "
+                    + (state.mTickerText != null ? state.mTickerText : state.mContent));
+        }
+        return state;
+    }
+
+    protected String getTitle() {
+        return mTitle;
+    }
+
+    @Override
+    public int getLatestMessageNotificationType() {
+        // This function is called to determine whether the most recent notification applies
+        // to an sms conversation or a hangout conversation. We have different ringtone/vibrate
+        // settings for both types of conversations.
+        if (mConvList.mConvInfos.size() > 0) {
+            final ConversationLineInfo convInfo = mConvList.mConvInfos.get(0);
+            return convInfo.getLatestMessageNotificationType();
+        }
+        return BugleNotifications.LOCAL_SMS_NOTIFICATION;
+    }
+
+    @Override
+    public String getRingtoneUri() {
+        if (mConvList.mConvInfos.size() > 0) {
+            return mConvList.mConvInfos.get(0).mRingtoneUri;
+        }
+        return null;
+    }
+
+    @Override
+    public boolean getNotificationVibrate() {
+        if (mConvList.mConvInfos.size() > 0) {
+            return mConvList.mConvInfos.get(0).mNotificationVibrate;
+        }
+        return false;
+    }
+
+    protected CharSequence getTicker() {
+        return BugleNotifications.buildColonSeparatedMessage(
+                mTickerSender != null ? mTickerSender : mTitle,
+                mTickerText != null ? mTickerText : mContent,
+                null,
+                null);
+    }
+
+    private static CharSequence convertHtmlAndStripUrls(final String s) {
+        final Spanned text = Html.fromHtml(s);
+        if (text instanceof Spannable) {
+            stripUrls((Spannable) text);
+        }
+        return text;
+    }
+
+    // Since we don't want to show URLs in notifications, a function
+    // to remove them in place.
+    private static void stripUrls(final Spannable text) {
+        final URLSpan[] spans = text.getSpans(0, text.length(), URLSpan.class);
+        for (final URLSpan span : spans) {
+            text.removeSpan(span);
+        }
+    }
+
+    /*
+    private static void updateAlertStatusMessages(final long thresholdDeltaMs) {
+        // TODO may need this when supporting error notifications
+        final EsDatabaseHelper helper = EsDatabaseHelper.getDatabaseHelper();
+        final ContentValues values = new ContentValues();
+        final long nowMicros = System.currentTimeMillis() * 1000;
+        values.put(MessageColumns.ALERT_STATUS, "1");
+        final String selection =
+                MessageColumns.ALERT_STATUS + "=0 AND (" +
+                MessageColumns.STATUS + "=" + EsProvider.MESSAGE_STATUS_FAILED_TO_SEND + " OR (" +
+                MessageColumns.STATUS + "!=" + EsProvider.MESSAGE_STATUS_ON_SERVER + " AND " +
+                MessageColumns.TIMESTAMP + "+" + thresholdDeltaMs*1000 + "<" + nowMicros + ")) ";
+
+        final int updateCount = helper.getWritableDatabaseWrapper().update(
+                EsProvider.MESSAGES_TABLE,
+                values,
+                selection,
+                null);
+        if (updateCount > 0) {
+            EsConversationsData.notifyConversationsChanged();
+        }
+    }*/
+
+    static CharSequence applyWarningTextColor(final Context context,
+            final CharSequence text) {
+        if (text == null) {
+            return null;
+        }
+        final SpannableStringBuilder spanBuilder = new SpannableStringBuilder();
+        spanBuilder.append(text);
+        spanBuilder.setSpan(new ForegroundColorSpan(context.getResources().getColor(
+                R.color.notification_warning_color)), 0, text.length(),
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return spanBuilder;
+    }
+
+    /**
+     * Check for failed messages and post notifications as needed.
+     * TODO: Rewrite this as a NotificationState.
+     */
+    public static void checkFailedMessages() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final Cursor messageDataCursor = db.query(DatabaseHelper.MESSAGES_TABLE,
+            MessageData.getProjection(),
+            FailedMessageQuery.FAILED_MESSAGES_WHERE_CLAUSE,
+            null /*selectionArgs*/,
+            null /*groupBy*/,
+            null /*having*/,
+            FailedMessageQuery.FAILED_ORDER_BY);
+
+        try {
+            final Context context = Factory.get().getApplicationContext();
+            final Resources resources = context.getResources();
+            final NotificationManagerCompat notificationManager =
+                    NotificationManagerCompat.from(context);
+            if (messageDataCursor != null) {
+                final MessageData messageData = new MessageData();
+
+                final HashSet<String> conversationsWithFailedMessages = new HashSet<String>();
+
+                // track row ids in case we want to display something that requires this
+                // information
+                final ArrayList<Integer> failedMessages = new ArrayList<Integer>();
+
+                int cursorPosition = -1;
+                final long when = 0;
+
+                messageDataCursor.moveToPosition(-1);
+                while (messageDataCursor.moveToNext()) {
+                    messageData.bind(messageDataCursor);
+
+                    final String conversationId = messageData.getConversationId();
+                    if (DataModel.get().isNewMessageObservable(conversationId)) {
+                        // Don't post a system notification for an observable conversation
+                        // because we already show an angry red annotation in the conversation
+                        // itself or in the conversation preview snippet.
+                        continue;
+                    }
+
+                    cursorPosition = messageDataCursor.getPosition();
+                    failedMessages.add(cursorPosition);
+                    conversationsWithFailedMessages.add(conversationId);
+                }
+
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "Found " + failedMessages.size() + " failed messages");
+                }
+                if (failedMessages.size() > 0) {
+                    final NotificationCompat.Builder builder =
+                            new NotificationCompat.Builder(context);
+
+                    CharSequence line1;
+                    CharSequence line2;
+                    final boolean isRichContent = false;
+                    ConversationIdSet conversationIds = null;
+                    PendingIntent destinationIntent;
+                    if (failedMessages.size() == 1) {
+                        messageDataCursor.moveToPosition(cursorPosition);
+                        messageData.bind(messageDataCursor);
+                        final String conversationId =  messageData.getConversationId();
+
+                        // We have a single conversation, go directly to that conversation.
+                        destinationIntent = UIIntents.get()
+                                .getPendingIntentForConversationActivity(context,
+                                        conversationId,
+                                        null /*draft*/);
+
+                        conversationIds = ConversationIdSet.createSet(conversationId);
+
+                        final String failedMessgeSnippet = messageData.getMessageText();
+                        int failureStringId;
+                        if (messageData.getStatus() ==
+                                MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED) {
+                            failureStringId =
+                                    R.string.notification_download_failures_line1_singular;
+                        } else {
+                            failureStringId = R.string.notification_send_failures_line1_singular;
+                        }
+                        line1 = resources.getString(failureStringId);
+                        line2 = failedMessgeSnippet;
+                        // Set rich text for non-SMS messages or MMS push notification messages
+                        // which we generate locally with rich text
+                        // TODO- fix this
+//                        if (messageData.isMmsInd()) {
+//                            isRichContent = true;
+//                        }
+                    } else {
+                        // We have notifications for multiple conversation, go to the conversation
+                        // list.
+                        destinationIntent = UIIntents.get()
+                            .getPendingIntentForConversationListActivity(context);
+
+                        int line1StringId;
+                        int line2PluralsId;
+                        if (messageData.getStatus() ==
+                                MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED) {
+                            line1StringId =
+                                    R.string.notification_download_failures_line1_plural;
+                            line2PluralsId = R.plurals.notification_download_failures;
+                        } else {
+                            line1StringId = R.string.notification_send_failures_line1_plural;
+                            line2PluralsId = R.plurals.notification_send_failures;
+                        }
+                        line1 = resources.getString(line1StringId);
+                        line2 = resources.getQuantityString(
+                                line2PluralsId,
+                                conversationsWithFailedMessages.size(),
+                                failedMessages.size(),
+                                conversationsWithFailedMessages.size());
+                    }
+                    line1 = applyWarningTextColor(context, line1);
+                    line2 = applyWarningTextColor(context, line2);
+
+                    final PendingIntent pendingIntentForDelete =
+                            UIIntents.get().getPendingIntentForClearingNotifications(
+                                    context,
+                                    BugleNotifications.UPDATE_ERRORS,
+                                    conversationIds,
+                                    0);
+
+                    builder
+                        .setContentTitle(line1)
+                        .setTicker(line1)
+                        .setWhen(when > 0 ? when : System.currentTimeMillis())
+                        .setSmallIcon(R.drawable.ic_failed_light)
+                        .setDeleteIntent(pendingIntentForDelete)
+                        .setContentIntent(destinationIntent)
+                        .setSound(UriUtil.getUriForResourceId(context, R.raw.message_failure));
+                    if (isRichContent && !TextUtils.isEmpty(line2)) {
+                        final NotificationCompat.InboxStyle inboxStyle =
+                                new NotificationCompat.InboxStyle(builder);
+                        if (line2 != null) {
+                            inboxStyle.addLine(Html.fromHtml(line2.toString()));
+                        }
+                        builder.setStyle(inboxStyle);
+                    } else {
+                        builder.setContentText(line2);
+                    }
+
+                    if (builder != null) {
+                        notificationManager.notify(
+                                BugleNotifications.buildNotificationTag(
+                                        PendingIntentConstants.MSG_SEND_ERROR, null),
+                                PendingIntentConstants.MSG_SEND_ERROR,
+                                builder.build());
+                    }
+                } else {
+                    notificationManager.cancel(
+                            BugleNotifications.buildNotificationTag(
+                                    PendingIntentConstants.MSG_SEND_ERROR, null),
+                            PendingIntentConstants.MSG_SEND_ERROR);
+                }
+            }
+        } finally {
+            if (messageDataCursor != null) {
+                messageDataCursor.close();
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/MessageTextStats.java b/src/com/android/messaging/datamodel/MessageTextStats.java
new file mode 100644
index 0000000..2bd24ff
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MessageTextStats.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.telephony.SmsMessage;
+
+import com.android.messaging.sms.MmsConfig;
+
+public class MessageTextStats {
+    private boolean mMessageLengthRequiresMms;
+    private int mMessageCount;
+    private int mCodePointsRemainingInCurrentMessage;
+
+    public MessageTextStats() {
+        mCodePointsRemainingInCurrentMessage = Integer.MAX_VALUE;
+    }
+
+    public int getNumMessagesToBeSent() {
+        return mMessageCount;
+    }
+
+    public int getCodePointsRemainingInCurrentMessage() {
+        return mCodePointsRemainingInCurrentMessage;
+    }
+
+    public boolean getMessageLengthRequiresMms() {
+        return mMessageLengthRequiresMms;
+    }
+
+    public void updateMessageTextStats(final int selfSubId, final String messageText) {
+        final int[] params = SmsMessage.calculateLength(messageText, false);
+        /* SmsMessage.calculateLength returns an int[4] with:
+         *   int[0] being the number of SMS's required,
+         *   int[1] the number of code points used,
+         *   int[2] is the number of code points remaining until the next message.
+         *   int[3] is the encoding type that should be used for the message.
+         */
+        mMessageCount = params[0];
+        mCodePointsRemainingInCurrentMessage = params[2];
+
+        final MmsConfig mmsConfig = MmsConfig.get(selfSubId);
+        if (!mmsConfig.getMultipartSmsEnabled() &&
+                !mmsConfig.getSendMultipartSmsAsSeparateMessages()) {
+            // The provider doesn't support multi-part sms's and we should use MMS to
+            // send multi-part sms, so as soon as the user types
+            // an sms longer than one segment, we have to turn the message into an mms.
+            mMessageLengthRequiresMms = mMessageCount > 1;
+        } else {
+            final int threshold = mmsConfig.getSmsToMmsTextThreshold();
+            mMessageLengthRequiresMms = threshold > 0 && mMessageCount > threshold;
+        }
+        // Some carriers require any SMS message longer than 80 to be sent as MMS
+        // see b/12122333
+        int smsToMmsLengthThreshold = mmsConfig.getSmsToMmsTextLengthThreshold();
+        if (smsToMmsLengthThreshold > 0) {
+            final int usedInCurrentMessage = params[1];
+            /*
+             * A little hacky way to find out if we should count characters in double bytes.
+             * SmsMessage.calculateLength counts message code units based on the characters
+             * in input. If all of them are ascii, the max length is
+             * SmsMessage.MAX_USER_DATA_SEPTETS (160). If any of them are double-byte, like
+             * Korean or Chinese, the max length is SmsMessage.MAX_USER_DATA_BYTES (140) bytes
+             * (70 code units).
+             * Here we check if the total code units we can use is smaller than 140. If so,
+             * we know we should count threshold in double-byte, so divide the threshold by 2.
+             * In this way, we will count Korean text correctly with regard to the length threshold.
+             */
+            if (usedInCurrentMessage + mCodePointsRemainingInCurrentMessage
+                    < SmsMessage.MAX_USER_DATA_BYTES) {
+                smsToMmsLengthThreshold /= 2;
+            }
+            if (usedInCurrentMessage > smsToMmsLengthThreshold) {
+                mMessageLengthRequiresMms = true;
+            }
+        }
+    }
+
+}
diff --git a/src/com/android/messaging/datamodel/MessagingContentProvider.java b/src/com/android/messaging/datamodel/MessagingContentProvider.java
new file mode 100644
index 0000000..7688abd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MessagingContentProvider.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+
+import com.android.messaging.BugleApplication;
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.widget.BugleWidgetProvider;
+import com.android.messaging.widget.WidgetConversationProvider;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+
+/**
+ * A centralized provider for Uris exposed by Bugle.
+ *  */
+public class MessagingContentProvider extends ContentProvider {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    @VisibleForTesting
+    public static final String AUTHORITY =
+            "com.android.messaging.datamodel.MessagingContentProvider";
+    private static final String CONTENT_AUTHORITY = "content://" + AUTHORITY + '/';
+
+    // Conversations query
+    private static final String CONVERSATIONS_QUERY = "conversations";
+
+    public static final Uri CONVERSATIONS_URI = Uri.parse(CONTENT_AUTHORITY + CONVERSATIONS_QUERY);
+    static final Uri PARTS_URI = Uri.parse(CONTENT_AUTHORITY + DatabaseHelper.PARTS_TABLE);
+
+    // Messages query
+    private static final String MESSAGES_QUERY = "messages";
+
+    static final Uri MESSAGES_URI = Uri.parse(CONTENT_AUTHORITY + MESSAGES_QUERY);
+
+    public static final Uri CONVERSATION_MESSAGES_URI = Uri.parse(CONTENT_AUTHORITY +
+            MESSAGES_QUERY + "/conversation");
+
+    // Conversation participants query
+    private static final String PARTICIPANTS_QUERY = "participants";
+
+    static class ConversationParticipantsQueryColumns extends ParticipantColumns {
+        static final String CONVERSATION_ID = ConversationParticipantsColumns.CONVERSATION_ID;
+    }
+
+    static final Uri CONVERSATION_PARTICIPANTS_URI = Uri.parse(CONTENT_AUTHORITY +
+            PARTICIPANTS_QUERY + "/conversation");
+
+    public static final Uri PARTICIPANTS_URI = Uri.parse(CONTENT_AUTHORITY + PARTICIPANTS_QUERY);
+
+    // Conversation images query
+    private static final String CONVERSATION_IMAGES_QUERY = "conversation_images";
+
+    public static final Uri CONVERSATION_IMAGES_URI = Uri.parse(CONTENT_AUTHORITY +
+            CONVERSATION_IMAGES_QUERY);
+
+    private static final String DRAFT_IMAGES_QUERY = "draft_images";
+
+    public static final Uri DRAFT_IMAGES_URI = Uri.parse(CONTENT_AUTHORITY +
+            DRAFT_IMAGES_QUERY);
+
+    /**
+     * Notifies that <i>all</i> data exposed by the provider needs to be refreshed.
+     * <p>
+     * <b>IMPORTANT!</b> You probably shouldn't be calling this. Prefer to notify more specific
+     * uri's instead. Currently only sync uses this, because sync can potentially update many
+     * different tables at once.
+     */
+    public static void notifyEverythingChanged() {
+        final Uri uri = Uri.parse(CONTENT_AUTHORITY);
+        final Context context = Factory.get().getApplicationContext();
+        final ContentResolver cr = context.getContentResolver();
+        cr.notifyChange(uri, null);
+
+        // Notify any conversations widgets the conversation list has changed.
+        BugleWidgetProvider.notifyConversationListChanged(context);
+
+        // Notify all conversation widgets to update.
+        WidgetConversationProvider.notifyMessagesChanged(context, null /*conversationId*/);
+    }
+
+    /**
+     * Build a participant uri from the conversation id.
+     */
+    public static Uri buildConversationParticipantsUri(final String conversationId) {
+        final Uri.Builder builder = CONVERSATION_PARTICIPANTS_URI.buildUpon();
+        builder.appendPath(conversationId);
+        return builder.build();
+    }
+
+    public static void notifyParticipantsChanged(final String conversationId) {
+        final Uri uri = buildConversationParticipantsUri(conversationId);
+        final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
+        cr.notifyChange(uri, null);
+    }
+
+    public static void notifyAllMessagesChanged() {
+        final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
+        cr.notifyChange(CONVERSATION_MESSAGES_URI, null);
+    }
+
+    public static void notifyAllParticipantsChanged() {
+        final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
+        cr.notifyChange(CONVERSATION_PARTICIPANTS_URI, null);
+    }
+
+    // Default value for unknown dimension of image
+    public static final int UNSPECIFIED_SIZE = -1;
+
+    // Internal
+    private static final int CONVERSATIONS_QUERY_CODE = 10;
+
+    private static final int CONVERSATION_QUERY_CODE = 20;
+    private static final int CONVERSATION_MESSAGES_QUERY_CODE = 30;
+    private static final int CONVERSATION_PARTICIPANTS_QUERY_CODE = 40;
+    private static final int CONVERSATION_IMAGES_QUERY_CODE = 50;
+    private static final int DRAFT_IMAGES_QUERY_CODE = 60;
+    private static final int PARTICIPANTS_QUERY_CODE = 70;
+
+    // TODO: Move to a better structured URI namespace.
+    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    static {
+        sURIMatcher.addURI(AUTHORITY, CONVERSATIONS_QUERY, CONVERSATIONS_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, CONVERSATIONS_QUERY + "/*", CONVERSATION_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, MESSAGES_QUERY + "/conversation/*",
+                CONVERSATION_MESSAGES_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, PARTICIPANTS_QUERY + "/conversation/*",
+                CONVERSATION_PARTICIPANTS_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, PARTICIPANTS_QUERY, PARTICIPANTS_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, CONVERSATION_IMAGES_QUERY + "/*",
+                CONVERSATION_IMAGES_QUERY_CODE);
+        sURIMatcher.addURI(AUTHORITY, DRAFT_IMAGES_QUERY + "/*",
+                DRAFT_IMAGES_QUERY_CODE);
+    }
+
+    /**
+     * Build a messages uri from the conversation id.
+     */
+    public static Uri buildConversationMessagesUri(final String conversationId) {
+        final Uri.Builder builder = CONVERSATION_MESSAGES_URI.buildUpon();
+        builder.appendPath(conversationId);
+        return builder.build();
+    }
+
+    public static void notifyMessagesChanged(final String conversationId) {
+        final Uri uri = buildConversationMessagesUri(conversationId);
+        final Context context = Factory.get().getApplicationContext();
+        final ContentResolver cr = context.getContentResolver();
+        cr.notifyChange(uri, null);
+        notifyConversationListChanged();
+
+        // Notify the widget the messages changed
+        WidgetConversationProvider.notifyMessagesChanged(context, conversationId);
+    }
+
+    /**
+     * Build a conversation metadata uri from a conversation id.
+     */
+    public static Uri buildConversationMetadataUri(final String conversationId) {
+        final Uri.Builder builder = CONVERSATIONS_URI.buildUpon();
+        builder.appendPath(conversationId);
+        return builder.build();
+    }
+
+    public static void notifyConversationMetadataChanged(final String conversationId) {
+        final Uri uri = buildConversationMetadataUri(conversationId);
+        final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
+        cr.notifyChange(uri, null);
+        notifyConversationListChanged();
+    }
+
+    public static void notifyPartsChanged() {
+        final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
+        cr.notifyChange(PARTS_URI, null);
+    }
+
+    public static void notifyConversationListChanged() {
+        final Context context = Factory.get().getApplicationContext();
+        final ContentResolver cr = context.getContentResolver();
+        cr.notifyChange(CONVERSATIONS_URI, null);
+
+        // Notify the widget the conversation list changed
+        BugleWidgetProvider.notifyConversationListChanged(context);
+    }
+
+    /**
+     * Build a conversation images uri from a conversation id.
+     */
+    public static Uri buildConversationImagesUri(final String conversationId) {
+        final Uri.Builder builder = CONVERSATION_IMAGES_URI.buildUpon();
+        builder.appendPath(conversationId);
+        return builder.build();
+    }
+
+    /**
+     * Build a draft images uri from a conversation id.
+     */
+    public static Uri buildDraftImagesUri(final String conversationId) {
+        final Uri.Builder builder = DRAFT_IMAGES_URI.buildUpon();
+        builder.appendPath(conversationId);
+        return builder.build();
+    }
+
+    private DatabaseHelper mDatabaseHelper;
+    private DatabaseWrapper mDatabaseWrapper;
+
+    public MessagingContentProvider() {
+        super();
+    }
+
+    @VisibleForTesting
+    public void setDatabaseForTest(final DatabaseWrapper db) {
+        Assert.isTrue(BugleApplication.isRunningTests());
+        mDatabaseWrapper = db;
+    }
+
+    private DatabaseWrapper getDatabaseWrapper() {
+        if (mDatabaseWrapper == null) {
+            mDatabaseWrapper = mDatabaseHelper.getDatabase();
+        }
+        return mDatabaseWrapper;
+    }
+
+    @Override
+    public Cursor query(final Uri uri, final String[] projection, String selection,
+            final String[] selectionArgs, String sortOrder) {
+
+        // Processes other than self are allowed to temporarily access the media
+        // scratch space; we grant uri read access on a case-by-case basis. Dialer app and
+        // contacts app would doQuery() on the vCard uri before trying to open the inputStream.
+        // There's nothing that we need to return for this uri so just No-Op.
+        //if (isMediaScratchSpaceUri(uri)) {
+        //    return null;
+        //}
+
+        final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
+
+        String[] queryArgs = selectionArgs;
+        final int match = sURIMatcher.match(uri);
+        String groupBy = null;
+        String limit = null;
+        switch (match) {
+            case CONVERSATIONS_QUERY_CODE:
+                queryBuilder.setTables(ConversationListItemData.getConversationListView());
+                // Hide empty conversations (ones with 0 sort_timestamp)
+                queryBuilder.appendWhere(ConversationColumns.SORT_TIMESTAMP + " > 0 ");
+                break;
+            case CONVERSATION_QUERY_CODE:
+                queryBuilder.setTables(ConversationListItemData.getConversationListView());
+                if (uri.getPathSegments().size() == 2) {
+                    queryBuilder.appendWhere(ConversationColumns._ID + "=?");
+                    // Get the conversation id from the uri
+                    queryArgs = prependArgs(queryArgs, uri.getPathSegments().get(1));
+                } else {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+                break;
+            case CONVERSATION_PARTICIPANTS_QUERY_CODE:
+                queryBuilder.setTables(DatabaseHelper.PARTICIPANTS_TABLE);
+                if (uri.getPathSegments().size() == 3 &&
+                        TextUtils.equals(uri.getPathSegments().get(1), "conversation")) {
+                    queryBuilder.appendWhere(ParticipantColumns._ID + " IN ( " + "SELECT "
+                            + ConversationParticipantsColumns.PARTICIPANT_ID + " AS "
+                            + ParticipantColumns._ID
+                            + " FROM " + DatabaseHelper.CONVERSATION_PARTICIPANTS_TABLE
+                            + " WHERE " + ConversationParticipantsColumns.CONVERSATION_ID
+                            + " =? UNION SELECT " + ParticipantColumns._ID + " FROM "
+                            + DatabaseHelper.PARTICIPANTS_TABLE + " WHERE "
+                            + ParticipantColumns.SUB_ID + " != "
+                            + ParticipantData.OTHER_THAN_SELF_SUB_ID + " )");
+                    // Get the conversation id from the uri
+                    queryArgs = prependArgs(queryArgs, uri.getPathSegments().get(2));
+                } else {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+                break;
+            case PARTICIPANTS_QUERY_CODE:
+                queryBuilder.setTables(DatabaseHelper.PARTICIPANTS_TABLE);
+                if (uri.getPathSegments().size() != 1) {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+                break;
+            case CONVERSATION_MESSAGES_QUERY_CODE:
+                if (uri.getPathSegments().size() == 3 &&
+                    TextUtils.equals(uri.getPathSegments().get(1), "conversation")) {
+                    // Get the conversation id from the uri
+                    final String conversationId = uri.getPathSegments().get(2);
+
+                    // We need to handle this query differently, instead of falling through to the
+                    // generic query call at the bottom. For performance reasons, the conversation
+                    // messages query is executed as a raw query. It is invalid to specify
+                    // selection/sorting for this query.
+
+                    if (selection == null && selectionArgs == null && sortOrder == null) {
+                        return queryConversationMessages(conversationId, uri);
+                    } else {
+                        throw new IllegalArgumentException(
+                                "Cannot set selection or sort order with this query");
+                    }
+                } else {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+            case CONVERSATION_IMAGES_QUERY_CODE:
+                queryBuilder.setTables(ConversationImagePartsView.getViewName());
+                if (uri.getPathSegments().size() == 2) {
+                    // Exclude draft.
+                    queryBuilder.appendWhere(
+                            ConversationImagePartsView.Columns.CONVERSATION_ID + " =? AND " +
+                                    ConversationImagePartsView.Columns.STATUS + "<>" +
+                                    MessageData.BUGLE_STATUS_OUTGOING_DRAFT);
+                    // Get the conversation id from the uri
+                    queryArgs = prependArgs(queryArgs, uri.getPathSegments().get(1));
+                } else {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+                break;
+            case DRAFT_IMAGES_QUERY_CODE:
+                queryBuilder.setTables(ConversationImagePartsView.getViewName());
+                if (uri.getPathSegments().size() == 2) {
+                    // Draft only.
+                    queryBuilder.appendWhere(
+                            ConversationImagePartsView.Columns.CONVERSATION_ID + " =? AND " +
+                                    ConversationImagePartsView.Columns.STATUS + "=" +
+                                    MessageData.BUGLE_STATUS_OUTGOING_DRAFT);
+                    // Get the conversation id from the uri
+                    queryArgs = prependArgs(queryArgs, uri.getPathSegments().get(1));
+                } else {
+                    throw new IllegalArgumentException("Malformed URI " + uri);
+                }
+                break;
+            default: {
+                throw new IllegalArgumentException("Unknown URI " + uri);
+            }
+        }
+
+        final Cursor cursor = getDatabaseWrapper().query(queryBuilder, projection, selection,
+                queryArgs, groupBy, null, sortOrder, limit);
+        cursor.setNotificationUri(getContext().getContentResolver(), uri);
+        return cursor;
+    }
+
+    private Cursor queryConversationMessages(final String conversationId, final Uri notifyUri) {
+        final String[] queryArgs = { conversationId };
+        final Cursor cursor = getDatabaseWrapper().rawQuery(
+                ConversationMessageData.getConversationMessagesQuerySql(), queryArgs);
+        cursor.setNotificationUri(getContext().getContentResolver(), notifyUri);
+        return cursor;
+    }
+
+    @Override
+    public String getType(final Uri uri) {
+        final StringBuilder sb = new
+                StringBuilder("vnd.android.cursor.dir/vnd.android.messaging.");
+
+        switch (sURIMatcher.match(uri)) {
+            case CONVERSATIONS_QUERY_CODE: {
+                sb.append(CONVERSATIONS_QUERY);
+                break;
+            }
+            default: {
+                throw new IllegalArgumentException("Unknown URI: " + uri);
+            }
+        }
+        return sb.toString();
+    }
+
+    protected DatabaseHelper getDatabase() {
+        return DatabaseHelper.getInstance(getContext());
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(final Uri uri, final String fileMode)
+            throws FileNotFoundException {
+        throw new IllegalArgumentException("openFile not supported: " + uri);
+    }
+
+    @Override
+    public Uri insert(final Uri uri, final ContentValues values) {
+        throw new IllegalStateException("Insert not supported " + uri);
+    }
+
+    @Override
+    public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
+        throw new IllegalArgumentException("Delete not supported: " + uri);
+    }
+
+    @Override
+    public int update(final Uri uri, final ContentValues values, final String selection,
+            final String[] selectionArgs) {
+        throw new IllegalArgumentException("Update not supported: " + uri);
+    }
+
+    /**
+     * Prepends new arguments to the existing argument list.
+     *
+     * @param oldArgList The current list of arguments. May be {@code null}
+     * @param args The new arguments to prepend
+     * @return A new argument list with the given arguments prepended
+     */
+    private String[] prependArgs(final String[] oldArgList, final String... args) {
+        if (args == null || args.length == 0) {
+            return oldArgList;
+        }
+        final int oldArgCount = (oldArgList == null ? 0 : oldArgList.length);
+        final int newArgCount = args.length;
+
+        final String[] newArgs = new String[oldArgCount + newArgCount];
+        System.arraycopy(args, 0, newArgs, 0, newArgCount);
+        if (oldArgCount > 0) {
+            System.arraycopy(oldArgList, 0, newArgs, newArgCount, oldArgCount);
+        }
+        return newArgs;
+    }
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
+        // First dump out the default SMS app package name
+        String defaultSmsApp = PhoneUtils.getDefault().getDefaultSmsApp();
+        if (TextUtils.isEmpty(defaultSmsApp)) {
+            if (OsUtil.isAtLeastKLP()) {
+                defaultSmsApp = "None";
+            } else {
+                defaultSmsApp = "None (pre-Kitkat)";
+            }
+        }
+        writer.println("Default SMS app: " + defaultSmsApp);
+        // Now dump logs
+        LogUtil.dump(writer);
+    }
+
+    @Override
+    public boolean onCreate() {
+        // This is going to wind up calling into createDatabase() below.
+        mDatabaseHelper = (DatabaseHelper) getDatabase();
+        // We cannot initialize mDatabaseWrapper yet as the Factory may not be initialized
+        return true;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/MmsFileProvider.java b/src/com/android/messaging/datamodel/MmsFileProvider.java
new file mode 100644
index 0000000..eb49802
--- /dev/null
+++ b/src/com/android/messaging/datamodel/MmsFileProvider.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A very simple content provider that can serve mms files from our cache directory.
+ */
+public class MmsFileProvider extends FileProvider {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    @VisibleForTesting
+    static final String AUTHORITY = "com.android.messaging.datamodel.MmsFileProvider";
+    private static final String RAW_MMS_DIR = "rawmms";
+
+    /**
+     * Returns a uri that can be used to access a raw mms file.
+     *
+     * @return the URI for an raw mms file
+     */
+    public static Uri buildRawMmsUri() {
+        final Uri uri = FileProvider.buildFileUri(AUTHORITY, null);
+        final File file = getFile(uri.getPath());
+        if (!ensureFileExists(file)) {
+            LogUtil.e(TAG, "Failed to create temp file " + file.getAbsolutePath());
+        }
+        return uri;
+    }
+
+    @Override
+    File getFile(final String path, final String extension) {
+        return getFile(path);
+    }
+
+    public static File getFile(final Uri uri) {
+        return getFile(uri.getPath());
+    }
+
+    private static File getFile(final String path) {
+        final Context context = Factory.get().getApplicationContext();
+        final File filePath = new File(getDirectory(context), path + ".dat");
+
+        try {
+            if (!filePath.getCanonicalPath()
+                    .startsWith(getDirectory(context).getCanonicalPath())) {
+                LogUtil.e(TAG, "getFile: path "
+                        + filePath.getCanonicalPath()
+                        + " does not start with "
+                        + getDirectory(context).getCanonicalPath());
+                return null;
+            }
+        } catch (IOException e) {
+            LogUtil.e(TAG, "getFile: getCanonicalPath failed ", e);
+            return null;
+        }
+        return filePath;
+    }
+
+    private static File getDirectory(final Context context) {
+        return new File(context.getCacheDir(), RAW_MMS_DIR);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/NoConfirmationSmsSendService.java b/src/com/android/messaging/datamodel/NoConfirmationSmsSendService.java
new file mode 100644
index 0000000..bea4961
--- /dev/null
+++ b/src/com/android/messaging/datamodel/NoConfirmationSmsSendService.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.core.app.RemoteInput;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.action.InsertNewMessageAction;
+import com.android.messaging.datamodel.action.UpdateMessageNotificationAction;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.conversationlist.ConversationListActivity;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * Respond to a special intent and send an SMS message without the user's intervention, unless
+ * the intent extra "showUI" is true.
+ */
+public class NoConfirmationSmsSendService extends IntentService {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final String EXTRA_SUBSCRIPTION = "subscription";
+    public static final String EXTRA_SELF_ID = "self_id";
+
+    public NoConfirmationSmsSendService() {
+        // Class name will be the thread name.
+        super(NoConfirmationSmsSendService.class.getName());
+
+        // Intent should be redelivered if the process gets killed before completing the job.
+        setIntentRedelivery(true);
+    }
+
+    @Override
+    protected void onHandleIntent(final Intent intent) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "NoConfirmationSmsSendService onHandleIntent");
+        }
+
+        final String action = intent.getAction();
+        if (!TelephonyManager.ACTION_RESPOND_VIA_MESSAGE.equals(action)) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "NoConfirmationSmsSendService onHandleIntent wrong action: " +
+                    action);
+            }
+            return;
+        }
+        final Bundle extras = intent.getExtras();
+        if (extras == null) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Called to send SMS but no extras");
+            }
+            return;
+        }
+
+        // Get all possible extras from intent
+        final String conversationId =
+                intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+        final String selfId = intent.getStringExtra(EXTRA_SELF_ID);
+        final boolean requiresMms = intent.getBooleanExtra(UIIntents.UI_INTENT_EXTRA_REQUIRES_MMS,
+                false);
+        final String message = getText(intent, Intent.EXTRA_TEXT);
+        final String subject = getText(intent, Intent.EXTRA_SUBJECT);
+        final int subId = extras.getInt(EXTRA_SUBSCRIPTION, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        // Get a comma-separated list of recipients
+        final String recipients = UriUtil.parseRecipientsFromSmsMmsUri(intent.getData());
+
+        if (TextUtils.isEmpty(recipients) && TextUtils.isEmpty(conversationId)) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Both conversationId and recipient(s) cannot be empty");
+            }
+            return;
+        }
+
+        if (extras.getBoolean("showUI", false)) {
+            startActivity(new Intent(this, ConversationListActivity.class));
+        } else {
+            if (TextUtils.isEmpty(message)) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "Message cannot be empty");
+                }
+                return;
+            }
+
+            // TODO: it's possible that a long message would require sending it via mms,
+            // but we're not testing for that here and we're sending the message as an sms.
+
+            if (TextUtils.isEmpty(conversationId)) {
+                InsertNewMessageAction.insertNewMessage(subId, recipients, message, subject);
+            } else {
+                MessageData messageData = null;
+                if (requiresMms) {
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "Auto-sending MMS message in conversation: " +
+                                conversationId);
+                    }
+                    messageData = MessageData.createDraftMmsMessage(conversationId, selfId, message,
+                            subject);
+                } else {
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "Auto-sending SMS message in conversation: " +
+                                conversationId);
+                    }
+                    messageData = MessageData.createDraftSmsMessage(conversationId, selfId,
+                            message);
+                }
+                InsertNewMessageAction.insertNewMessage(messageData);
+            }
+            UpdateMessageNotificationAction.updateMessageNotification();
+        }
+    }
+
+    private String getText(final Intent intent, final String textType) {
+        final String message = intent.getStringExtra(textType);
+        if (message == null) {
+            final Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+            if (remoteInput != null) {
+                final CharSequence extra = remoteInput.getCharSequence(textType);
+                if (extra != null) {
+                    return extra.toString();
+                }
+            }
+        }
+        return message;
+    }
+
+}
diff --git a/src/com/android/messaging/datamodel/NotificationState.java b/src/com/android/messaging/datamodel/NotificationState.java
new file mode 100644
index 0000000..e19f70c
--- /dev/null
+++ b/src/com/android/messaging/datamodel/NotificationState.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.app.PendingIntent;
+import android.net.Uri;
+import androidx.core.app.NotificationCompat;
+
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.ConversationIdSet;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * Base class for representing notifications. The main reason for this class is that in order to
+ * show pictures or avatars they might need to be loaded in the background. This class and
+ * subclasses can do the main work to get the notification ready and then wait until any images
+ * that are needed are ready before posting.
+ *
+ * The creation of a notification is split into two parts. The NotificationState ctor should
+ * setup the basic information including the mContentIntent. A Notification Builder is created in
+ * RealTimeChatNotifications and passed to the build() method of each notification where the
+ * Notification is fully specified.
+ *
+ * TODO: There is still some duplication and inconsistency in the utility functions and
+ * placement of different building blocks across notification types (e.g. summary text for accounts)
+ */
+public abstract class NotificationState {
+    private static final int CONTENT_INTENT_REQUEST_CODE_OFFSET = 0;
+    private static final int CLEAR_INTENT_REQUEST_CODE_OFFSET = 1;
+    private static final int NUM_REQUEST_CODES_NEEDED = 2;
+
+    public interface FailedMessageQuery {
+        static final String FAILED_MESSAGES_WHERE_CLAUSE =
+                "((" + MessageColumns.STATUS + " = " +
+                MessageData.BUGLE_STATUS_OUTGOING_FAILED + " OR " +
+                MessageColumns.STATUS + " = " +
+                MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED + ") AND " +
+                DatabaseHelper.MessageColumns.SEEN + " = 0)";
+
+        static final String FAILED_ORDER_BY = DatabaseHelper.MessageColumns.CONVERSATION_ID + ", " +
+                DatabaseHelper.MessageColumns.SENT_TIMESTAMP + " asc";
+    }
+
+    public final ConversationIdSet mConversationIds;
+    public final HashSet<String> mPeople;
+
+    public NotificationCompat.Style mNotificationStyle;
+    public NotificationCompat.Builder mNotificationBuilder;
+    public boolean mCanceled;
+    public int mType;
+    public int mBaseRequestCode;
+    public ArrayList<Uri> mParticipantAvatarsUris = null;
+    public ArrayList<Uri> mParticipantContactUris = null;
+
+    NotificationState(final ConversationIdSet conversationIds) {
+        mConversationIds = conversationIds;
+        mPeople = new HashSet<String>();
+    }
+
+    /**
+     * The intent to be triggered when the notification is dismissed.
+     */
+    public abstract PendingIntent getClearIntent();
+
+    protected Uri getAttachmentUri() {
+        return null;
+    }
+
+    // Returns the mime type of the attachment (See ContentType class for definitions)
+    protected String getAttachmentType() {
+        return null;
+    }
+
+    /**
+     * Build the notification using the given builder.
+     * @param builder
+     * @return The style of the notification.
+     */
+    protected abstract NotificationCompat.Style build(NotificationCompat.Builder builder);
+
+    protected void setAvatarUrlsForConversation(final String conversationId) {
+    }
+
+    protected void setPeopleForConversation(final String conversationId) {
+    }
+
+    /**
+     * Reserves request codes for this notification type. By default 2 codes are reserved, one for
+     * the main intent and another for the cancel intent. Override this function to reserve more.
+     */
+    public int getNumRequestCodesNeeded() {
+        return NUM_REQUEST_CODES_NEEDED;
+    }
+
+    public int getContentIntentRequestCode() {
+        return mBaseRequestCode + CONTENT_INTENT_REQUEST_CODE_OFFSET;
+    }
+
+    public int getClearIntentRequestCode() {
+        return mBaseRequestCode + CLEAR_INTENT_REQUEST_CODE_OFFSET;
+    }
+
+    /**
+     * Gets the appropriate icon needed for notifications.
+     */
+    public abstract int getIcon();
+
+    /**
+     * @return the type of notification that should be used from {@link RealTimeChatNotifications}
+     * so that the proper ringtone and vibrate settings can be used.
+     */
+    public int getLatestMessageNotificationType() {
+        return BugleNotifications.LOCAL_SMS_NOTIFICATION;
+    }
+
+    /**
+     * @return the notification priority level for this notification.
+     */
+    public abstract int getPriority();
+
+    /** @return custom ringtone URI or null if not set */
+    public String getRingtoneUri() {
+        return null;
+    }
+
+    public boolean getNotificationVibrate() {
+        return false;
+    }
+
+    public long getLatestReceivedTimestamp() {
+        return Long.MIN_VALUE;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/ParticipantRefresh.java b/src/com/android/messaging/datamodel/ParticipantRefresh.java
new file mode 100644
index 0000000..55d439b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/ParticipantRefresh.java
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentValues;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.graphics.Color;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import androidx.collection.ArrayMap;
+import android.telephony.SubscriptionInfo;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Utility class for refreshing participant information based on matching contact. This updates
+ *     1. name, photo_uri, matching contact_id of participants.
+ *     2. generated_name of conversations.
+ *
+ * There are two kinds of participant refreshes,
+ *     1. Full refresh, this is triggered at application start or activity resumes after contact
+ *        change is detected.
+ *     2. Partial refresh, this is triggered when a participant is added to a conversation. This
+ *        normally happens during SMS sync.
+ */
+@VisibleForTesting
+public class ParticipantRefresh {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    /**
+     * Refresh all participants including ones that were resolved before.
+     */
+    public static final int REFRESH_MODE_FULL = 0;
+
+    /**
+     * Refresh all unresolved participants.
+     */
+    public static final int REFRESH_MODE_INCREMENTAL = 1;
+
+    /**
+     * Force refresh all self participants.
+     */
+    public static final int REFRESH_MODE_SELF_ONLY = 2;
+
+    public static class ConversationParticipantsQuery {
+        public static final String[] PROJECTION = new String[] {
+            ConversationParticipantsColumns._ID,
+            ConversationParticipantsColumns.CONVERSATION_ID,
+            ConversationParticipantsColumns.PARTICIPANT_ID
+        };
+
+        public static final int INDEX_ID                        = 0;
+        public static final int INDEX_CONVERSATION_ID           = 1;
+        public static final int INDEX_PARTICIPANT_ID            = 2;
+    }
+
+    // Track whether observer is initialized or not.
+    private static volatile boolean sObserverInitialized = false;
+    private static final Object sLock = new Object();
+    private static final AtomicBoolean sFullRefreshScheduled = new AtomicBoolean(false);
+    private static final Runnable sFullRefreshRunnable = new Runnable() {
+        @Override
+        public void run() {
+            final boolean oldScheduled = sFullRefreshScheduled.getAndSet(false);
+            Assert.isTrue(oldScheduled);
+            refreshParticipants(REFRESH_MODE_FULL);
+        }
+    };
+    private static final Runnable sSelfOnlyRefreshRunnable = new Runnable() {
+        @Override
+        public void run() {
+            refreshParticipants(REFRESH_MODE_SELF_ONLY);
+        }
+    };
+
+    /**
+     * A customized content resolver to track contact changes.
+     */
+    public static class ContactContentObserver extends ContentObserver {
+        private volatile boolean mContactChanged = false;
+
+        public ContactContentObserver() {
+            super(null);
+        }
+
+        @Override
+        public void onChange(final boolean selfChange) {
+            super.onChange(selfChange);
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Contacts changed");
+            }
+            mContactChanged = true;
+        }
+
+        public boolean getContactChanged() {
+            return mContactChanged;
+        }
+
+        public void resetContactChanged() {
+            mContactChanged = false;
+        }
+
+        public void initialize() {
+            // TODO: Handle enterprise contacts post M once contacts provider supports it
+            Factory.get().getApplicationContext().getContentResolver().registerContentObserver(
+                    Phone.CONTENT_URI, true, this);
+            mContactChanged = true; // Force a full refresh on initialization.
+        }
+    }
+
+    /**
+     * Refresh participants only if needed, i.e., application start or contact changed.
+     */
+    public static void refreshParticipantsIfNeeded() {
+        if (ParticipantRefresh.getNeedFullRefresh() &&
+                sFullRefreshScheduled.compareAndSet(false, true)) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Started full participant refresh");
+            }
+            SafeAsyncTask.executeOnThreadPool(sFullRefreshRunnable);
+        } else if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "Skipped full participant refresh");
+        }
+    }
+
+    /**
+     * Refresh self participants on subscription or settings change.
+     */
+    public static void refreshSelfParticipants() {
+        SafeAsyncTask.executeOnThreadPool(sSelfOnlyRefreshRunnable);
+    }
+
+    private static boolean getNeedFullRefresh() {
+        final ContactContentObserver observer = Factory.get().getContactContentObserver();
+        if (observer == null) {
+            // If there is no observer (for unittest cases), we don't need to refresh participants.
+            return false;
+        }
+
+        if (!sObserverInitialized) {
+            synchronized (sLock) {
+                if (!sObserverInitialized) {
+                    observer.initialize();
+                    sObserverInitialized = true;
+                }
+            }
+        }
+
+        return observer.getContactChanged();
+    }
+
+    private static void resetNeedFullRefresh() {
+        final ContactContentObserver observer = Factory.get().getContactContentObserver();
+        if (observer != null) {
+            observer.resetContactChanged();
+        }
+    }
+
+    /**
+     * This class is totally static. Make constructor to be private so that an instance
+     * of this class would not be created by by mistake.
+     */
+    private ParticipantRefresh() {
+    }
+
+    /**
+     * Refresh participants in Bugle.
+     *
+     * @param refreshMode the refresh mode desired. See {@link #REFRESH_MODE_FULL},
+     *        {@link #REFRESH_MODE_INCREMENTAL}, and {@link #REFRESH_MODE_SELF_ONLY}
+     */
+     @VisibleForTesting
+     static void refreshParticipants(final int refreshMode) {
+        Assert.inRange(refreshMode, REFRESH_MODE_FULL, REFRESH_MODE_SELF_ONLY);
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            switch (refreshMode) {
+                case REFRESH_MODE_FULL:
+                    LogUtil.v(TAG, "Start full participant refresh");
+                    break;
+                case REFRESH_MODE_INCREMENTAL:
+                    LogUtil.v(TAG, "Start partial participant refresh");
+                    break;
+                case REFRESH_MODE_SELF_ONLY:
+                    LogUtil.v(TAG, "Start self participant refresh");
+                    break;
+            }
+        }
+
+        if (!ContactUtil.hasReadContactsPermission() || !OsUtil.hasPhonePermission()) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Skipping participant referesh because of permissions");
+            }
+            return;
+        }
+
+        if (refreshMode == REFRESH_MODE_FULL) {
+            // resetNeedFullRefresh right away so that we will skip duplicated full refresh
+            // requests.
+            resetNeedFullRefresh();
+        }
+
+        if (refreshMode == REFRESH_MODE_FULL || refreshMode == REFRESH_MODE_SELF_ONLY) {
+            refreshSelfParticipantList();
+        }
+
+        final ArrayList<String> changedParticipants = new ArrayList<String>();
+
+        String selection = null;
+        String[] selectionArgs = null;
+
+        if (refreshMode == REFRESH_MODE_INCREMENTAL) {
+            // In case of incremental refresh, filter out participants that are already resolved.
+            selection = ParticipantColumns.CONTACT_ID + "=?";
+            selectionArgs = new String[] {
+                    String.valueOf(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED) };
+        } else if (refreshMode == REFRESH_MODE_SELF_ONLY) {
+            // In case of self-only refresh, filter out non-self participants.
+            selection = SELF_PARTICIPANTS_CLAUSE;
+            selectionArgs = null;
+        }
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        Cursor cursor = null;
+        boolean selfUpdated = false;
+        try {
+            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null);
+
+            if (cursor != null) {
+                while (cursor.moveToNext()) {
+                    try {
+                        final ParticipantData participantData =
+                                ParticipantData.getFromCursor(cursor);
+                        if (refreshParticipant(db, participantData)) {
+                            if (participantData.isSelf()) {
+                                selfUpdated = true;
+                            }
+                            updateParticipant(db, participantData);
+                            final String id = participantData.getId();
+                            changedParticipants.add(id);
+                        }
+                    } catch (final Exception exception) {
+                        // Failure to update one participant shouldn't cancel the entire refresh.
+                        // Log the failure so we know what's going on and resume the loop.
+                        LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "ParticipantRefresh: Failed to " +
+                                "update participant", exception);
+                    }
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "Number of participants refreshed:" + changedParticipants.size());
+        }
+
+        // Refresh conversations for participants that are changed.
+        if (changedParticipants.size() > 0) {
+            BugleDatabaseOperations.refreshConversationsForParticipants(changedParticipants);
+        }
+        if (selfUpdated) {
+            // Boom
+            MessagingContentProvider.notifyAllParticipantsChanged();
+            MessagingContentProvider.notifyAllMessagesChanged();
+        }
+    }
+
+    private static final String SELF_PARTICIPANTS_CLAUSE = ParticipantColumns.SUB_ID
+            + " NOT IN ( "
+            + ParticipantData.OTHER_THAN_SELF_SUB_ID
+            + " )";
+
+    private static final Set<Integer> getExistingSubIds() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final HashSet<Integer> existingSubIds = new HashSet<Integer>();
+
+        Cursor cursor = null;
+        try {
+            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantsQuery.PROJECTION,
+                    SELF_PARTICIPANTS_CLAUSE, null, null, null, null);
+
+            if (cursor != null) {
+                while (cursor.moveToNext()) {
+                    final int subId = cursor.getInt(ParticipantsQuery.INDEX_SUB_ID);
+                    existingSubIds.add(subId);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return existingSubIds;
+    }
+
+    private static final String UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL =
+            "UPDATE " + DatabaseHelper.PARTICIPANTS_TABLE + " SET "
+            +  ParticipantColumns.SIM_SLOT_ID + " = %d, "
+            +  ParticipantColumns.SUBSCRIPTION_COLOR + " = %d, "
+            +  ParticipantColumns.SUBSCRIPTION_NAME + " = %s "
+            + " WHERE %s";
+
+    static String getUpdateSelfParticipantSubscriptionInfoSql(final int slotId,
+            final int subscriptionColor, final String subscriptionName, final String where) {
+        return String.format((Locale) null /* construct SQL string without localization */,
+                UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL,
+                slotId, subscriptionColor, subscriptionName, where);
+    }
+
+    /**
+     * Ensure that there is a self participant corresponding to every active SIM. Also, ensure
+     * that any other older SIM self participants are marked as inactive.
+     */
+    private static void refreshSelfParticipantList() {
+        if (!OsUtil.isAtLeastL_MR1()) {
+            return;
+        }
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final List<SubscriptionInfo> subInfoRecords =
+                PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList();
+        final ArrayMap<Integer, SubscriptionInfo> activeSubscriptionIdToRecordMap =
+                new ArrayMap<Integer, SubscriptionInfo>();
+        db.beginTransaction();
+        final Set<Integer> existingSubIds = getExistingSubIds();
+
+        try {
+            if (subInfoRecords != null) {
+                for (final SubscriptionInfo subInfoRecord : subInfoRecords) {
+                    final int subId = subInfoRecord.getSubscriptionId();
+                    // If its a new subscription, add it to the database.
+                    if (!existingSubIds.contains(subId)) {
+                        db.execSQL(DatabaseHelper.getCreateSelfParticipantSql(subId));
+                        // Add it to the local set to guard against duplicated entries returned
+                        // by subscription manager.
+                        existingSubIds.add(subId);
+                    }
+                    activeSubscriptionIdToRecordMap.put(subId, subInfoRecord);
+
+                    if (subId == PhoneUtils.getDefault().getDefaultSmsSubscriptionId()) {
+                        // This is the system default subscription, so update the default self.
+                        activeSubscriptionIdToRecordMap.put(ParticipantData.DEFAULT_SELF_SUB_ID,
+                                subInfoRecord);
+                    }
+                }
+            }
+
+            // For subscriptions already in the database, refresh ParticipantColumns.SIM_SLOT_ID.
+            for (final Integer subId : activeSubscriptionIdToRecordMap.keySet()) {
+                final SubscriptionInfo record = activeSubscriptionIdToRecordMap.get(subId);
+                final String displayName =
+                        DatabaseUtils.sqlEscapeString(record.getDisplayName().toString());
+                db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql(record.getSimSlotIndex(),
+                        record.getIconTint(), displayName,
+                        ParticipantColumns.SUB_ID + " = " + subId));
+            }
+            db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql(
+                    ParticipantData.INVALID_SLOT_ID, Color.TRANSPARENT, "''",
+                    ParticipantColumns.SUB_ID + " NOT IN (" +
+                    Joiner.on(", ").join(activeSubscriptionIdToRecordMap.keySet()) + ")"));
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        // Fix up conversation self ids by reverting to default self for conversations whose self
+        // ids are no longer active.
+        refreshConversationSelfIds();
+    }
+
+    /**
+     * Refresh one participant.
+     * @return true if the ParticipantData was changed
+     */
+    public static boolean refreshParticipant(final DatabaseWrapper db,
+            final ParticipantData participantData) {
+        boolean updated = false;
+
+        if (participantData.isSelf()) {
+            final int selfChange = refreshFromSelfProfile(db, participantData);
+
+            if (selfChange == SELF_PROFILE_EXISTS) {
+                // If a self-profile exists, it takes precedence over Contacts data. So we are done.
+                return true;
+            }
+
+            updated = (selfChange == SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED);
+
+            // Fall-through and try to update based on Contacts data
+        }
+
+        updated |= refreshFromContacts(db, participantData);
+        return updated;
+    }
+
+    private static final int SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED = 1;
+    private static final int SELF_PROFILE_EXISTS = 2;
+
+    private static int refreshFromSelfProfile(final DatabaseWrapper db,
+            final ParticipantData participantData) {
+        int changed = 0;
+        // Refresh the phone number based on information from telephony
+        if (participantData.updatePhoneNumberForSelfIfChanged()) {
+            changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED;
+        }
+
+        if (OsUtil.isAtLeastL_MR1()) {
+            // Refresh the subscription info based on information from SubscriptionManager.
+            final SubscriptionInfo subscriptionInfo =
+                    PhoneUtils.get(participantData.getSubId()).toLMr1().getActiveSubscriptionInfo();
+            if (participantData.updateSubscriptionInfoForSelfIfChanged(subscriptionInfo)) {
+                changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED;
+            }
+        }
+
+        // For self participant, try getting name/avatar from self profile in CP2 first.
+        // TODO: in case of multi-sim, profile would not be able to be used for
+        // different numbers. Need to figure out that.
+        Cursor selfCursor = null;
+        try {
+            selfCursor = ContactUtil.getSelf(db.getContext()).performSynchronousQuery();
+            if (selfCursor != null && selfCursor.getCount() > 0) {
+                selfCursor.moveToNext();
+                final long selfContactId = selfCursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+                participantData.setContactId(selfContactId);
+                participantData.setFullName(selfCursor.getString(
+                        ContactUtil.INDEX_DISPLAY_NAME));
+                participantData.setFirstName(
+                        ContactUtil.lookupFirstName(db.getContext(), selfContactId));
+                participantData.setProfilePhotoUri(selfCursor.getString(
+                        ContactUtil.INDEX_PHOTO_URI));
+                participantData.setLookupKey(selfCursor.getString(
+                        ContactUtil.INDEX_SELF_QUERY_LOOKUP_KEY));
+                return SELF_PROFILE_EXISTS;
+            }
+        } catch (final Exception exception) {
+            // It's possible for contact query to fail and we don't want that to crash our app.
+            // However, we need to at least log the exception so we know something was wrong.
+            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " +
+                    "participant. exception=" + exception);
+        } finally {
+            if (selfCursor != null) {
+                selfCursor.close();
+            }
+        }
+        return changed;
+    }
+
+    private static boolean refreshFromContacts(final DatabaseWrapper db,
+            final ParticipantData participantData) {
+        final String normalizedDestination = participantData.getNormalizedDestination();
+        final long currentContactId = participantData.getContactId();
+        final String currentDisplayName = participantData.getFullName();
+        final String currentFirstName = participantData.getFirstName();
+        final String currentPhotoUri = participantData.getProfilePhotoUri();
+        final String currentContactDestination = participantData.getContactDestination();
+
+        Cursor matchingContactCursor = null;
+        long matchingContactId = -1;
+        String matchingDisplayName = null;
+        String matchingFirstName = null;
+        String matchingPhotoUri = null;
+        String matchingLookupKey = null;
+        String matchingDestination = null;
+        boolean updated = false;
+
+        if (TextUtils.isEmpty(normalizedDestination)) {
+            // The normalized destination can be "" for the self id if we can't get it from the
+            // SIM.  Some contact providers throw an IllegalArgumentException if you lookup "",
+            // so we early out.
+            return false;
+        }
+
+        try {
+            matchingContactCursor = ContactUtil.lookupDestination(db.getContext(),
+                    normalizedDestination).performSynchronousQuery();
+            if (matchingContactCursor == null || matchingContactCursor.getCount() == 0) {
+                // If there is no match, mark the participant as contact not found.
+                if (currentContactId != ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND) {
+                    participantData.setContactId(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND);
+                    participantData.setFullName(null);
+                    participantData.setFirstName(null);
+                    participantData.setProfilePhotoUri(null);
+                    participantData.setLookupKey(null);
+                    updated = true;
+                }
+                return updated;
+            }
+
+            while (matchingContactCursor.moveToNext()) {
+                final long contactId = matchingContactCursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+                // Pick either the first contact or the contact with same id as previous matched
+                // contact id.
+                if (matchingContactId == -1 || currentContactId == contactId) {
+                    matchingContactId = contactId;
+                    matchingDisplayName = matchingContactCursor.getString(
+                            ContactUtil.INDEX_DISPLAY_NAME);
+                    matchingFirstName = ContactUtil.lookupFirstName(db.getContext(), contactId);
+                    matchingPhotoUri = matchingContactCursor.getString(
+                            ContactUtil.INDEX_PHOTO_URI);
+                    matchingLookupKey = matchingContactCursor.getString(
+                            ContactUtil.INDEX_LOOKUP_KEY);
+                    matchingDestination = matchingContactCursor.getString(
+                            ContactUtil.INDEX_PHONE_EMAIL);
+                }
+
+                // There is no need to try other contacts if the current contactId was not filled...
+                if (currentContactId < 0
+                        // or we found the matching contact id
+                        || currentContactId == contactId) {
+                    break;
+                }
+            }
+        } catch (final Exception exception) {
+            // It's possible for contact query to fail and we don't want that to crash our app.
+            // However, we need to at least log the exception so we know something was wrong.
+            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " +
+                    "participant. exception=" + exception);
+            return false;
+        } finally {
+            if (matchingContactCursor != null) {
+                matchingContactCursor.close();
+            }
+        }
+
+        // Update participant only if something changed.
+        final boolean isContactIdChanged = (matchingContactId != currentContactId);
+        final boolean isDisplayNameChanged =
+                !TextUtils.equals(matchingDisplayName, currentDisplayName);
+        final boolean isFirstNameChanged = !TextUtils.equals(matchingFirstName, currentFirstName);
+        final boolean isPhotoUrlChanged = !TextUtils.equals(matchingPhotoUri, currentPhotoUri);
+        final boolean isDestinationChanged = !TextUtils.equals(matchingDestination,
+                currentContactDestination);
+
+        if (isContactIdChanged || isDisplayNameChanged || isFirstNameChanged || isPhotoUrlChanged
+                || isDestinationChanged) {
+            participantData.setContactId(matchingContactId);
+            participantData.setFullName(matchingDisplayName);
+            participantData.setFirstName(matchingFirstName);
+            participantData.setProfilePhotoUri(matchingPhotoUri);
+            participantData.setLookupKey(matchingLookupKey);
+            participantData.setContactDestination(matchingDestination);
+            if (isDestinationChanged) {
+                // Update the send destination to the new one entered by user in Contacts.
+                participantData.setSendDestination(matchingDestination);
+            }
+            updated = true;
+        }
+
+        return updated;
+    }
+
+    /**
+     * Update participant with matching contact's contactId, displayName and photoUri.
+     */
+    private static void updateParticipant(final DatabaseWrapper db,
+            final ParticipantData participantData) {
+        final ContentValues values = new ContentValues();
+        if (participantData.isSelf()) {
+            // Self participants can refresh their normalized phone numbers
+            values.put(ParticipantColumns.NORMALIZED_DESTINATION,
+                    participantData.getNormalizedDestination());
+            values.put(ParticipantColumns.DISPLAY_DESTINATION,
+                    participantData.getDisplayDestination());
+        }
+        values.put(ParticipantColumns.CONTACT_ID, participantData.getContactId());
+        values.put(ParticipantColumns.LOOKUP_KEY, participantData.getLookupKey());
+        values.put(ParticipantColumns.FULL_NAME, participantData.getFullName());
+        values.put(ParticipantColumns.FIRST_NAME, participantData.getFirstName());
+        values.put(ParticipantColumns.PROFILE_PHOTO_URI, participantData.getProfilePhotoUri());
+        values.put(ParticipantColumns.CONTACT_DESTINATION, participantData.getContactDestination());
+        values.put(ParticipantColumns.SEND_DESTINATION, participantData.getSendDestination());
+
+        db.beginTransaction();
+        try {
+            db.update(DatabaseHelper.PARTICIPANTS_TABLE, values, ParticipantColumns._ID + "=?",
+                    new String[] { participantData.getId() });
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    /**
+     * Get a list of inactive self ids in the participants table.
+     */
+    private static List<String> getInactiveSelfParticipantIds() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final List<String> inactiveSelf = new ArrayList<String>();
+
+        final String selection = ParticipantColumns.SIM_SLOT_ID + "=? AND " +
+                SELF_PARTICIPANTS_CLAUSE;
+        Cursor cursor = null;
+        try {
+            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    new String[] { ParticipantColumns._ID },
+                    selection, new String[] { String.valueOf(ParticipantData.INVALID_SLOT_ID) },
+                    null, null, null);
+
+            if (cursor != null) {
+                while (cursor.moveToNext()) {
+                    final String participantId = cursor.getString(0);
+                    inactiveSelf.add(participantId);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return inactiveSelf;
+    }
+
+    /**
+     * Gets a list of conversations with the given self ids.
+     */
+    private static List<String> getConversationsWithSelfParticipantIds(final List<String> selfIds) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final List<String> conversationIds = new ArrayList<String>();
+
+        Cursor cursor = null;
+        try {
+            final StringBuilder selectionList = new StringBuilder();
+            for (int i = 0; i < selfIds.size(); i++) {
+                selectionList.append('?');
+                if (i < selfIds.size() - 1) {
+                    selectionList.append(',');
+                }
+            }
+            final String selection =
+                    ConversationColumns.CURRENT_SELF_ID + " IN (" + selectionList + ")";
+            cursor = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                    new String[] { ConversationColumns._ID },
+                    selection, selfIds.toArray(new String[0]),
+                    null, null, null);
+
+            if (cursor != null) {
+                while (cursor.moveToNext()) {
+                    final String conversationId = cursor.getString(0);
+                    conversationIds.add(conversationId);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return conversationIds;
+    }
+
+    /**
+     * Refresh one conversation's self id.
+     */
+    private static void updateConversationSelfId(final String conversationId,
+            final String selfId) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        db.beginTransaction();
+        try {
+            BugleDatabaseOperations.updateConversationSelfIdInTransaction(db, conversationId,
+                    selfId);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        MessagingContentProvider.notifyMessagesChanged(conversationId);
+        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
+        UIIntents.get().broadcastConversationSelfIdChange(db.getContext(), conversationId, selfId);
+    }
+
+    /**
+     * After refreshing the self participant list, find all conversations with inactive self ids,
+     * and switch them back to system default.
+     */
+    private static void refreshConversationSelfIds() {
+        final List<String> inactiveSelfs = getInactiveSelfParticipantIds();
+        if (inactiveSelfs.size() == 0) {
+            return;
+        }
+        final List<String> conversationsToRefresh =
+                getConversationsWithSelfParticipantIds(inactiveSelfs);
+        if (conversationsToRefresh.size() == 0) {
+            return;
+        }
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final ParticipantData defaultSelf =
+                BugleDatabaseOperations.getOrCreateSelf(db, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        if (defaultSelf != null) {
+            for (final String conversationId : conversationsToRefresh) {
+                updateConversationSelfId(conversationId, defaultSelf.getId());
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/SyncManager.java b/src/com/android/messaging/datamodel/SyncManager.java
new file mode 100644
index 0000000..28fc696
--- /dev/null
+++ b/src/com/android/messaging/datamodel/SyncManager.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.provider.Telephony;
+import androidx.collection.LongSparseArray;
+
+import com.android.messaging.datamodel.action.SyncMessagesAction;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * This class manages message sync with the Telephony SmsProvider/MmsProvider.
+ */
+public class SyncManager {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    /**
+     * Record of any user customization to conversation settings
+     */
+    public static class ConversationCustomization {
+        private final boolean mArchived;
+        private final boolean mMuted;
+        private final boolean mNoVibrate;
+        private final String mNotificationSoundUri;
+
+        public ConversationCustomization(final boolean archived, final boolean muted,
+                final boolean noVibrate, final String notificationSoundUri) {
+            mArchived = archived;
+            mMuted = muted;
+            mNoVibrate = noVibrate;
+            mNotificationSoundUri = notificationSoundUri;
+        }
+
+        public boolean isArchived() {
+            return mArchived;
+        }
+
+        public boolean isMuted() {
+            return mMuted;
+        }
+
+        public boolean noVibrate() {
+            return mNoVibrate;
+        }
+
+        public String getNotificationSoundUri() {
+            return mNotificationSoundUri;
+        }
+    }
+
+    SyncManager() {
+    }
+
+    /**
+     * Timestamp of in progress sync - used to keep track of whether sync is running
+     */
+    private long mSyncInProgressTimestamp = -1;
+
+    /**
+     * Timestamp of current sync batch upper bound - used to determine if message makes batch dirty
+     */
+    private long mCurrentUpperBoundTimestamp = -1;
+
+    /**
+     * Timestamp of messages inserted since sync batch started - used to determine if batch dirty
+     */
+    private long mMaxRecentChangeTimestamp = -1L;
+
+    private final ThreadInfoCache mThreadInfoCache = new ThreadInfoCache();
+
+    /**
+     * User customization to conversations. If this is set, we need to recover them after
+     * a full sync.
+     */
+    private LongSparseArray<ConversationCustomization> mCustomization = null;
+
+    /**
+     * Start an incremental sync (backed off a few seconds)
+     */
+    public static void sync() {
+        SyncMessagesAction.sync();
+    }
+
+    /**
+     * Start an incremental sync (with no backoff)
+     */
+    public static void immediateSync() {
+        SyncMessagesAction.immediateSync();
+    }
+
+    /**
+     * Start a full sync (for debugging)
+     */
+    public static void forceSync() {
+        SyncMessagesAction.fullSync();
+    }
+
+    /**
+     * Called from data model thread when starting a sync batch
+     * @param upperBoundTimestamp upper bound timestamp for sync batch
+     */
+    public synchronized void startSyncBatch(final long upperBoundTimestamp) {
+        Assert.isTrue(mCurrentUpperBoundTimestamp < 0);
+        mCurrentUpperBoundTimestamp = upperBoundTimestamp;
+        mMaxRecentChangeTimestamp = -1L;
+    }
+
+    /**
+     * Called from data model thread at end of batch to determine if any messages added in window
+     * @param lowerBoundTimestamp lower bound timestamp for sync batch
+     * @return true if message added within window from lower to upper bound timestamp of batch
+     */
+    public synchronized boolean isBatchDirty(final long lowerBoundTimestamp) {
+        Assert.isTrue(mCurrentUpperBoundTimestamp >= 0);
+        final long max = mMaxRecentChangeTimestamp;
+
+        final boolean dirty = (max >= 0 && max >= lowerBoundTimestamp);
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncManager: Sync batch of messages from " + lowerBoundTimestamp
+                    + " to " + mCurrentUpperBoundTimestamp + " is "
+                    + (dirty ? "DIRTY" : "clean") + "; max change timestamp = "
+                    + mMaxRecentChangeTimestamp);
+        }
+
+        mCurrentUpperBoundTimestamp = -1L;
+        mMaxRecentChangeTimestamp = -1L;
+
+        return dirty;
+    }
+
+    /**
+     * Called from data model or background worker thread to indicate start of message add process
+     * (add must complete on that thread before action transitions to new thread/stage)
+     * @param timestamp timestamp of message being added
+     */
+    public synchronized void onNewMessageInserted(final long timestamp) {
+        if (mCurrentUpperBoundTimestamp >= 0 && timestamp <= mCurrentUpperBoundTimestamp) {
+            // Message insert in current sync window
+            mMaxRecentChangeTimestamp = Math.max(mCurrentUpperBoundTimestamp, timestamp);
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "SyncManager: New message @ " + timestamp + " before upper bound of "
+                        + "current sync batch " + mCurrentUpperBoundTimestamp);
+            }
+        } else if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncManager: New message @ " + timestamp + " after upper bound of "
+                    + "current sync batch " + mCurrentUpperBoundTimestamp);
+        }
+    }
+
+    /**
+     * Synchronously checks whether sync is allowed and starts sync if allowed
+     * @param full - true indicates a full (not incremental) sync operation
+     * @param startTimestamp - starttimestamp for this sync (if allowed)
+     * @return - true if sync should start
+     */
+    public synchronized boolean shouldSync(final boolean full, final long startTimestamp) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "SyncManager: Checking shouldSync " + (full ? "full " : "")
+                    + "at " + startTimestamp);
+        }
+
+        if (full) {
+            final long delayUntilFullSync = delayUntilFullSync(startTimestamp);
+            if (delayUntilFullSync > 0) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SyncManager: Full sync requested for " + startTimestamp
+                            + " delayed for " + delayUntilFullSync + " ms");
+                }
+                return false;
+            }
+        }
+
+        if (isSyncing()) {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "SyncManager: Not allowed to " + (full ? "full " : "")
+                        + "sync yet; still running sync started at " + mSyncInProgressTimestamp);
+            }
+            return false;
+        }
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncManager: Starting " + (full ? "full " : "") + "sync at "
+                    + startTimestamp);
+        }
+
+        mSyncInProgressTimestamp = startTimestamp;
+
+        return true;
+    }
+
+    /**
+     * Return delay (in ms) until allowed to run a full sync (0 meaning can run immediately)
+     * @param startTimestamp Timestamp used to start the sync
+     * @return 0 if allowed to run now, else delay in ms
+     */
+    public long delayUntilFullSync(final long startTimestamp) {
+        final BugleGservices bugleGservices = BugleGservices.get();
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+
+        final long lastFullSyncTime = prefs.getLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, -1L);
+        final long smsFullSyncBackoffTimeMillis = bugleGservices.getLong(
+                BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS,
+                BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
+        final long noFullSyncBefore = (lastFullSyncTime < 0 ? startTimestamp :
+            lastFullSyncTime + smsFullSyncBackoffTimeMillis);
+
+        final long delayUntilFullSync = noFullSyncBefore - startTimestamp;
+        if (delayUntilFullSync > 0) {
+            return delayUntilFullSync;
+        }
+        return 0;
+    }
+
+    /**
+     * Check if sync currently in progress (public for asserts/logging).
+     */
+    public synchronized boolean isSyncing() {
+        return (mSyncInProgressTimestamp >= 0);
+    }
+
+    /**
+     * Check if sync batch should be in progress - compares upperBound with in memory value
+     * @param upperBoundTimestamp - upperbound timestamp for sync batch
+     * @return - true if timestamps match (otherwise batch is orphan from older process)
+     */
+    public synchronized boolean isSyncing(final long upperBoundTimestamp) {
+        Assert.isTrue(upperBoundTimestamp >= 0);
+        return (upperBoundTimestamp == mCurrentUpperBoundTimestamp);
+    }
+
+    /**
+     * Check if sync has completed for the first time.
+     */
+    public boolean getHasFirstSyncCompleted() {
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        return prefs.getLong(BuglePrefsKeys.LAST_SYNC_TIME,
+                BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT) !=
+                BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT;
+    }
+
+    /**
+     * Called once sync is complete
+     */
+    public synchronized void complete() {
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncManager: Sync started at " + mSyncInProgressTimestamp
+                    + " marked as complete");
+        }
+        mSyncInProgressTimestamp = -1L;
+        // Conversation customization only used once
+        mCustomization = null;
+    }
+
+    private final ContentObserver mMmsSmsObserver = new TelephonyMessagesObserver();
+    private boolean mSyncOnChanges = false;
+    private boolean mNotifyOnChanges = false;
+
+    /**
+     * Register content observer when necessary and kick off a catch up sync
+     */
+    public void updateSyncObserver(final Context context) {
+        registerObserver(context);
+        // Trigger an sms sync in case we missed and messages before registering this observer or
+        // becoming the SMS provider.
+        immediateSync();
+    }
+
+    private void registerObserver(final Context context) {
+        if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
+            // Not default SMS app - need to actively monitor telephony but not notify
+            mNotifyOnChanges = false;
+            mSyncOnChanges = true;
+        } else if (OsUtil.isSecondaryUser()){
+            // Secondary users default SMS app - need to actively monitor telephony and notify
+            mNotifyOnChanges = true;
+            mSyncOnChanges = true;
+        } else {
+            // Primary users default SMS app - don't monitor telephony (most changes from this app)
+            mNotifyOnChanges = false;
+            mSyncOnChanges = false;
+            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+                // This is default SMS app but on Auto platform, even default SMS app needs
+                // to be notified of changes because Bluetooth makes changes to Sms database
+                // (thru ContentProvider). Content Change notifications help the default SMS app
+                // refresh display with changes, whenever Bluetooth changes data in SMS db.
+                mNotifyOnChanges = true;
+                mSyncOnChanges = false;
+            }
+        }
+        if (mNotifyOnChanges || mSyncOnChanges) {
+            context.getContentResolver().registerContentObserver(Telephony.MmsSms.CONTENT_URI,
+                    true, mMmsSmsObserver);
+        } else {
+            context.getContentResolver().unregisterContentObserver(mMmsSmsObserver);
+        }
+    }
+
+    public synchronized void setCustomization(
+            final LongSparseArray<ConversationCustomization> customization) {
+        this.mCustomization = customization;
+    }
+
+    public synchronized ConversationCustomization getCustomizationForThread(final long threadId) {
+        if (mCustomization != null) {
+            return mCustomization.get(threadId);
+        }
+        return null;
+    }
+
+    public static void resetLastSyncTimestamps() {
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME,
+                BuglePrefsKeys.LAST_FULL_SYNC_TIME_DEFAULT);
+        prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT);
+    }
+
+    private class TelephonyMessagesObserver extends ContentObserver {
+        public TelephonyMessagesObserver() {
+            // Just run on default thread
+            super(null);
+        }
+
+        // Implement the onChange(boolean) method to delegate the change notification to
+        // the onChange(boolean, Uri) method to ensure correct operation on older versions
+        // of the framework that did not have the onChange(boolean, Uri) method.
+        @Override
+        public void onChange(final boolean selfChange) {
+            onChange(selfChange, null);
+        }
+
+        // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
+        @Override
+        public void onChange(final boolean selfChange, final Uri uri) {
+            // Handle change.
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "SyncManager: Sms/Mms DB changed @" + System.currentTimeMillis()
+                        + " for " + (uri == null ? "<unk>" : uri.toString()) + " "
+                        + mSyncOnChanges + "/" + mNotifyOnChanges);
+            }
+
+            if (mSyncOnChanges) {
+                // If sync is already running this will do nothing - but at end of each sync
+                // action there is a check for recent messages that should catch new changes.
+                SyncManager.immediateSync();
+            }
+            if (mNotifyOnChanges) {
+                // TODO: Secondary users are not going to get notifications
+            }
+        }
+    }
+
+    public ThreadInfoCache getThreadInfoCache() {
+        return mThreadInfoCache;
+    }
+
+    public static class ThreadInfoCache {
+        // Cache of thread->conversationId map
+        private final LongSparseArray<String> mThreadToConversationId =
+                new LongSparseArray<String>();
+
+        // Cache of thread->recipients map
+        private final LongSparseArray<List<String>> mThreadToRecipients =
+                new LongSparseArray<List<String>>();
+
+        // Remember the conversation ids that need to be archived
+        private final HashSet<String> mArchivedConversations = new HashSet<>();
+
+        public synchronized void clear() {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "SyncManager: Cleared ThreadInfoCache");
+            }
+            mThreadToConversationId.clear();
+            mThreadToRecipients.clear();
+            mArchivedConversations.clear();
+        }
+
+        public synchronized boolean isArchived(final String conversationId) {
+            return mArchivedConversations.contains(conversationId);
+        }
+
+        /**
+         * Get or create a conversation based on the message's thread id
+         *
+         * @param threadId The message's thread
+         * @param refSubId The subId used for normalizing phone numbers in the thread
+         * @param customization The user setting customization to the conversation if any
+         * @return The existing conversation id or new conversation id
+         */
+        public synchronized String getOrCreateConversation(final DatabaseWrapper db,
+                final long threadId, int refSubId, final ConversationCustomization customization) {
+            // This function has several components which need to be atomic.
+            Assert.isTrue(db.getDatabase().inTransaction());
+
+            // If we already have this conversation ID in our local map, just return it
+            String conversationId = mThreadToConversationId.get(threadId);
+            if (conversationId != null) {
+                return conversationId;
+            }
+
+            final List<String> recipients = getThreadRecipients(threadId);
+            final ArrayList<ParticipantData> participants =
+                    BugleDatabaseOperations.getConversationParticipantsFromRecipients(recipients,
+                            refSubId);
+
+            if (customization != null) {
+                // There is user customization we need to recover
+                conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                        customization.isArchived(), participants, customization.isMuted(),
+                        customization.noVibrate(), customization.getNotificationSoundUri());
+                if (customization.isArchived()) {
+                    mArchivedConversations.add(conversationId);
+                }
+            } else {
+                conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                        false/*archived*/, participants, false/*noNotification*/,
+                        false/*noVibrate*/, null/*soundUri*/);
+            }
+
+            if (conversationId != null) {
+                mThreadToConversationId.put(threadId, conversationId);
+                return conversationId;
+            }
+
+            return null;
+        }
+
+
+        /**
+         * Load the recipients of a thread from telephony provider. If we fail, use
+         * a predefined unknown recipient. This should not return null.
+         *
+         * @param threadId
+         */
+        public synchronized List<String> getThreadRecipients(final long threadId) {
+            List<String> recipients = mThreadToRecipients.get(threadId);
+            if (recipients == null) {
+                recipients = MmsUtils.getRecipientsByThread(threadId);
+                if (recipients != null && recipients.size() > 0) {
+                    mThreadToRecipients.put(threadId, recipients);
+                }
+            }
+
+            if (recipients == null || recipients.isEmpty()) {
+                LogUtil.w(TAG, "SyncManager : using unknown sender since thread " + threadId +
+                        " couldn't find any recipients.");
+
+                // We want to try our best to load the messages,
+                // so if recipient info is broken, try to fix it with unknown recipient
+                recipients = Lists.newArrayList();
+                recipients.add(ParticipantData.getUnknownSenderDestination());
+            }
+
+            return recipients;
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/Action.java b/src/com/android/messaging/datamodel/action/Action.java
new file mode 100644
index 0000000..e4c332e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/Action.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelException;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener;
+import com.android.messaging.util.LogUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Base class for operations that perform application business logic off the main UI thread while
+ * holding a wake lock.
+ * .
+ * Note all derived classes need to provide real implementation of Parcelable (this is abstract)
+ */
+public abstract class Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    // Members holding the parameters common to all actions - no action state
+    public final String actionKey;
+
+    // If derived classes keep their data in actionParameters then parcelable is trivial
+    protected Bundle actionParameters;
+
+    // This does not get written to the parcel
+    private final List<Action> mBackgroundActions = new LinkedList<Action>();
+
+    /**
+     * Process the action locally - runs on action service thread.
+     * TODO: Currently, there is no way for this method to indicate failure
+     * @return result to be passed in to {@link ActionExecutedListener#onActionExecuted}. It is
+     *         also the result passed in to {@link ActionCompletedListener#onActionSucceeded} if
+     *         there is no background work.
+     */
+    protected Object executeAction() {
+        return null;
+    }
+
+    /**
+     * Queues up background work ie. {@link #doBackgroundWork} will be called on the
+     * background worker thread.
+     */
+    protected void requestBackgroundWork() {
+        mBackgroundActions.add(this);
+    }
+
+    /**
+     * Queues up background actions for background processing after the current action has
+     * completed its processing ({@link #executeAction}, {@link processBackgroundCompletion}
+     * or {@link #processBackgroundFailure}) on the Action thread.
+     * @param backgroundAction
+     */
+    protected void requestBackgroundWork(final Action backgroundAction) {
+        mBackgroundActions.add(backgroundAction);
+    }
+
+    /**
+     * Return flag indicating if any actions have been queued
+     */
+    public boolean hasBackgroundActions() {
+        return !mBackgroundActions.isEmpty();
+    }
+
+    /**
+     * Send queued actions to the background worker provided
+     */
+    public void sendBackgroundActions(final BackgroundWorker worker) {
+        worker.queueBackgroundWork(mBackgroundActions);
+        mBackgroundActions.clear();
+    }
+
+    /**
+     * Do work in a long running background worker thread.
+     * {@link #requestBackgroundWork} needs to be called for this method to
+     * be called. {@link #processBackgroundFailure} will be called on the Action service thread
+     * if this method throws {@link DataModelException}.
+     * @return response that is to be passed to {@link #processBackgroundResponse}
+     */
+    protected Bundle doBackgroundWork() throws DataModelException {
+        return null;
+    }
+
+    /**
+     * Process the success response from the background worker. Runs on action service thread.
+     * @param response the response returned by {@link #doBackgroundWork}
+     * @return result to be passed in to {@link ActionCompletedListener#onActionSucceeded}
+     */
+    protected Object processBackgroundResponse(final Bundle response) {
+        return null;
+    }
+
+    /**
+     * Called in case of failures when sending background actions. Runs on action service thread
+     * @return result to be passed in to {@link ActionCompletedListener#onActionFailed}
+     */
+    protected Object processBackgroundFailure() {
+        return null;
+    }
+
+    /**
+     * Constructor
+     */
+    protected Action(final String key) {
+        this.actionKey = key;
+        this.actionParameters = new Bundle();
+    }
+
+    /**
+     * Constructor
+     */
+    protected Action() {
+        this.actionKey = generateUniqueActionKey(getClass().getSimpleName());
+        this.actionParameters = new Bundle();
+    }
+
+    /**
+     * Queue an action and monitor for processing by the ActionService via the factory helper
+     */
+    protected void start(final ActionMonitor monitor) {
+        ActionMonitor.registerActionMonitor(this.actionKey, monitor);
+        DataModel.startActionService(this);
+    }
+
+    /**
+     * Queue an action for processing by the ActionService via the factory helper
+     */
+    public void start() {
+        DataModel.startActionService(this);
+    }
+
+    /**
+     * Queue an action for delayed processing by the ActionService via the factory helper
+     */
+    public void schedule(final int requestCode, final long delayMs) {
+        DataModel.scheduleAction(this, requestCode, delayMs);
+    }
+
+    /**
+     * Called when action queues ActionService intent
+     */
+    protected final void markStart() {
+        ActionMonitor.setState(this, ActionMonitor.STATE_CREATED,
+                ActionMonitor.STATE_QUEUED);
+    }
+
+    /**
+     * Mark the beginning of local action execution
+     */
+    protected final void markBeginExecute() {
+        ActionMonitor.setState(this, ActionMonitor.STATE_QUEUED,
+                ActionMonitor.STATE_EXECUTING);
+    }
+
+    /**
+     * Mark the end of local action execution - either completes the action or queues
+     * background actions
+     */
+    protected final void markEndExecute(final Object result) {
+        final boolean hasBackgroundActions = hasBackgroundActions();
+        ActionMonitor.setExecutedState(this, ActionMonitor.STATE_EXECUTING,
+                hasBackgroundActions, result);
+        if (!hasBackgroundActions) {
+            ActionMonitor.setCompleteState(this, ActionMonitor.STATE_EXECUTING,
+                    result, true);
+        }
+    }
+
+    /**
+     * Update action state to indicate that the background worker is starting
+     */
+    protected final void markBackgroundWorkStarting() {
+        ActionMonitor.setState(this,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
+    }
+
+    /**
+     * Update action state to indicate that the background worker has posted its response
+     * (or failure) to the Action service
+     */
+    protected final void markBackgroundCompletionQueued() {
+        ActionMonitor.setState(this,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED);
+    }
+
+    /**
+     * Update action state to indicate the background action failed but is being re-queued for retry
+     */
+    protected final void markBackgroundWorkQueued() {
+        ActionMonitor.setState(this,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
+    }
+
+    /**
+     * Called by ActionService to process a response from the background worker
+     * @param response the response returned by {@link #doBackgroundWork}
+     */
+    protected final void processBackgroundWorkResponse(final Bundle response) {
+        ActionMonitor.setState(this,
+                ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED,
+                ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE);
+        final Object result = processBackgroundResponse(response);
+        ActionMonitor.setCompleteState(this,
+                ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE, result, true);
+    }
+
+    /**
+     * Called by ActionService when a background action fails
+     */
+    protected final void processBackgroundWorkFailure() {
+        final Object result = processBackgroundFailure();
+        ActionMonitor.setCompleteState(this, ActionMonitor.STATE_UNDEFINED,
+                result, false);
+    }
+
+    private static final Object sLock = new Object();
+    private static long sActionIdx = System.currentTimeMillis() * 1000;
+
+    /**
+     * Helper method to generate a unique operation index
+     */
+    protected static long getActionIdx() {
+        long idx = 0;
+        synchronized (sLock) {
+            idx = ++sActionIdx;
+        }
+        return idx;
+    }
+
+    /**
+     * This helper can be used to generate a unique key used to identify an action.
+     * @param baseKey - key generated to identify the action parameters
+     * @return - composite key generated by appending unique index
+     */
+    protected static String generateUniqueActionKey(final String baseKey) {
+        final StringBuilder key = new StringBuilder();
+        if (!TextUtils.isEmpty(baseKey)) {
+            key.append(baseKey);
+        }
+        key.append(":");
+        key.append(getActionIdx());
+        return key.toString();
+    }
+
+    /**
+     * Most derived classes use this base implementation (unless they include files handles)
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Derived classes need to implement writeToParcel (but typically should call this method
+     * to parcel Action member variables before they parcel their member variables).
+     */
+    public void writeActionToParcel(final Parcel parcel, final int flags) {
+        parcel.writeString(this.actionKey);
+        parcel.writeBundle(this.actionParameters);
+    }
+
+    /**
+     * Helper for derived classes to implement parcelable
+     */
+    public Action(final Parcel in) {
+        this.actionKey = in.readString();
+        // Note: Need to set classloader to ensure we can un-parcel classes from this package
+        this.actionParameters = in.readBundle(Action.class.getClassLoader());
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ActionMonitor.java b/src/com/android/messaging/datamodel/action/ActionMonitor.java
new file mode 100644
index 0000000..ac83414
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ActionMonitor.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Handler;
+import androidx.collection.SimpleArrayMap;
+import android.text.TextUtils;
+
+import com.android.messaging.util.Assert.RunsOnAnyThread;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.ThreadUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Base class for action monitors
+ * Actions come in various flavors but
+ *  o) Fire and forget - no monitor
+ *  o) Immediate local processing only - will trigger ActionCompletedListener when done
+ *  o) Background worker processing only - will trigger ActionCompletedListener when done
+ *  o) Immediate local processing followed by background work followed by more local processing
+ *      - will trigger ActionExecutedListener once local processing complete and
+ *        ActionCompletedListener when second set of local process (dealing with background
+ *         worker response) is complete
+ */
+public class ActionMonitor {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    /**
+     * Interface used to notify on completion of local execution for an action
+     */
+    public interface ActionExecutedListener {
+        /**
+         * @param result value returned by {@link Action#executeAction}
+         */
+        @RunsOnMainThread
+        abstract void onActionExecuted(ActionMonitor monitor, final Action action,
+                final Object data, final Object result);
+    }
+
+    /**
+     * Interface used to notify action completion
+     */
+    public interface ActionCompletedListener {
+        /**
+         * @param result object returned from processing the action. This is the value returned by
+         *               {@link Action#executeAction} if there is no background work, or
+         *               else the value returned by
+         *               {@link Action#processBackgroundResponse}
+         */
+        @RunsOnMainThread
+        abstract void onActionSucceeded(ActionMonitor monitor,
+                final Action action, final Object data, final Object result);
+        /**
+         * @param result value returned by {@link Action#processBackgroundFailure}
+         */
+        @RunsOnMainThread
+        abstract void onActionFailed(ActionMonitor monitor, final Action action,
+                final Object data, final Object result);
+    }
+
+    /**
+     * Interface for being notified of action state changes - used for profiling, testing only
+     */
+    protected interface ActionStateChangedListener {
+        /**
+         * @param action the action that is changing state
+         * @param state the new state of the action
+         */
+        @RunsOnAnyThread
+        void onActionStateChanged(Action action, int state);
+    }
+
+    /**
+     * Operations always start out as STATE_CREATED and finish as STATE_COMPLETE.
+     * Some common state transition sequences in between include:
+     * <ul>
+     *   <li>Local data change only : STATE_QUEUED - STATE_EXECUTING
+     *   <li>Background worker request only : STATE_BACKGROUND_ACTIONS_QUEUED
+     *      - STATE_EXECUTING_BACKGROUND_ACTION
+     *      - STATE_BACKGROUND_COMPLETION_QUEUED
+     *      - STATE_PROCESSING_BACKGROUND_RESPONSE
+     *   <li>Local plus background worker request : STATE_QUEUED - STATE_EXECUTING
+     *      - STATE_BACKGROUND_ACTIONS_QUEUED
+     *      - STATE_EXECUTING_BACKGROUND_ACTION
+     *      - STATE_BACKGROUND_COMPLETION_QUEUED
+     *      - STATE_PROCESSING_BACKGROUND_RESPONSE
+     * </ul>
+     */
+    protected static final int STATE_UNDEFINED = 0;
+    protected static final int STATE_CREATED = 1; // Just created
+    protected static final int STATE_QUEUED = 2; // Action queued for processing
+    protected static final int STATE_EXECUTING = 3; // Action processing on datamodel thread
+    protected static final int STATE_BACKGROUND_ACTIONS_QUEUED = 4;
+    protected static final int STATE_EXECUTING_BACKGROUND_ACTION = 5;
+    // The background work has completed, either returning a success response or resulting in a
+    // failure
+    protected static final int STATE_BACKGROUND_COMPLETION_QUEUED = 6;
+    protected static final int STATE_PROCESSING_BACKGROUND_RESPONSE = 7;
+    protected static final int STATE_COMPLETE = 8; // Action complete
+
+    /**
+     * Lock used to protect access to state and listeners
+     */
+    private final Object mLock = new Object();
+
+    /**
+     * Current state of action
+     */
+    @VisibleForTesting
+    protected int mState;
+
+    /**
+     * Listener which is notified on action completion
+     */
+    private ActionCompletedListener mCompletedListener;
+
+    /**
+     * Listener which is notified on action executed
+     */
+    private ActionExecutedListener mExecutedListener;
+
+    /**
+     * Listener which is notified of state changes
+     */
+    private ActionStateChangedListener mStateChangedListener;
+
+    /**
+     * Handler used to post results back to caller
+     */
+    private final Handler mHandler;
+
+    /**
+     * Data passed back to listeners (associated with the action when it is created)
+     */
+    private final Object mData;
+
+    /**
+     * The action key is used to determine equivalence of operations and their requests
+     */
+    private final String mActionKey;
+
+    /**
+     * Get action key identifying associated action
+     */
+    public String getActionKey() {
+        return mActionKey;
+    }
+
+    /**
+     * Unregister listeners so that they will not be called back - override this method if needed
+     */
+    public void unregister() {
+        clearListeners();
+    }
+
+    /**
+     * Unregister listeners so that they will not be called
+     */
+    protected final void clearListeners() {
+        synchronized (mLock) {
+            mCompletedListener = null;
+            mExecutedListener = null;
+        }
+    }
+
+    /**
+     * Create a monitor associated with a particular action instance
+     */
+    protected ActionMonitor(final int initialState, final String actionKey,
+            final Object data) {
+        mHandler = ThreadUtil.getMainThreadHandler();
+        mActionKey = actionKey;
+        mState = initialState;
+        mData = data;
+    }
+
+    /**
+     * Return flag to indicate if action is complete
+     */
+    public boolean isComplete() {
+        boolean complete = false;
+        synchronized (mLock) {
+            complete = (mState == STATE_COMPLETE);
+        }
+        return complete;
+    }
+
+    /**
+     * Set listener that will be called with action completed result
+     */
+    protected final void setCompletedListener(final ActionCompletedListener listener) {
+        synchronized (mLock) {
+            mCompletedListener = listener;
+        }
+    }
+
+    /**
+     * Set listener that will be called with local execution result
+     */
+    protected final void setExecutedListener(final ActionExecutedListener listener) {
+        synchronized (mLock) {
+            mExecutedListener = listener;
+        }
+    }
+
+    /**
+     * Set listener that will be called with local execution result
+     */
+    protected final void setStateChangedListener(final ActionStateChangedListener listener) {
+        synchronized (mLock) {
+            mStateChangedListener = listener;
+        }
+    }
+
+    /**
+     * Perform a state update transition
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param newState - new state which will be set
+     */
+    @VisibleForTesting
+    protected void updateState(final Action action, final int expectedOldState,
+            final int newState) {
+        ActionStateChangedListener listener = null;
+        synchronized (mLock) {
+            if (expectedOldState != STATE_UNDEFINED &&
+                    mState != expectedOldState) {
+                throw new IllegalStateException("On updateState to " + newState + " was " + mState
+                        + " expecting " + expectedOldState);
+            }
+            if (newState != mState) {
+                mState = newState;
+                listener = mStateChangedListener;
+            }
+        }
+        if (listener != null) {
+            listener.onActionStateChanged(action, newState);
+        }
+    }
+
+    /**
+     * Perform a state update transition
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param newState - new state which will be set
+     */
+    static void setState(final Action action, final int expectedOldState,
+            final int newState) {
+        int oldMonitorState = expectedOldState;
+        int newMonitorState = newState;
+        final ActionMonitor monitor
+                = ActionMonitor.lookupActionMonitor(action.actionKey);
+        if (monitor != null) {
+            oldMonitorState = monitor.mState;
+            monitor.updateState(action, expectedOldState, newState);
+            newMonitorState = monitor.mState;
+        }
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+            df.setTimeZone(TimeZone.getTimeZone("UTC"));
+            LogUtil.v(TAG, "Operation-" + action.actionKey + ": @" + df.format(new Date())
+                    + "UTC State = " + oldMonitorState + " - " + newMonitorState);
+        }
+    }
+
+    /**
+     * Mark action complete
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param result - object returned from processing the action. This is the value returned by
+     *                 {@link Action#executeAction} if there is no background work, or
+     *                 else the value returned by {@link Action#processBackgroundResponse}
+     *                 or {@link Action#processBackgroundFailure}
+     */
+    private final void complete(final Action action,
+            final int expectedOldState, final Object result,
+            final boolean succeeded) {
+        ActionCompletedListener completedListener = null;
+        synchronized (mLock) {
+            setState(action, expectedOldState, STATE_COMPLETE);
+            completedListener = mCompletedListener;
+            mExecutedListener = null;
+            mStateChangedListener = null;
+        }
+        if (completedListener != null) {
+            // Marshal to UI thread
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    ActionCompletedListener listener = null;
+                    synchronized (mLock) {
+                        if (mCompletedListener != null) {
+                            listener = mCompletedListener;
+                        }
+                        mCompletedListener = null;
+                    }
+                    if (listener != null) {
+                        if (succeeded) {
+                            listener.onActionSucceeded(ActionMonitor.this,
+                                    action, mData, result);
+                        } else {
+                            listener.onActionFailed(ActionMonitor.this,
+                                    action, mData, result);
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Mark action complete
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param result - object returned from processing the action. This is the value returned by
+     *                 {@link Action#executeAction} if there is no background work, or
+     *                 else the value returned by {@link Action#processBackgroundResponse}
+     *                 or {@link Action#processBackgroundFailure}
+     */
+    static void setCompleteState(final Action action, final int expectedOldState,
+            final Object result, final boolean succeeded) {
+        int oldMonitorState = expectedOldState;
+        final ActionMonitor monitor
+                = ActionMonitor.lookupActionMonitor(action.actionKey);
+        if (monitor != null) {
+            oldMonitorState = monitor.mState;
+            monitor.complete(action, expectedOldState, result, succeeded);
+            unregisterActionMonitorIfComplete(action.actionKey, monitor);
+        }
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+            df.setTimeZone(TimeZone.getTimeZone("UTC"));
+            LogUtil.v(TAG, "Operation-" + action.actionKey + ": @" + df.format(new Date())
+                    + "UTC State = " + oldMonitorState + " - " + STATE_COMPLETE);
+        }
+    }
+
+    /**
+     * Mark action complete
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param hasBackgroundActions - has the completing action requested background work
+     * @param result - the return value of {@link Action#executeAction}
+     */
+    final void executed(final Action action,
+            final int expectedOldState, final boolean hasBackgroundActions, final Object result) {
+        ActionExecutedListener executedListener = null;
+        synchronized (mLock) {
+            if (hasBackgroundActions) {
+                setState(action, expectedOldState, STATE_BACKGROUND_ACTIONS_QUEUED);
+            }
+            executedListener = mExecutedListener;
+        }
+        if (executedListener != null) {
+            // Marshal to UI thread
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    ActionExecutedListener listener = null;
+                    synchronized (mLock) {
+                        if (mExecutedListener != null) {
+                            listener = mExecutedListener;
+                            mExecutedListener = null;
+                        }
+                    }
+                    if (listener != null) {
+                        listener.onActionExecuted(ActionMonitor.this,
+                                action, mData, result);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Mark action complete
+     * @param action - action whose state is updating
+     * @param expectedOldState - expected existing state of action (can be UNKNOWN)
+     * @param hasBackgroundActions - has the completing action requested background work
+     * @param result - the return value of {@link Action#executeAction}
+     */
+    static void setExecutedState(final Action action,
+            final int expectedOldState, final boolean hasBackgroundActions, final Object result) {
+        int oldMonitorState = expectedOldState;
+        final ActionMonitor monitor
+                = ActionMonitor.lookupActionMonitor(action.actionKey);
+        if (monitor != null) {
+            oldMonitorState = monitor.mState;
+            monitor.executed(action, expectedOldState, hasBackgroundActions, result);
+        }
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+            df.setTimeZone(TimeZone.getTimeZone("UTC"));
+            LogUtil.v(TAG, "Operation-" + action.actionKey + ": @" + df.format(new Date())
+                    + "UTC State = " + oldMonitorState + " - EXECUTED");
+        }
+    }
+
+    /**
+     * Map of action monitors indexed by actionKey
+     */
+    @VisibleForTesting
+    static SimpleArrayMap<String, ActionMonitor> sActionMonitors =
+            new SimpleArrayMap<String, ActionMonitor>();
+
+    /**
+     * Insert new monitor into map
+     */
+    static void registerActionMonitor(final String actionKey,
+            final ActionMonitor monitor) {
+        if (monitor != null
+                && (TextUtils.isEmpty(monitor.getActionKey())
+                        || TextUtils.isEmpty(actionKey)
+                        || !actionKey.equals(monitor.getActionKey()))) {
+            throw new IllegalArgumentException("Monitor key " + monitor.getActionKey()
+                    + " not compatible with action key " + actionKey);
+        }
+        synchronized (sActionMonitors) {
+            sActionMonitors.put(actionKey, monitor);
+        }
+    }
+
+    /**
+     * Find monitor associated with particular action
+     */
+    private static ActionMonitor lookupActionMonitor(final String actionKey) {
+        ActionMonitor monitor = null;
+        synchronized (sActionMonitors) {
+            monitor = sActionMonitors.get(actionKey);
+        }
+        return monitor;
+    }
+
+    /**
+     * Remove monitor from map
+     */
+    @VisibleForTesting
+    static void unregisterActionMonitor(final String actionKey,
+            final ActionMonitor monitor) {
+        if (monitor != null) {
+            synchronized (sActionMonitors) {
+                sActionMonitors.remove(actionKey);
+            }
+        }
+    }
+
+    /**
+     * Remove monitor from map if the action is complete
+     */
+    static void unregisterActionMonitorIfComplete(final String actionKey,
+            final ActionMonitor monitor) {
+        if (monitor != null && monitor.isComplete()) {
+            synchronized (sActionMonitors) {
+                sActionMonitors.remove(actionKey);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ActionService.java b/src/com/android/messaging/datamodel/action/ActionService.java
new file mode 100644
index 0000000..29225fa
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ActionService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.Bundle;
+
+/**
+ * Class providing interface for the ActionService - can be stubbed for testing
+ */
+public class ActionService {
+    protected static PendingIntent makeStartActionPendingIntent(final Context context,
+            final Action action, final int requestCode, final boolean launchesAnActivity) {
+        return ActionServiceImpl.makeStartActionPendingIntent(context, action, requestCode,
+                launchesAnActivity);
+    }
+
+    /**
+     * Start an action by posting it over the the ActionService
+     */
+    public void startAction(final Action action) {
+        ActionServiceImpl.startAction(action);
+    }
+
+    /**
+     * Schedule a delayed action by posting it over the the ActionService
+     */
+    public void scheduleAction(final Action action, final int code,
+            final long delayMs) {
+        ActionServiceImpl.scheduleAction(action, code, delayMs);
+    }
+
+    /**
+     * Process a response from the BackgroundWorker in the ActionService
+     */
+    protected void handleResponseFromBackgroundWorker(
+            final Action action, final Bundle response) {
+        ActionServiceImpl.handleResponseFromBackgroundWorker(action, response);
+    }
+
+    /**
+     * Process a failure from the BackgroundWorker in the ActionService
+     */
+    protected void handleFailureFromBackgroundWorker(final Action action,
+            final Exception exception) {
+        ActionServiceImpl.handleFailureFromBackgroundWorker(action, exception);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ActionServiceImpl.java b/src/com/android/messaging/datamodel/action/ActionServiceImpl.java
new file mode 100644
index 0000000..d78bdc0
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ActionServiceImpl.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+import androidx.core.app.JobIntentService;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.LoggingTimer;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * ActionService used to perform background processing for data model
+ */
+public class ActionServiceImpl extends JobIntentService {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final boolean VERBOSE = false;
+
+    /**
+     * Unique job ID for this service.
+     */
+    public static final int JOB_ID = 1000;
+
+    public ActionServiceImpl() {
+        super();
+    }
+
+    /**
+     * Start action by sending intent to the service
+     * @param action - action to start
+     */
+    protected static void startAction(final Action action) {
+        final Intent intent = makeIntent(OP_START_ACTION);
+        final Bundle actionBundle = new Bundle();
+        actionBundle.putParcelable(BUNDLE_ACTION, action);
+        intent.putExtra(EXTRA_ACTION_BUNDLE, actionBundle);
+        action.markStart();
+        startServiceWithIntent(intent);
+    }
+
+    /**
+     * Schedule an action to run after specified delay using alarm manager to send pendingintent
+     * @param action - action to start
+     * @param requestCode - request code used to collapse requests
+     * @param delayMs - delay in ms (from now) before action will start
+     */
+    protected static void scheduleAction(final Action action, final int requestCode,
+            final long delayMs) {
+        final Intent intent = PendingActionReceiver.makeIntent(OP_START_ACTION);
+        final Bundle actionBundle = new Bundle();
+        actionBundle.putParcelable(BUNDLE_ACTION, action);
+        intent.putExtra(EXTRA_ACTION_BUNDLE, actionBundle);
+
+        PendingActionReceiver.scheduleAlarm(intent, requestCode, delayMs);
+    }
+
+    /**
+     * Handle response returned by BackgroundWorker
+     * @param request - request generating response
+     * @param response - response from service
+     */
+    protected static void handleResponseFromBackgroundWorker(final Action action,
+            final Bundle response) {
+        final Intent intent = makeIntent(OP_RECEIVE_BACKGROUND_RESPONSE);
+
+        final Bundle actionBundle = new Bundle();
+        actionBundle.putParcelable(BUNDLE_ACTION, action);
+        intent.putExtra(EXTRA_ACTION_BUNDLE, actionBundle);
+        intent.putExtra(EXTRA_WORKER_RESPONSE, response);
+
+        startServiceWithIntent(intent);
+    }
+
+    /**
+     * Handle response returned by BackgroundWorker
+     * @param request - request generating failure
+     */
+    protected static void handleFailureFromBackgroundWorker(final Action action,
+            final Exception exception) {
+        final Intent intent = makeIntent(OP_RECEIVE_BACKGROUND_FAILURE);
+
+        final Bundle actionBundle = new Bundle();
+        actionBundle.putParcelable(BUNDLE_ACTION, action);
+        intent.putExtra(EXTRA_ACTION_BUNDLE, actionBundle);
+        intent.putExtra(EXTRA_WORKER_EXCEPTION, exception);
+
+        startServiceWithIntent(intent);
+    }
+
+    // ops
+    @VisibleForTesting
+    protected static final int OP_START_ACTION = 200;
+    @VisibleForTesting
+    protected static final int OP_RECEIVE_BACKGROUND_RESPONSE = 201;
+    @VisibleForTesting
+    protected static final int OP_RECEIVE_BACKGROUND_FAILURE = 202;
+
+    // extras
+    @VisibleForTesting
+    protected static final String EXTRA_OP_CODE = "op";
+    @VisibleForTesting
+    protected static final String EXTRA_ACTION_BUNDLE = "datamodel_action_bundle";
+    @VisibleForTesting
+    protected static final String EXTRA_WORKER_EXCEPTION = "worker_exception";
+    @VisibleForTesting
+    protected static final String EXTRA_WORKER_RESPONSE = "worker_response";
+    @VisibleForTesting
+    protected static final String EXTRA_WORKER_UPDATE = "worker_update";
+    @VisibleForTesting
+    protected static final String BUNDLE_ACTION = "bundle_action";
+
+    private BackgroundWorker mBackgroundWorker;
+
+    /**
+     * Allocate an intent with a specific opcode.
+     */
+    private static Intent makeIntent(final int opcode) {
+        final Intent intent = new Intent(Factory.get().getApplicationContext(),
+                ActionServiceImpl.class);
+        intent.putExtra(EXTRA_OP_CODE, opcode);
+        return intent;
+    }
+
+    /**
+     * Broadcast receiver for alarms scheduled through ActionService.
+     */
+    public static class PendingActionReceiver extends BroadcastReceiver {
+        static final String ACTION = "com.android.messaging.datamodel.PENDING_ACTION";
+
+        /**
+         * Allocate an intent with a specific opcode and alarm action.
+         */
+        public static Intent makeIntent(final int opcode) {
+            final Intent intent = new Intent(Factory.get().getApplicationContext(),
+                    PendingActionReceiver.class);
+            intent.setAction(ACTION);
+            intent.putExtra(EXTRA_OP_CODE, opcode);
+            return intent;
+        }
+
+        public static void scheduleAlarm(final Intent intent, final int requestCode,
+                final long delayMs) {
+            final Context context = Factory.get().getApplicationContext();
+            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+            final AlarmManager mgr =
+                    (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+            if (delayMs < Long.MAX_VALUE) {
+                mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                        SystemClock.elapsedRealtime() + delayMs, pendingIntent);
+            } else {
+                mgr.cancel(pendingIntent);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(final Context context, final Intent intent) {
+            ActionServiceImpl.startServiceWithIntent(intent);
+        }
+    }
+
+    /**
+     * Creates a pending intent that will trigger a data model action when the intent is
+     * triggered
+     */
+    public static PendingIntent makeStartActionPendingIntent(final Context context,
+            final Action action, final int requestCode, final boolean launchesAnActivity) {
+        final Intent intent = PendingActionReceiver.makeIntent(OP_START_ACTION);
+        final Bundle actionBundle = new Bundle();
+        actionBundle.putParcelable(BUNDLE_ACTION, action);
+        intent.putExtra(EXTRA_ACTION_BUNDLE, actionBundle);
+        if (launchesAnActivity) {
+            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        }
+        return PendingIntent.getBroadcast(context, requestCode, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mBackgroundWorker = DataModel.get().getBackgroundWorkerForActionService();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+    }
+
+    /**
+     * Queue intent to the ActionService.
+     */
+    private static void startServiceWithIntent(final Intent intent) {
+        final Context context = Factory.get().getApplicationContext();
+        final int opcode = intent.getIntExtra(EXTRA_OP_CODE, 0);
+        intent.setClass(context, ActionServiceImpl.class);
+        enqueueWork(context, intent);
+    }
+
+    public static void enqueueWork(Context context, Intent work) {
+        enqueueWork(context, ActionServiceImpl.class, JOB_ID, work);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void onHandleWork(final Intent intent) {
+        if (intent == null) {
+            // Shouldn't happen but sometimes does following another crash.
+            LogUtil.w(TAG, "ActionService.onHandleIntent: Called with null intent");
+            return;
+        }
+        final int opcode = intent.getIntExtra(EXTRA_OP_CODE, 0);
+
+        Action action;
+        final Bundle actionBundle = intent.getBundleExtra(EXTRA_ACTION_BUNDLE);
+        actionBundle.setClassLoader(getClassLoader());
+        switch(opcode) {
+            case OP_START_ACTION: {
+                action = (Action) actionBundle.getParcelable(BUNDLE_ACTION);
+                executeAction(action);
+                break;
+            }
+
+            case OP_RECEIVE_BACKGROUND_RESPONSE: {
+                action = (Action) actionBundle.getParcelable(BUNDLE_ACTION);
+                final Bundle response = intent.getBundleExtra(EXTRA_WORKER_RESPONSE);
+                processBackgroundResponse(action, response);
+                break;
+            }
+
+            case OP_RECEIVE_BACKGROUND_FAILURE: {
+                action = (Action) actionBundle.getParcelable(BUNDLE_ACTION);
+                processBackgroundFailure(action);
+                break;
+            }
+
+            default:
+                throw new RuntimeException("Unrecognized opcode in ActionServiceImpl");
+        }
+
+        action.sendBackgroundActions(mBackgroundWorker);
+    }
+
+    private static final long EXECUTION_TIME_WARN_LIMIT_MS = 1000; // 1 second
+    /**
+     * Local execution of action on ActionService thread
+     */
+    private void executeAction(final Action action) {
+        action.markBeginExecute();
+
+        final LoggingTimer timer = createLoggingTimer(action, "#executeAction");
+        timer.start();
+
+        final Object result = action.executeAction();
+
+        timer.stopAndLog();
+
+        action.markEndExecute(result);
+    }
+
+    /**
+     * Process response on ActionService thread
+     */
+    private void processBackgroundResponse(final Action action, final Bundle response) {
+        final LoggingTimer timer = createLoggingTimer(action, "#processBackgroundResponse");
+        timer.start();
+
+        action.processBackgroundWorkResponse(response);
+
+        timer.stopAndLog();
+    }
+
+    /**
+     * Process failure on ActionService thread
+     */
+    private void processBackgroundFailure(final Action action) {
+        final LoggingTimer timer = createLoggingTimer(action, "#processBackgroundFailure");
+        timer.start();
+
+        action.processBackgroundWorkFailure();
+
+        timer.stopAndLog();
+    }
+
+    private static LoggingTimer createLoggingTimer(
+            final Action action, final String methodName) {
+        return new LoggingTimer(TAG, action.getClass().getSimpleName() + methodName,
+                EXECUTION_TIME_WARN_LIMIT_MS);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/BackgroundWorker.java b/src/com/android/messaging/datamodel/action/BackgroundWorker.java
new file mode 100644
index 0000000..aad3c07
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/BackgroundWorker.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import java.util.List;
+
+/**
+ * Interface between action service and its workers
+ */
+public class BackgroundWorker {
+
+    /**
+     * Send list of requests from action service to a worker
+     */
+    public void queueBackgroundWork(final List<Action> backgroundActions) {
+        BackgroundWorkerService.queueBackgroundWork(backgroundActions);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/BackgroundWorkerService.java b/src/com/android/messaging/datamodel/action/BackgroundWorkerService.java
new file mode 100644
index 0000000..6096345
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/BackgroundWorkerService.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.core.app.JobIntentService;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelException;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.LoggingTimer;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.List;
+
+/**
+ * Background worker service is an initial example of a background work queue handler
+ * Used to actually "send" messages which may take some time and should not block ActionService
+ * or UI
+ */
+public class BackgroundWorkerService extends JobIntentService {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final boolean VERBOSE = false;
+
+    /**
+     * Unique job ID for this service.
+     */
+    public static final int JOB_ID = 1001;
+
+    private final ActionService mHost;
+
+    public BackgroundWorkerService() {
+        super();
+        mHost = DataModel.get().getActionService();
+    }
+
+    /**
+     * Queue a list of requests from action service to this worker
+     */
+    public static void queueBackgroundWork(final List<Action> actions) {
+        for (final Action action : actions) {
+            startServiceWithAction(action, 0);
+        }
+    }
+
+    // ops
+    @VisibleForTesting
+    protected static final int OP_PROCESS_REQUEST = 400;
+
+    // extras
+    @VisibleForTesting
+    protected static final String EXTRA_OP_CODE = "op";
+    @VisibleForTesting
+    protected static final String EXTRA_ACTION = "action";
+    @VisibleForTesting
+    protected static final String EXTRA_ATTEMPT = "retry_attempt";
+
+    /**
+     * Queue action intent to the BackgroundWorkerService.
+     */
+    private static void startServiceWithAction(final Action action,
+            final int retryCount) {
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_ACTION, action);
+        intent.putExtra(EXTRA_ATTEMPT, retryCount);
+        startServiceWithIntent(OP_PROCESS_REQUEST, intent);
+    }
+
+    /**
+     * Queue intent to the BackgroundWorkerService.
+     */
+    private static void startServiceWithIntent(final int opcode, final Intent intent) {
+        final Context context = Factory.get().getApplicationContext();
+
+        intent.setClass(context, BackgroundWorkerService.class);
+        intent.putExtra(EXTRA_OP_CODE, opcode);
+
+        enqueueWork(context, intent);
+    }
+
+    public static void enqueueWork(Context context, Intent work) {
+        enqueueWork(context, BackgroundWorkerService.class, JOB_ID, work);
+    }
+
+    @Override
+    protected void onHandleWork(final Intent intent) {
+        if (intent == null) {
+            // Shouldn't happen but sometimes does following another crash.
+            LogUtil.w(TAG, "BackgroundWorkerService.onHandleIntent: Called with null intent");
+            return;
+        }
+        final int opcode = intent.getIntExtra(EXTRA_OP_CODE, 0);
+
+        switch(opcode) {
+            case OP_PROCESS_REQUEST: {
+                final Action action = intent.getParcelableExtra(EXTRA_ACTION);
+                final int attempt = intent.getIntExtra(EXTRA_ATTEMPT, -1);
+                doBackgroundWork(action, attempt);
+                break;
+            }
+
+            default:
+                LogUtil.w(TAG, "Unrecognized opcode in BackgroundWorkerService " + opcode);
+                throw new RuntimeException("Unrecognized opcode in BackgroundWorkerService");
+        }
+    }
+
+    /**
+     * Local execution of background work for action on ActionService thread
+     */
+    private void doBackgroundWork(final Action action, final int attempt) {
+        action.markBackgroundWorkStarting();
+        Bundle response = null;
+        try {
+            final LoggingTimer timer = new LoggingTimer(
+                    TAG, action.getClass().getSimpleName() + "#doBackgroundWork");
+            timer.start();
+
+            response = action.doBackgroundWork();
+
+            timer.stopAndLog();
+            action.markBackgroundCompletionQueued();
+            mHost.handleResponseFromBackgroundWorker(action, response);
+        } catch (final Exception exception) {
+            final boolean retry = false;
+            LogUtil.e(TAG, "Error in background worker", exception);
+            if (!(exception instanceof DataModelException)) {
+                // DataModelException is expected (sort-of) and handled in handleFailureFromWorker
+                // below, but other exceptions should crash ENG builds
+                Assert.fail("Unexpected error in background worker - abort");
+            }
+            if (retry) {
+                action.markBackgroundWorkQueued();
+                startServiceWithAction(action, attempt + 1);
+            } else {
+                action.markBackgroundCompletionQueued();
+                mHost.handleFailureFromBackgroundWorker(action, exception);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/BugleActionToasts.java b/src/com/android/messaging/datamodel/action/BugleActionToasts.java
new file mode 100644
index 0000000..f60facd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/BugleActionToasts.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.widget.Toast;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.ThreadUtil;
+
+import javax.annotation.Nullable;
+
+/**
+ * Shows one-time, transient notifications in response to action failures (i.e. permanent failures
+ * when sending a message) by showing toasts.
+ */
+public class BugleActionToasts {
+    /**
+     * Called when SendMessageAction or DownloadMmsAction finishes
+     * @param conversationId the conversation of the sent or downloaded message
+     * @param success did the action succeed
+     * @param status the message sending status
+     * @param isSms whether the message is sent using SMS
+     * @param subId the subId of the SIM related to this send
+     * @param isSend whether it is a send (false for download)
+     */
+    static void onSendMessageOrManualDownloadActionCompleted(
+            final String conversationId,
+            final boolean success,
+            final int status,
+            final boolean isSms,
+            final int subId,
+            final boolean isSend) {
+        // We only show notifications for two cases, i.e. when mobile data is off or when we are
+        // in airplane mode, both of which fail fast with permanent failures.
+        if (!success && status == MmsUtils.MMS_REQUEST_MANUAL_RETRY) {
+            final PhoneUtils phoneUtils = PhoneUtils.get(subId);
+            if (phoneUtils.isAirplaneModeOn()) {
+                if (isSend) {
+                    showToast(R.string.send_message_failure_airplane_mode);
+                } else {
+                    showToast(R.string.download_message_failure_airplane_mode);
+                }
+                return;
+            } else if (!isSms && !phoneUtils.isMobileDataEnabled()) {
+                if (isSend) {
+                    showToast(R.string.send_message_failure_no_data);
+                } else {
+                    showToast(R.string.download_message_failure_no_data);
+                }
+                return;
+            }
+        }
+
+        if (AccessibilityUtil.isTouchExplorationEnabled(Factory.get().getApplicationContext())) {
+            final boolean isFocusedConversation = DataModel.get().isFocusedConversation(conversationId);
+            if (isFocusedConversation && success) {
+                // Using View.announceForAccessibility may be preferable, but we do not have a
+                // View, and so we use a toast instead.
+                showToast(isSend ? R.string.send_message_success
+                        : R.string.download_message_success);
+                return;
+            }
+
+            // {@link MessageNotificationState#checkFailedMessages} does not post a notification for
+            // failures in observable conversations. For accessibility, we provide an indication
+            // here.
+            final boolean isObservableConversation = DataModel.get().isNewMessageObservable(
+                    conversationId);
+            if (isObservableConversation && !success) {
+                showToast(isSend ? R.string.send_message_failure
+                        : R.string.download_message_failure);
+            }
+        }
+    }
+
+    public static void onMessageReceived(final String conversationId,
+            @Nullable final ParticipantData sender, @Nullable final MessageData message) {
+        final Context context = Factory.get().getApplicationContext();
+        if (AccessibilityUtil.isTouchExplorationEnabled(context)) {
+            final boolean isFocusedConversation = DataModel.get().isFocusedConversation(
+                    conversationId);
+            if (isFocusedConversation) {
+                final Resources res = context.getResources();
+                final String senderDisplayName = (sender == null)
+                        ? res.getString(R.string.unknown_sender) : sender.getDisplayName(false);
+                final String announcement = res.getString(
+                        R.string.incoming_message_announcement, senderDisplayName,
+                        (message == null) ? "" : message.getMessageText());
+                showToast(announcement);
+            }
+        }
+    }
+
+    public static void onConversationDeleted() {
+        showToast(R.string.conversation_deleted);
+    }
+
+    private static void showToast(final int messageResId) {
+        ThreadUtil.getMainThreadHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                Toast.makeText(getApplicationContext(),
+                        getApplicationContext().getString(messageResId), Toast.LENGTH_LONG).show();
+            }
+        });
+    }
+
+    private static void showToast(final String message) {
+        ThreadUtil.getMainThreadHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
+            }
+        });
+    }
+
+    private static Context getApplicationContext() {
+        return Factory.get().getApplicationContext();
+    }
+
+    private static class UpdateDestinationBlockedActionToast
+            implements UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener {
+        private final Context mContext;
+
+        UpdateDestinationBlockedActionToast(final Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void onUpdateDestinationBlockedAction(
+                final UpdateDestinationBlockedAction action,
+                final boolean success,
+                final boolean block,
+                final String destination) {
+            if (success) {
+                Toast.makeText(mContext,
+                        block
+                                ? R.string.update_destination_blocked
+                                : R.string.update_destination_unblocked,
+                        Toast.LENGTH_LONG
+                ).show();
+            }
+        }
+    }
+
+    public static UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
+            makeUpdateDestinationBlockedActionListener(final Context context) {
+        return new UpdateDestinationBlockedActionToast(context);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/DeleteConversationAction.java b/src/com/android/messaging/datamodel/action/DeleteConversationAction.java
new file mode 100644
index 0000000..a00f6d6
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/DeleteConversationAction.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelException;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.widget.WidgetConversationProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Action used to delete a conversation.
+ */
+public class DeleteConversationAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    public static void deleteConversation(final String conversationId, final long cutoffTimestamp) {
+        final DeleteConversationAction action = new DeleteConversationAction(conversationId,
+                cutoffTimestamp);
+        action.start();
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+    private static final String KEY_CUTOFF_TIMESTAMP = "cutoff_timestamp";
+
+    private DeleteConversationAction(final String conversationId, final long cutoffTimestamp) {
+        super();
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+        // TODO: Should we set cuttoff timestamp to prevent us deleting new messages?
+        actionParameters.putLong(KEY_CUTOFF_TIMESTAMP, cutoffTimestamp);
+    }
+
+    // Delete conversation from both the local DB and telephony in the background so sync cannot
+    // run concurrently and incorrectly try to recreate the conversation's messages locally. The
+    // telephony database can sometimes be quite slow to delete conversations, so we delete from
+    // the local DB first, notify the UI, and then delete from telephony.
+    @Override
+    protected Bundle doBackgroundWork() throws DataModelException {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final long cutoffTimestamp = actionParameters.getLong(KEY_CUTOFF_TIMESTAMP);
+
+        if (!TextUtils.isEmpty(conversationId)) {
+            // First find the thread id for this conversation.
+            final long threadId = BugleDatabaseOperations.getThreadId(db, conversationId);
+
+            if (BugleDatabaseOperations.deleteConversation(db, conversationId, cutoffTimestamp)) {
+                LogUtil.i(TAG, "DeleteConversationAction: Deleted local conversation "
+                        + conversationId);
+
+                BugleActionToasts.onConversationDeleted();
+
+                // Remove notifications if necessary
+                BugleNotifications.update(true /* silent */, null /* conversationId */,
+                        BugleNotifications.UPDATE_MESSAGES);
+
+                // We have changed the conversation list
+                MessagingContentProvider.notifyConversationListChanged();
+
+                // Notify the widget the conversation is deleted so it can go into its configure state.
+                WidgetConversationProvider.notifyConversationDeleted(
+                        Factory.get().getApplicationContext(),
+                        conversationId);
+            } else {
+                LogUtil.w(TAG, "DeleteConversationAction: Could not delete local conversation "
+                        + conversationId);
+                return null;
+            }
+
+            // Now delete from telephony DB. MmsSmsProvider throws an exception if the thread id is
+            // less than 0. If it's greater than zero, it will delete all messages with that thread
+            // id, even if there's no corresponding row in the threads table.
+            if (threadId >= 0) {
+                final int count = MmsUtils.deleteThread(threadId, cutoffTimestamp);
+                if (count > 0) {
+                    LogUtil.i(TAG, "DeleteConversationAction: Deleted telephony thread "
+                            + threadId + " (cutoffTimestamp = " + cutoffTimestamp + ")");
+                } else {
+                    LogUtil.w(TAG, "DeleteConversationAction: Could not delete thread from "
+                            + "telephony: conversationId = " + conversationId + ", thread id = "
+                            + threadId);
+                }
+            } else {
+                LogUtil.w(TAG, "DeleteConversationAction: Local conversation " + conversationId
+                        + " has an invalid telephony thread id; will delete messages individually");
+                deleteConversationMessagesFromTelephony();
+            }
+        } else {
+            LogUtil.e(TAG, "DeleteConversationAction: conversationId is empty");
+        }
+
+        return null;
+    }
+
+    /**
+     * Deletes all the telephony messages for the local conversation being deleted.
+     * <p>
+     * This is a fallback used when the conversation is not associated with any telephony thread,
+     * or its thread id is invalid (e.g. negative). This is not common, but can happen sometimes
+     * (e.g. the Unknown Sender conversation). In the usual case of deleting a conversation, we
+     * don't need this because the telephony provider automatically deletes messages when a thread
+     * is deleted.
+     */
+    private void deleteConversationMessagesFromTelephony() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        Assert.notNull(conversationId);
+
+        final List<Uri> messageUris = new ArrayList<>();
+        Cursor cursor = null;
+        try {
+            cursor = db.query(DatabaseHelper.MESSAGES_TABLE,
+                    new String[] { MessageColumns.SMS_MESSAGE_URI },
+                    MessageColumns.CONVERSATION_ID + "=?",
+                    new String[] { conversationId },
+                    null, null, null);
+            while (cursor.moveToNext()) {
+                String messageUri = cursor.getString(0);
+                try {
+                    messageUris.add(Uri.parse(messageUri));
+                } catch (Exception e) {
+                    LogUtil.e(TAG, "DeleteConversationAction: Could not parse message uri "
+                            + messageUri);
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        for (Uri messageUri : messageUris) {
+            int count = MmsUtils.deleteMessage(messageUri);
+            if (count > 0) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "DeleteConversationAction: Deleted telephony message "
+                            + messageUri);
+                }
+            } else {
+                LogUtil.w(TAG, "DeleteConversationAction: Could not delete telephony message "
+                        + messageUri);
+            }
+        }
+    }
+
+    @Override
+    protected Object executeAction() {
+        requestBackgroundWork();
+        return null;
+    }
+
+    private DeleteConversationAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<DeleteConversationAction> CREATOR
+            = new Parcelable.Creator<DeleteConversationAction>() {
+        @Override
+        public DeleteConversationAction createFromParcel(final Parcel in) {
+            return new DeleteConversationAction(in);
+        }
+
+        @Override
+        public DeleteConversationAction[] newArray(final int size) {
+            return new DeleteConversationAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/DeleteMessageAction.java b/src/com/android/messaging/datamodel/action/DeleteMessageAction.java
new file mode 100644
index 0000000..9ddb2a6
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/DeleteMessageAction.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action used to delete a single message.
+ */
+public class DeleteMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    public static void deleteMessage(final String messageId) {
+        final DeleteMessageAction action = new DeleteMessageAction(messageId);
+        action.start();
+    }
+
+    private static final String KEY_MESSAGE_ID = "message_id";
+
+    private DeleteMessageAction(final String messageId) {
+        super();
+        actionParameters.putString(KEY_MESSAGE_ID, messageId);
+    }
+
+    // Doing this work in the background so that we're not competing with sync
+    // which could bring the deleted message back to life between the time we deleted
+    // it locally and deleted it in telephony (sync is also done on doBackgroundWork).
+    //
+    // Previously this block of code deleted from telephony first but that can be very
+    // slow (on the order of seconds) so this was modified to first delete locally, trigger
+    // the UI update, then delete from telephony.
+    @Override
+    protected Bundle doBackgroundWork() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // First find the thread id for this conversation.
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+
+        if (!TextUtils.isEmpty(messageId)) {
+            // Check message still exists
+            final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+            if (message != null) {
+                // Delete from local DB
+                int count = BugleDatabaseOperations.deleteMessage(db, messageId);
+                if (count > 0) {
+                    LogUtil.i(TAG, "DeleteMessageAction: Deleted local message "
+                            + messageId);
+                } else {
+                    LogUtil.w(TAG, "DeleteMessageAction: Could not delete local message "
+                            + messageId);
+                }
+                MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+                // We may have changed the conversation list
+                MessagingContentProvider.notifyConversationListChanged();
+
+                final Uri messageUri = message.getSmsMessageUri();
+                if (messageUri != null) {
+                    // Delete from telephony DB
+                    count = MmsUtils.deleteMessage(messageUri);
+                    if (count > 0) {
+                        LogUtil.i(TAG, "DeleteMessageAction: Deleted telephony message "
+                                + messageUri);
+                    } else {
+                        LogUtil.w(TAG, "DeleteMessageAction: Could not delete message from "
+                                + "telephony: messageId = " + messageId + ", telephony uri = "
+                                + messageUri);
+                    }
+                } else {
+                    LogUtil.i(TAG, "DeleteMessageAction: Local message " + messageId
+                            + " has no telephony uri.");
+                }
+            } else {
+                LogUtil.w(TAG, "DeleteMessageAction: Message " + messageId + " no longer exists");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Delete the message.
+     */
+    @Override
+    protected Object executeAction() {
+        requestBackgroundWork();
+        return null;
+    }
+
+    private DeleteMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<DeleteMessageAction> CREATOR
+            = new Parcelable.Creator<DeleteMessageAction>() {
+        @Override
+        public DeleteMessageAction createFromParcel(final Parcel in) {
+            return new DeleteMessageAction(in);
+        }
+
+        @Override
+        public DeleteMessageAction[] newArray(final int size) {
+            return new DeleteMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/DownloadMmsAction.java b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
new file mode 100644
index 0000000..2852a61
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Downloads an MMS message.
+ * <p>
+ * This class is public (not package-private) because the SMS/MMS (e.g. MmsUtils) classes need to
+ * access the EXTRA_* fields for setting up the 'downloaded' pending intent.
+ */
+public class DownloadMmsAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    /**
+     * Interface for DownloadMmsAction listeners
+     */
+    public interface DownloadMmsActionListener {
+        @RunsOnMainThread
+        abstract void onDownloadMessageStarting(final ActionMonitor monitor,
+                final Object data, final MessageData message);
+        @RunsOnMainThread
+        abstract void onDownloadMessageSucceeded(final ActionMonitor monitor,
+                final Object data, final MessageData message);
+        @RunsOnMainThread
+        abstract void onDownloadMessageFailed(final ActionMonitor monitor,
+                final Object data, final MessageData message);
+    }
+
+    /**
+     * Queue download of an mms notification message (can only be called during execute of action)
+     */
+    static boolean queueMmsForDownloadInBackground(final String messageId,
+            final Action processingAction) {
+        // When this method is being called, it is always from auto download
+        final DownloadMmsAction action = new DownloadMmsAction();
+        // This could queue nothing
+        return action.queueAction(messageId, processingAction);
+    }
+
+    private static final String KEY_MESSAGE_ID = "message_id";
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+    private static final String KEY_PARTICIPANT_ID = "participant_id";
+    private static final String KEY_CONTENT_LOCATION = "content_location";
+    private static final String KEY_TRANSACTION_ID = "transaction_id";
+    private static final String KEY_NOTIFICATION_URI = "notification_uri";
+    private static final String KEY_SUB_ID = "sub_id";
+    private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
+    private static final String KEY_AUTO_DOWNLOAD = "auto_download";
+    private static final String KEY_FAILURE_STATUS = "failure_status";
+    private static final String KEY_EXPIRY = "expiry";
+
+    // Values we attach to the pending intent that's fired when the message is downloaded.
+    // Only applicable when downloading via the platform APIs on L+.
+    public static final String EXTRA_MESSAGE_ID = "message_id";
+    public static final String EXTRA_CONTENT_URI = "content_uri";
+    public static final String EXTRA_NOTIFICATION_URI = "notification_uri";
+    public static final String EXTRA_SUB_ID = "sub_id";
+    public static final String EXTRA_SUB_PHONE_NUMBER = "sub_phone_number";
+    public static final String EXTRA_TRANSACTION_ID = "transaction_id";
+    public static final String EXTRA_CONTENT_LOCATION = "content_location";
+    public static final String EXTRA_AUTO_DOWNLOAD = "auto_download";
+    public static final String EXTRA_RECEIVED_TIMESTAMP = "received_timestamp";
+    public static final String EXTRA_CONVERSATION_ID = "conversation_id";
+    public static final String EXTRA_PARTICIPANT_ID = "participant_id";
+    public static final String EXTRA_STATUS_IF_FAILED = "status_if_failed";
+    public static final String EXTRA_EXPIRY = "expiry";
+
+    private DownloadMmsAction() {
+        super();
+    }
+
+    @Override
+    protected Object executeAction() {
+        Assert.fail("DownloadMmsAction must be queued rather than started");
+        return null;
+    }
+
+    protected boolean queueAction(final String messageId, final Action processingAction) {
+        actionParameters.putString(KEY_MESSAGE_ID, messageId);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        // Read the message from local db
+        final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+        if (message != null && message.canDownloadMessage()) {
+            final Uri notificationUri = message.getSmsMessageUri();
+            final String conversationId = message.getConversationId();
+            final int status = message.getStatus();
+
+            final String selfId = message.getSelfId();
+            final ParticipantData self = BugleDatabaseOperations
+                    .getExistingParticipant(db, selfId);
+            final int subId = self.getSubId();
+            actionParameters.putInt(KEY_SUB_ID, subId);
+            actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+            actionParameters.putString(KEY_PARTICIPANT_ID, message.getParticipantId());
+            actionParameters.putString(KEY_CONTENT_LOCATION, message.getMmsContentLocation());
+            actionParameters.putString(KEY_TRANSACTION_ID, message.getMmsTransactionId());
+            actionParameters.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
+            actionParameters.putBoolean(KEY_AUTO_DOWNLOAD, isAutoDownload(status));
+            actionParameters.putLong(KEY_EXPIRY, message.getMmsExpiry());
+
+            final long now = System.currentTimeMillis();
+            if (message.getInDownloadWindow(now)) {
+                // We can still retry
+                actionParameters.putString(KEY_SUB_PHONE_NUMBER, self.getNormalizedDestination());
+
+                final int downloadingStatus = getDownloadingStatus(status);
+                // Update message status to indicate downloading.
+                updateMessageStatus(notificationUri, messageId, conversationId,
+                        downloadingStatus, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED);
+                // Pre-compute the next status when failed so we don't have to load from db again
+                actionParameters.putInt(KEY_FAILURE_STATUS, getFailureStatus(downloadingStatus));
+
+                // Actual download happens in background
+                processingAction.requestBackgroundWork(this);
+
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG,
+                            "DownloadMmsAction: Queued download of MMS message " + messageId);
+                }
+                return true;
+            } else {
+                LogUtil.w(TAG, "DownloadMmsAction: Download of MMS message " + messageId
+                        + " failed (outside download window)");
+
+                // Retries depleted and we failed. Update the message status so we won't retry again
+                updateMessageStatus(notificationUri, messageId, conversationId,
+                        MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED,
+                        MessageData.RAW_TELEPHONY_STATUS_UNDEFINED);
+                if (status == MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD) {
+                    // For auto download failure, we should send a DEFERRED NotifyRespInd
+                    // to carrier to indicate we will manual download later
+                    ProcessDownloadedMmsAction.sendDeferredRespStatus(
+                            messageId, message.getMmsTransactionId(),
+                            message.getMmsContentLocation(), subId);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Find out the auto download state of this message based on its starting status
+     *
+     * @param status The starting status of the message.
+     * @return True if this is a message doing auto downloading, false otherwise
+     */
+    private static boolean isAutoDownload(final int status) {
+        switch (status) {
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                return false;
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+                return true;
+            default:
+                Assert.fail("isAutoDownload: invalid input status " + status);
+                return false;
+        }
+    }
+
+    /**
+     * Get the corresponding downloading status based on the starting status of the message
+     *
+     * @param status The starting status of the message.
+     * @return The downloading status
+     */
+    private static int getDownloadingStatus(final int status) {
+        switch (status) {
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                return MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING;
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+                return MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING;
+            default:
+                Assert.fail("isAutoDownload: invalid input status " + status);
+                return MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING;
+        }
+    }
+
+    /**
+     * Get the corresponding failed status based on the current downloading status
+     *
+     * @param status The downloading status
+     * @return The status the message should have if downloading failed
+     */
+    private static int getFailureStatus(final int status) {
+        switch (status) {
+            case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
+                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD;
+            case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
+                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD;
+            default:
+                Assert.fail("isAutoDownload: invalid input status " + status);
+                return MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD;
+        }
+    }
+
+    @Override
+    protected Bundle doBackgroundWork() {
+        final Context context = Factory.get().getApplicationContext();
+        final int subId = actionParameters.getInt(KEY_SUB_ID);
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final Uri notificationUri = actionParameters.getParcelable(KEY_NOTIFICATION_URI);
+        final String subPhoneNumber = actionParameters.getString(KEY_SUB_PHONE_NUMBER);
+        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
+        final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION);
+        final boolean autoDownload = actionParameters.getBoolean(KEY_AUTO_DOWNLOAD);
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
+        final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
+        final long expiry = actionParameters.getLong(KEY_EXPIRY);
+
+        final long receivedTimestampRoundedToSecond =
+                1000 * ((System.currentTimeMillis() + 500) / 1000);
+
+        LogUtil.i(TAG, "DownloadMmsAction: Downloading MMS message " + messageId
+                + " (" + (autoDownload ? "auto" : "manual") + ")");
+
+        // Bundle some values we'll need after the message is downloaded (via platform APIs)
+        final Bundle extras = new Bundle();
+        extras.putString(EXTRA_MESSAGE_ID, messageId);
+        extras.putString(EXTRA_CONVERSATION_ID, conversationId);
+        extras.putString(EXTRA_PARTICIPANT_ID, participantId);
+        extras.putInt(EXTRA_STATUS_IF_FAILED, statusIfFailed);
+
+        // Start the download
+        final MmsUtils.StatusPlusUri status = MmsUtils.downloadMmsMessage(context,
+                notificationUri, subId, subPhoneNumber, transactionId, contentLocation,
+                autoDownload, receivedTimestampRoundedToSecond / 1000L, expiry / 1000L, extras);
+        if (status == MmsUtils.STATUS_PENDING) {
+            // Async download; no status yet
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "DownloadMmsAction: Downloading MMS message " + messageId
+                        + " asynchronously; waiting for pending intent to signal completion");
+            }
+        } else {
+            // Inform sync that message has been added at local received timestamp
+            final SyncManager syncManager = DataModel.get().getSyncManager();
+            syncManager.onNewMessageInserted(receivedTimestampRoundedToSecond);
+            // Handle downloaded message
+            ProcessDownloadedMmsAction.processMessageDownloadFastFailed(messageId,
+                    notificationUri, conversationId, participantId, contentLocation, subId,
+                    subPhoneNumber, statusIfFailed, autoDownload, transactionId,
+                    status.resultCode);
+        }
+        return null;
+    }
+
+    @Override
+    protected Object processBackgroundResponse(final Bundle response) {
+        // Nothing to do here; post-download actions handled by ProcessDownloadedMmsAction
+        return null;
+    }
+
+    @Override
+    protected Object processBackgroundFailure() {
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
+        final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
+        final int subId = actionParameters.getInt(KEY_SUB_ID);
+
+        ProcessDownloadedMmsAction.processDownloadActionFailure(messageId,
+                MmsUtils.MMS_REQUEST_MANUAL_RETRY, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
+                conversationId, participantId, statusIfFailed, subId, transactionId);
+
+        return null;
+    }
+
+    static void updateMessageStatus(final Uri messageUri, final String messageId,
+            final String conversationId, final int status, final int rawStatus) {
+        final Context context = Factory.get().getApplicationContext();
+        // Downloading status just kept in local DB but need to fix up telephony DB first
+        if (status == MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING ||
+                status == MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING) {
+            MmsUtils.clearMmsStatus(context, messageUri);
+        }
+        // Then mark downloading status in our local DB
+        final ContentValues values = new ContentValues();
+        values.put(MessageColumns.STATUS, status);
+        values.put(MessageColumns.RAW_TELEPHONY_STATUS, rawStatus);
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        BugleDatabaseOperations.updateMessageRowIfExists(db, messageId, values);
+
+        MessagingContentProvider.notifyMessagesChanged(conversationId);
+    }
+
+    private DownloadMmsAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<DownloadMmsAction> CREATOR
+            = new Parcelable.Creator<DownloadMmsAction>() {
+        @Override
+        public DownloadMmsAction createFromParcel(final Parcel in) {
+            return new DownloadMmsAction(in);
+        }
+
+        @Override
+        public DownloadMmsAction[] newArray(final int size) {
+            return new DownloadMmsAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/DumpDatabaseAction.java b/src/com/android/messaging/datamodel/action/DumpDatabaseAction.java
new file mode 100644
index 0000000..ab320bf
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/DumpDatabaseAction.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class DumpDatabaseAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    public static final String DUMP_NAME = "db_copy.db";
+    private static final int BUFFER_SIZE = 16384;
+
+    /**
+     * Copy the database to external storage
+     */
+    public static void dumpDatabase() {
+        final DumpDatabaseAction action = new DumpDatabaseAction();
+        action.start();
+    }
+
+    private DumpDatabaseAction() {
+    }
+
+    @Override
+    protected Object executeAction() {
+        final Context context = Factory.get().getApplicationContext();
+        final String dbName = DatabaseHelper.DATABASE_NAME;
+        BufferedOutputStream bos = null;
+        BufferedInputStream bis = null;
+
+        long originalSize = 0;
+        final File inFile = context.getDatabasePath(dbName);
+        if (inFile.exists() && inFile.isFile()) {
+            originalSize = inFile.length();
+        }
+        final File outFile = DebugUtils.getDebugFile(DUMP_NAME, true);
+        if (outFile != null) {
+            int totalBytes = 0;
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(outFile));
+                bis = new BufferedInputStream(new FileInputStream(inFile));
+
+                final byte[] buffer = new byte[BUFFER_SIZE];
+                int bytesRead;
+                while ((bytesRead = bis.read(buffer)) > 0) {
+                    bos.write(buffer, 0, bytesRead);
+                    totalBytes += bytesRead;
+                }
+            } catch (final IOException e) {
+                LogUtil.w(TAG, "Exception copying the database;"
+                        + " destination may not be complete.", e);
+            } finally {
+                if (bos != null) {
+                    try {
+                        bos.close();
+                    } catch (final IOException e) {
+                        // Nothing to do
+                    }
+                }
+
+                if (bis != null) {
+                    try {
+                        bis.close();
+                    } catch (final IOException e) {
+                        // Nothing to do
+                    }
+                }
+                DebugUtils.ensureReadable(outFile);
+                LogUtil.i(TAG, "Dump complete; orig size: " + originalSize +
+                        ", copy size: " + totalBytes);
+            }
+        }
+        return null;
+    }
+
+    private DumpDatabaseAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<DumpDatabaseAction> CREATOR
+            = new Parcelable.Creator<DumpDatabaseAction>() {
+        @Override
+        public DumpDatabaseAction createFromParcel(final Parcel in) {
+            return new DumpDatabaseAction(in);
+        }
+
+        @Override
+        public DumpDatabaseAction[] newArray(final int size) {
+            return new DumpDatabaseAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/FixupMessageStatusOnStartupAction.java b/src/com/android/messaging/datamodel/action/FixupMessageStatusOnStartupAction.java
new file mode 100644
index 0000000..45e2474
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/FixupMessageStatusOnStartupAction.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action used to fixup actively downloading or sending status at startup - just in case we
+ * crash - never run this when a message might actually be sending or downloading.
+ */
+public class FixupMessageStatusOnStartupAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    public static void fixupMessageStatus() {
+        final FixupMessageStatusOnStartupAction action = new FixupMessageStatusOnStartupAction();
+        action.start();
+    }
+
+    private FixupMessageStatusOnStartupAction() {
+    }
+
+    @Override
+    protected Object executeAction() {
+        // Now mark any messages in active sending or downloading state as inactive
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        int downloadFailedCnt = 0;
+        int sendFailedCnt = 0;
+        try {
+            // For both sending and downloading messages, let's assume they failed.
+            // For MMS sent/downloaded via platform, the sent/downloaded pending intent
+            // may come back. That will update the message. User may see the message
+            // in wrong status within a short window if that happens. But this should
+            // rarely happen. This is a simple solution to situations like app gets killed
+            // while the pending intent is still in the fly. Alternatively, we could
+            // keep the status for platform sent/downloaded MMS and timeout these messages.
+            // But that is much more complex.
+            final ContentValues values = new ContentValues();
+            values.put(DatabaseHelper.MessageColumns.STATUS,
+                    MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED);
+            downloadFailedCnt = db.update(DatabaseHelper.MESSAGES_TABLE, values,
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?)",
+                    new String[]{
+                            Integer.toString(MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING),
+                            Integer.toString(MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING)
+                    });
+
+            values.clear();
+            values.put(DatabaseHelper.MessageColumns.STATUS,
+                    MessageData.BUGLE_STATUS_OUTGOING_FAILED);
+            sendFailedCnt = db.update(DatabaseHelper.MESSAGES_TABLE, values,
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?)",
+                    new String[]{
+                            Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_SENDING),
+                            Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_RESENDING)
+                    });
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        LogUtil.i(TAG, "Fixup: Send failed - " + sendFailedCnt
+                + " Download failed - " + downloadFailedCnt);
+
+        // Don't send contentObserver notifications as displayed text should not change
+        return null;
+    }
+
+    private FixupMessageStatusOnStartupAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<FixupMessageStatusOnStartupAction> CREATOR
+            = new Parcelable.Creator<FixupMessageStatusOnStartupAction>() {
+        @Override
+        public FixupMessageStatusOnStartupAction createFromParcel(final Parcel in) {
+            return new FixupMessageStatusOnStartupAction(in);
+        }
+
+        @Override
+        public FixupMessageStatusOnStartupAction[] newArray(final int size) {
+            return new FixupMessageStatusOnStartupAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/GetOrCreateConversationAction.java b/src/com/android/messaging/datamodel/action/GetOrCreateConversationAction.java
new file mode 100644
index 0000000..b262141
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/GetOrCreateConversationAction.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
+import com.android.messaging.datamodel.data.LaunchConversationData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+
+/**
+ * Action used to get or create a conversation for a list of conversation participants.
+ */
+public class GetOrCreateConversationAction extends Action implements Parcelable {
+    /**
+     * Interface for GetOrCreateConversationAction listeners
+     */
+    public interface GetOrCreateConversationActionListener {
+        @RunsOnMainThread
+        abstract void onGetOrCreateConversationSucceeded(final ActionMonitor monitor,
+                final Object data, final String conversationId);
+
+        @RunsOnMainThread
+        abstract void onGetOrCreateConversationFailed(final ActionMonitor monitor,
+                final Object data);
+    }
+
+    public static GetOrCreateConversationActionMonitor getOrCreateConversation(
+            final ArrayList<ParticipantData> participants, final Object data,
+            final GetOrCreateConversationActionListener listener) {
+        final GetOrCreateConversationActionMonitor monitor = new
+                GetOrCreateConversationActionMonitor(data, listener);
+        final GetOrCreateConversationAction action = new GetOrCreateConversationAction(participants,
+                monitor.getActionKey());
+        action.start(monitor);
+        return monitor;
+    }
+
+
+    public static GetOrCreateConversationActionMonitor getOrCreateConversation(
+            final String[] recipients, final Object data, final LaunchConversationData listener) {
+        final ArrayList<ParticipantData> participants = new ArrayList<>();
+        for (String recipient : recipients) {
+            recipient = recipient.trim();
+            if (!TextUtils.isEmpty(recipient)) {
+                participants.add(ParticipantData.getFromRawPhoneBySystemLocale(recipient));
+            } else {
+                LogUtil.w(LogUtil.BUGLE_TAG, "getOrCreateConversation hit empty recipient");
+            }
+        }
+        return getOrCreateConversation(participants, data, listener);
+    }
+
+    private static final String KEY_PARTICIPANTS_LIST = "participants_list";
+
+    private GetOrCreateConversationAction(final ArrayList<ParticipantData> participants,
+            final String actionKey) {
+        super(actionKey);
+        actionParameters.putParcelableArrayList(KEY_PARTICIPANTS_LIST, participants);
+    }
+
+    /**
+     * Lookup the conversation or create a new one.
+     */
+    @Override
+    protected Object executeAction() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // First find the thread id for this list of participants.
+        final ArrayList<ParticipantData> participants =
+                actionParameters.getParcelableArrayList(KEY_PARTICIPANTS_LIST);
+        BugleDatabaseOperations.sanitizeConversationParticipants(participants);
+        final ArrayList<String> recipients =
+                BugleDatabaseOperations.getRecipientsFromConversationParticipants(participants);
+
+        final long threadId = MmsUtils.getOrCreateThreadId(Factory.get().getApplicationContext(),
+                recipients);
+
+        if (threadId < 0) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't create a threadId in SMS db for numbers : " +
+                    LogUtil.sanitizePII(recipients.toString()));
+            // TODO: Add a better way to indicate an error from executeAction.
+            return null;
+        }
+
+        final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                false, participants, false, false, null);
+
+        return conversationId;
+    }
+
+    /**
+     * A monitor that notifies a listener upon completion
+     */
+    public static class GetOrCreateConversationActionMonitor extends ActionMonitor
+            implements ActionCompletedListener {
+        private final GetOrCreateConversationActionListener mListener;
+
+        GetOrCreateConversationActionMonitor(final Object data,
+                final GetOrCreateConversationActionListener listener) {
+            super(STATE_CREATED, generateUniqueActionKey("GetOrCreateConversationAction"), data);
+            setCompletedListener(this);
+            mListener = listener;
+        }
+
+        @Override
+        public void onActionSucceeded(final ActionMonitor monitor,
+                final Action action, final Object data, final Object result) {
+            if (result == null) {
+                mListener.onGetOrCreateConversationFailed(monitor, data);
+            } else {
+                mListener.onGetOrCreateConversationSucceeded(monitor, data, (String) result);
+            }
+        }
+
+        @Override
+        public void onActionFailed(final ActionMonitor monitor,
+                final Action action, final Object data, final Object result) {
+            // TODO: Currently onActionFailed is only called if there is an error in
+            // processing requests, not for errors in the local processing.
+            Assert.fail("Unreachable");
+            mListener.onGetOrCreateConversationFailed(monitor, data);
+        }
+    }
+
+    private GetOrCreateConversationAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<GetOrCreateConversationAction> CREATOR
+            = new Parcelable.Creator<GetOrCreateConversationAction>() {
+        @Override
+        public GetOrCreateConversationAction createFromParcel(final Parcel in) {
+            return new GetOrCreateConversationAction(in);
+        }
+
+        @Override
+        public GetOrCreateConversationAction[] newArray(final int size) {
+            return new GetOrCreateConversationAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/HandleLowStorageAction.java b/src/com/android/messaging/datamodel/action/HandleLowStorageAction.java
new file mode 100644
index 0000000..7bfcfe0
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/HandleLowStorageAction.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.sms.SmsReleaseStorage;
+import com.android.messaging.util.Assert;
+
+/**
+ * Action used to handle low storage related issues on the device.
+ */
+public class HandleLowStorageAction extends Action implements Parcelable {
+    private static final int SUB_OP_CODE_CLEAR_MEDIA_MESSAGES = 100;
+    private static final int SUB_OP_CODE_CLEAR_OLD_MESSAGES = 101;
+
+    public static void handleDeleteMediaMessages(final long durationInMillis) {
+        final HandleLowStorageAction action = new HandleLowStorageAction(
+                SUB_OP_CODE_CLEAR_MEDIA_MESSAGES, durationInMillis);
+        action.start();
+    }
+
+    public static void handleDeleteOldMessages(final long durationInMillis) {
+        final HandleLowStorageAction action = new HandleLowStorageAction(
+                SUB_OP_CODE_CLEAR_OLD_MESSAGES, durationInMillis);
+        action.start();
+    }
+
+    private static final String KEY_SUB_OP_CODE = "sub_op_code";
+    private static final String KEY_CUTOFF_DURATION_MILLIS = "cutoff_duration_millis";
+
+    private HandleLowStorageAction(final int subOpcode, final long durationInMillis) {
+        super();
+        actionParameters.putInt(KEY_SUB_OP_CODE, subOpcode);
+        actionParameters.putLong(KEY_CUTOFF_DURATION_MILLIS, durationInMillis);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final int subOpCode = actionParameters.getInt(KEY_SUB_OP_CODE);
+        final long durationInMillis = actionParameters.getLong(KEY_CUTOFF_DURATION_MILLIS);
+        switch (subOpCode) {
+            case SUB_OP_CODE_CLEAR_MEDIA_MESSAGES:
+                SmsReleaseStorage.deleteMessages(0, durationInMillis);
+                break;
+
+            case SUB_OP_CODE_CLEAR_OLD_MESSAGES:
+                SmsReleaseStorage.deleteMessages(1, durationInMillis);
+                break;
+
+            default:
+                Assert.fail("Unsupported action type!");
+                break;
+        }
+        return true;
+    }
+
+    private HandleLowStorageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<HandleLowStorageAction> CREATOR
+            = new Parcelable.Creator<HandleLowStorageAction>() {
+        @Override
+        public HandleLowStorageAction createFromParcel(final Parcel in) {
+            return new HandleLowStorageAction(in);
+        }
+
+        @Override
+        public HandleLowStorageAction[] newArray(final int size) {
+            return new HandleLowStorageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java b/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java
new file mode 100644
index 0000000..8bf6d5e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Action used to convert a draft message to an outgoing message. Its writes SMS messages to
+ * the telephony db, but {@link SendMessageAction} is responsible for inserting MMS message into
+ * the telephony DB. The latter also does the actual sending of the message in the background.
+ * The latter is also responsible for re-sending a failed message.
+ */
+public class InsertNewMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static long sLastSentMessageTimestamp = -1;
+
+    /**
+     * Insert message (no listener)
+     */
+    public static void insertNewMessage(final MessageData message) {
+        final InsertNewMessageAction action = new InsertNewMessageAction(message);
+        action.start();
+    }
+
+    /**
+     * Insert message (no listener) with a given non-default subId.
+     */
+    public static void insertNewMessage(final MessageData message, final int subId) {
+        Assert.isFalse(subId == ParticipantData.DEFAULT_SELF_SUB_ID);
+        final InsertNewMessageAction action = new InsertNewMessageAction(message, subId);
+        action.start();
+    }
+
+    /**
+     * Insert message (no listener)
+     */
+    public static void insertNewMessage(final int subId, final String recipients,
+            final String messageText, final String subject) {
+        final InsertNewMessageAction action = new InsertNewMessageAction(
+                subId, recipients, messageText, subject);
+        action.start();
+    }
+
+    public static long getLastSentMessageTimestamp() {
+        return sLastSentMessageTimestamp;
+    }
+
+    private static final String KEY_SUB_ID = "sub_id";
+    private static final String KEY_MESSAGE = "message";
+    private static final String KEY_RECIPIENTS = "recipients";
+    private static final String KEY_MESSAGE_TEXT = "message_text";
+    private static final String KEY_SUBJECT_TEXT = "subject_text";
+
+    private InsertNewMessageAction(final MessageData message) {
+        this(message, ParticipantData.DEFAULT_SELF_SUB_ID);
+        actionParameters.putParcelable(KEY_MESSAGE, message);
+    }
+
+    private InsertNewMessageAction(final MessageData message, final int subId) {
+        super();
+        actionParameters.putParcelable(KEY_MESSAGE, message);
+        actionParameters.putInt(KEY_SUB_ID, subId);
+    }
+
+    private InsertNewMessageAction(final int subId, final String recipients,
+            final String messageText, final String subject) {
+        super();
+        if (TextUtils.isEmpty(recipients) || TextUtils.isEmpty(messageText)) {
+            Assert.fail("InsertNewMessageAction: Can't have empty recipients or message");
+        }
+        actionParameters.putInt(KEY_SUB_ID, subId);
+        actionParameters.putString(KEY_RECIPIENTS, recipients);
+        actionParameters.putString(KEY_MESSAGE_TEXT, messageText);
+        actionParameters.putString(KEY_SUBJECT_TEXT, subject);
+    }
+
+    /**
+     * Add message to database in pending state and queue actual sending
+     */
+    @Override
+    protected Object executeAction() {
+        MessageData message = actionParameters.getParcelable(KEY_MESSAGE);
+        if (message == null) {
+            LogUtil.i(TAG, "InsertNewMessageAction: Creating MessageData with provided data");
+            message = createMessage();
+            if (message == null) {
+                LogUtil.w(TAG, "InsertNewMessageAction: Could not create MessageData");
+                return null;
+            }
+        }
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final String conversationId = message.getConversationId();
+
+        final ParticipantData self = getSelf(db, conversationId, message);
+        if (self == null) {
+            return null;
+        }
+        message.bindSelfId(self.getId());
+        // If the user taps the Send button before the conversation draft is created/loaded by
+        // ReadDraftDataAction (maybe the action service thread was busy), the MessageData may not
+        // have the participant id set. It should be equal to the self id, so we'll use that.
+        if (message.getParticipantId() == null) {
+            message.bindParticipantId(self.getId());
+        }
+
+        final long timestamp = System.currentTimeMillis();
+        final ArrayList<String> recipients =
+                BugleDatabaseOperations.getRecipientsForConversation(db, conversationId);
+        if (recipients.size() < 1) {
+            LogUtil.w(TAG, "InsertNewMessageAction: message recipients is empty");
+            return null;
+        }
+        final int subId = self.getSubId();
+        LogUtil.i(TAG, "InsertNewMessageAction: inserting new message for subId " + subId);
+        actionParameters.putInt(KEY_SUB_ID, subId);
+
+        // TODO: Work out whether to send with SMS or MMS (taking into account recipients)?
+        final boolean isSms = (message.getProtocol() == MessageData.PROTOCOL_SMS);
+        if (isSms) {
+            String sendingConversationId = conversationId;
+            if (recipients.size() > 1) {
+                // Broadcast SMS - put message in "fake conversation" before farming out to real 1:1
+                final long laterTimestamp = timestamp + 1;
+                // Send a single message
+                insertBroadcastSmsMessage(conversationId, message, subId,
+                        laterTimestamp, recipients);
+
+                sendingConversationId = null;
+            }
+
+            for (final String recipient : recipients) {
+                // Start actual sending
+                insertSendingSmsMessage(message, subId, recipient,
+                        timestamp, sendingConversationId);
+            }
+
+            // Can now clear draft from conversation (deleting attachments if necessary)
+            BugleDatabaseOperations.updateDraftMessageData(db, conversationId,
+                    null /* message */, BugleDatabaseOperations.UPDATE_MODE_CLEAR_DRAFT);
+        } else {
+            final long timestampRoundedToSecond = 1000 * ((timestamp + 500) / 1000);
+            // Write place holder message directly referencing parts from the draft
+            final MessageData messageToSend = insertSendingMmsMessage(conversationId,
+                    message, timestampRoundedToSecond);
+
+            // Can now clear draft from conversation (preserving attachments which are now
+            // referenced by messageToSend)
+            BugleDatabaseOperations.updateDraftMessageData(db, conversationId,
+                    messageToSend, BugleDatabaseOperations.UPDATE_MODE_CLEAR_DRAFT);
+        }
+        MessagingContentProvider.notifyConversationListChanged();
+        ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
+
+        return message;
+    }
+
+    private ParticipantData getSelf(
+            final DatabaseWrapper db, final String conversationId, final MessageData message) {
+        ParticipantData self;
+        // Check if we are asked to bind to a non-default subId. This is directly passed in from
+        // the UI thread so that the sub id may be locked as soon as the user clicks on the Send
+        // button.
+        final int requestedSubId = actionParameters.getInt(
+                KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        if (requestedSubId != ParticipantData.DEFAULT_SELF_SUB_ID) {
+            self = BugleDatabaseOperations.getOrCreateSelf(db, requestedSubId);
+        } else {
+            String selfId = message.getSelfId();
+            if (selfId == null) {
+                // The conversation draft provides no self id hint, meaning that 1) conversation
+                // self id was not loaded AND 2) the user didn't pick a SIM from the SIM selector.
+                // In this case, use the conversation's self id.
+                final ConversationListItemData conversation =
+                        ConversationListItemData.getExistingConversation(db, conversationId);
+                if (conversation != null) {
+                    selfId = conversation.getSelfId();
+                } else {
+                    LogUtil.w(LogUtil.BUGLE_DATAMODEL_TAG, "Conversation " + conversationId +
+                            "already deleted before sending draft message " +
+                            message.getMessageId() + ". Aborting InsertNewMessageAction.");
+                    return null;
+                }
+            }
+
+            // We do not use SubscriptionManager.DEFAULT_SUB_ID for sending a message, so we need
+            // to bind the message to the system default subscription if it's unbound.
+            final ParticipantData unboundSelf = BugleDatabaseOperations.getExistingParticipant(
+                    db, selfId);
+            if (unboundSelf.getSubId() == ParticipantData.DEFAULT_SELF_SUB_ID
+                    && OsUtil.isAtLeastL_MR1()) {
+                final int defaultSubId = PhoneUtils.getDefault().getDefaultSmsSubscriptionId();
+                self = BugleDatabaseOperations.getOrCreateSelf(db, defaultSubId);
+            } else {
+                self = unboundSelf;
+            }
+        }
+        return self;
+    }
+
+    /** Create MessageData using KEY_RECIPIENTS, KEY_MESSAGE_TEXT and KEY_SUBJECT */
+    private MessageData createMessage() {
+        // First find the thread id for this list of participants.
+        final String recipientsList = actionParameters.getString(KEY_RECIPIENTS);
+        final String messageText = actionParameters.getString(KEY_MESSAGE_TEXT);
+        final String subjectText = actionParameters.getString(KEY_SUBJECT_TEXT);
+        final int subId = actionParameters.getInt(
+                KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        final ArrayList<ParticipantData> participants = new ArrayList<>();
+        for (final String recipient : recipientsList.split(",")) {
+            participants.add(ParticipantData.getFromRawPhoneBySimLocale(recipient, subId));
+        }
+        if (participants.size() == 0) {
+            Assert.fail("InsertNewMessage: Empty participants");
+            return null;
+        }
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        BugleDatabaseOperations.sanitizeConversationParticipants(participants);
+        final ArrayList<String> recipients =
+                BugleDatabaseOperations.getRecipientsFromConversationParticipants(participants);
+        if (recipients.size() == 0) {
+            Assert.fail("InsertNewMessage: Empty recipients");
+            return null;
+        }
+
+        final long threadId = MmsUtils.getOrCreateThreadId(Factory.get().getApplicationContext(),
+                recipients);
+
+        if (threadId < 0) {
+            Assert.fail("InsertNewMessage: Couldn't get threadId in SMS db for these recipients: "
+                    + recipients.toString());
+            // TODO: How do we fail the action?
+            return null;
+        }
+
+        final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                false, participants, false, false, null);
+
+        final ParticipantData self = BugleDatabaseOperations.getOrCreateSelf(db, subId);
+
+        if (TextUtils.isEmpty(subjectText)) {
+            return MessageData.createDraftSmsMessage(conversationId, self.getId(), messageText);
+        } else {
+            return MessageData.createDraftMmsMessage(conversationId, self.getId(), messageText,
+                    subjectText);
+        }
+    }
+
+    private void insertBroadcastSmsMessage(final String conversationId,
+            final MessageData message, final int subId, final long laterTimestamp,
+            final ArrayList<String> recipients) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "InsertNewMessageAction: Inserting broadcast SMS message "
+                    + message.getMessageId());
+        }
+        final Context context = Factory.get().getApplicationContext();
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // Inform sync that message is being added at timestamp
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        syncManager.onNewMessageInserted(laterTimestamp);
+
+        final long threadId = BugleDatabaseOperations.getThreadId(db, conversationId);
+        final String address = TextUtils.join(" ", recipients);
+
+        final String messageText = message.getMessageText();
+        // Insert message into telephony database sms message table
+        final Uri messageUri = MmsUtils.insertSmsMessage(context,
+                Telephony.Sms.CONTENT_URI,
+                subId,
+                address,
+                messageText,
+                laterTimestamp,
+                Telephony.Sms.STATUS_COMPLETE,
+                Telephony.Sms.MESSAGE_TYPE_SENT, threadId);
+        if (messageUri != null && !TextUtils.isEmpty(messageUri.toString())) {
+            db.beginTransaction();
+            try {
+                message.updateSendingMessage(conversationId, messageUri, laterTimestamp);
+                message.markMessageSent(laterTimestamp);
+
+                BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+
+                BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
+                        conversationId, message.getMessageId(), laterTimestamp,
+                        false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "InsertNewMessageAction: Inserted broadcast SMS message "
+                        + message.getMessageId() + ", uri = " + message.getSmsMessageUri());
+            }
+            MessagingContentProvider.notifyMessagesChanged(conversationId);
+            MessagingContentProvider.notifyPartsChanged();
+        } else {
+            // Ignore error as we only really care about the individual messages?
+            LogUtil.e(TAG,
+                    "InsertNewMessageAction: No uri for broadcast SMS " + message.getMessageId()
+                    + " inserted into telephony DB");
+        }
+    }
+
+    /**
+     * Insert SMS messaging into our database and telephony db.
+     */
+    private MessageData insertSendingSmsMessage(final MessageData content, final int subId,
+            final String recipient, final long timestamp, final String sendingConversationId) {
+        sLastSentMessageTimestamp = timestamp;
+
+        final Context context = Factory.get().getApplicationContext();
+
+        // Inform sync that message is being added at timestamp
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        syncManager.onNewMessageInserted(timestamp);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // Send a single message
+        long threadId;
+        String conversationId;
+        if (sendingConversationId == null) {
+            // For 1:1 message generated sending broadcast need to look up threadId+conversationId
+            threadId = MmsUtils.getOrCreateSmsThreadId(context, recipient);
+            conversationId = BugleDatabaseOperations.getOrCreateConversationFromRecipient(
+                    db, threadId, false /* sender blocked */,
+                    ParticipantData.getFromRawPhoneBySimLocale(recipient, subId));
+        } else {
+            // Otherwise just look up threadId
+            threadId = BugleDatabaseOperations.getThreadId(db, sendingConversationId);
+            conversationId = sendingConversationId;
+        }
+
+        final String messageText = content.getMessageText();
+
+        // Insert message into telephony database sms message table
+        final Uri messageUri = MmsUtils.insertSmsMessage(context,
+                Telephony.Sms.CONTENT_URI,
+                subId,
+                recipient,
+                messageText,
+                timestamp,
+                Telephony.Sms.STATUS_NONE,
+                Telephony.Sms.MESSAGE_TYPE_SENT, threadId);
+
+        MessageData message = null;
+        if (messageUri != null && !TextUtils.isEmpty(messageUri.toString())) {
+            db.beginTransaction();
+            try {
+                message = MessageData.createDraftSmsMessage(conversationId,
+                        content.getSelfId(), messageText);
+                message.updateSendingMessage(conversationId, messageUri, timestamp);
+
+                BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+
+                // Do not update the conversation summary to reflect autogenerated 1:1 messages
+                if (sendingConversationId != null) {
+                    BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
+                            conversationId, message.getMessageId(), timestamp,
+                            false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
+                }
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "InsertNewMessageAction: Inserted SMS message "
+                        + message.getMessageId() + " (uri = " + message.getSmsMessageUri()
+                        + ", timestamp = " + message.getReceivedTimeStamp() + ")");
+            }
+            MessagingContentProvider.notifyMessagesChanged(conversationId);
+            MessagingContentProvider.notifyPartsChanged();
+        } else {
+            LogUtil.e(TAG, "InsertNewMessageAction: No uri for SMS inserted into telephony DB");
+        }
+
+        return message;
+    }
+
+    /**
+     * Insert MMS messaging into our database.
+     */
+    private MessageData insertSendingMmsMessage(final String conversationId,
+            final MessageData message, final long timestamp) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        final List<MessagePartData> attachmentsUpdated = new ArrayList<>();
+        try {
+            sLastSentMessageTimestamp = timestamp;
+
+            // Insert "draft" message as placeholder until the final message is written to
+            // the telephony db
+            message.updateSendingMessage(conversationId, null/*messageUri*/, timestamp);
+
+            // No need to inform SyncManager as message currently has no Uri...
+            BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+
+            BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
+                    conversationId, message.getMessageId(), timestamp,
+                    false /* senderBlocked */, false /* shouldAutoSwitchSelfId */);
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "InsertNewMessageAction: Inserted MMS message "
+                    + message.getMessageId() + " (timestamp = " + timestamp + ")");
+        }
+        MessagingContentProvider.notifyMessagesChanged(conversationId);
+        MessagingContentProvider.notifyPartsChanged();
+
+        return message;
+    }
+
+    private InsertNewMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<InsertNewMessageAction> CREATOR
+            = new Parcelable.Creator<InsertNewMessageAction>() {
+        @Override
+        public InsertNewMessageAction createFromParcel(final Parcel in) {
+            return new InsertNewMessageAction(in);
+        }
+
+        @Override
+        public InsertNewMessageAction[] newArray(final int size) {
+            return new InsertNewMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/LogTelephonyDatabaseAction.java b/src/com/android/messaging/datamodel/action/LogTelephonyDatabaseAction.java
new file mode 100644
index 0000000..441a5a2
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/LogTelephonyDatabaseAction.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.Threads;
+import android.provider.Telephony.ThreadsColumns;
+
+import com.android.messaging.Factory;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+
+public class LogTelephonyDatabaseAction extends Action implements Parcelable {
+    // Because we use sanitizePII, we should also use BUGLE_TAG
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final String[] ALL_THREADS_PROJECTION = {
+        Threads._ID,
+        Threads.DATE,
+        Threads.MESSAGE_COUNT,
+        Threads.RECIPIENT_IDS,
+        Threads.SNIPPET,
+        Threads.SNIPPET_CHARSET,
+        Threads.READ,
+        Threads.ERROR,
+        Threads.HAS_ATTACHMENT };
+
+    // Constants from the Telephony Database
+    private static final int ID               = 0;
+    private static final int DATE             = 1;
+    private static final int MESSAGE_COUNT    = 2;
+    private static final int RECIPIENT_IDS    = 3;
+    private static final int SNIPPET          = 4;
+    private static final int SNIPPET_CHAR_SET = 5;
+    private static final int READ             = 6;
+    private static final int ERROR            = 7;
+    private static final int HAS_ATTACHMENT   = 8;
+
+    /**
+     * Log telephony data to logcat
+     */
+    public static void dumpDatabase() {
+        final LogTelephonyDatabaseAction action = new LogTelephonyDatabaseAction();
+        action.start();
+    }
+
+    private LogTelephonyDatabaseAction() {
+    }
+
+    @Override
+    protected Object executeAction() {
+        final Context context = Factory.get().getApplicationContext();
+
+        if (!DebugUtils.isDebugEnabled()) {
+            LogUtil.e(TAG, "Can't log telephony database unless debugging is enabled");
+            return null;
+        }
+
+        if (!LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.w(TAG, "Can't log telephony database unless DEBUG is turned on for TAG: " +
+                    TAG);
+            return null;
+        }
+
+        LogUtil.d(TAG, "\n");
+        LogUtil.d(TAG, "Dump of canoncial_addresses table");
+        LogUtil.d(TAG, "*********************************");
+
+        Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+                Uri.parse("content://mms-sms/canonical-addresses"), null, null, null, null);
+
+        if (cursor == null) {
+            LogUtil.w(TAG, "null Cursor in content://mms-sms/canonical-addresses");
+        } else {
+            try {
+                while (cursor.moveToNext()) {
+                    long id = cursor.getLong(0);
+                    String number = cursor.getString(1);
+                    LogUtil.d(TAG, LogUtil.sanitizePII("id: " + id + " number: " + number));
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+
+        LogUtil.d(TAG, "\n");
+        LogUtil.d(TAG, "Dump of threads table");
+        LogUtil.d(TAG, "*********************");
+
+        cursor = SqliteWrapper.query(context, context.getContentResolver(),
+                Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build(),
+                ALL_THREADS_PROJECTION, null, null, "date ASC");
+        try {
+            while (cursor.moveToNext()) {
+                LogUtil.d(TAG, LogUtil.sanitizePII("threadId: " + cursor.getLong(ID) +
+                        " " + ThreadsColumns.DATE + " : " + cursor.getLong(DATE) +
+                        " " + ThreadsColumns.MESSAGE_COUNT + " : " + cursor.getInt(MESSAGE_COUNT) +
+                        " " + ThreadsColumns.SNIPPET + " : " + cursor.getString(SNIPPET) +
+                        " " + ThreadsColumns.READ + " : " + cursor.getInt(READ) +
+                        " " + ThreadsColumns.ERROR + " : " + cursor.getInt(ERROR) +
+                        " " + ThreadsColumns.HAS_ATTACHMENT + " : " +
+                            cursor.getInt(HAS_ATTACHMENT) +
+                        " " + ThreadsColumns.RECIPIENT_IDS + " : " +
+                            cursor.getString(RECIPIENT_IDS)));
+            }
+        } finally {
+            cursor.close();
+        }
+
+        return null;
+    }
+
+    private LogTelephonyDatabaseAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<LogTelephonyDatabaseAction> CREATOR
+            = new Parcelable.Creator<LogTelephonyDatabaseAction>() {
+        @Override
+        public LogTelephonyDatabaseAction createFromParcel(final Parcel in) {
+            return new LogTelephonyDatabaseAction(in);
+        }
+
+        @Override
+        public LogTelephonyDatabaseAction[] newArray(final int size) {
+            return new LogTelephonyDatabaseAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/MarkAsReadAction.java b/src/com/android/messaging/datamodel/action/MarkAsReadAction.java
new file mode 100644
index 0000000..31bc59d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/MarkAsReadAction.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action used to mark all the messages in a conversation as read
+ */
+public class MarkAsReadAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+
+    /**
+     * Mark all the messages as read for a particular conversation.
+     */
+    public static void markAsRead(final String conversationId) {
+        final MarkAsReadAction action = new MarkAsReadAction(conversationId);
+        action.start();
+    }
+
+    private MarkAsReadAction(final String conversationId) {
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+
+        // TODO: Consider doing this in background service to avoid delaying other actions
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // Mark all messages in thread as read in telephony
+        final long threadId = BugleDatabaseOperations.getThreadId(db, conversationId);
+        if (threadId != -1) {
+            MmsUtils.updateSmsReadStatus(threadId, Long.MAX_VALUE);
+        }
+
+        // Update local db
+        db.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+            values.put(MessageColumns.CONVERSATION_ID, conversationId);
+            values.put(MessageColumns.READ, 1);
+            values.put(MessageColumns.SEEN, 1);     // if they read it, they saw it
+
+            final int count = db.update(DatabaseHelper.MESSAGES_TABLE, values,
+                    "(" + MessageColumns.READ + " !=1 OR " +
+                            MessageColumns.SEEN + " !=1 ) AND " +
+                            MessageColumns.CONVERSATION_ID + "=?",
+                    new String[] { conversationId });
+            if (count > 0) {
+                MessagingContentProvider.notifyMessagesChanged(conversationId);
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        // After marking messages as read, update the notifications. This will
+        // clear the now stale notifications.
+        BugleNotifications.update(false/*silent*/, BugleNotifications.UPDATE_ALL);
+        return null;
+    }
+
+    private MarkAsReadAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<MarkAsReadAction> CREATOR
+            = new Parcelable.Creator<MarkAsReadAction>() {
+        @Override
+        public MarkAsReadAction createFromParcel(final Parcel in) {
+            return new MarkAsReadAction(in);
+        }
+
+        @Override
+        public MarkAsReadAction[] newArray(final int size) {
+            return new MarkAsReadAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/MarkAsSeenAction.java b/src/com/android/messaging/datamodel/action/MarkAsSeenAction.java
new file mode 100644
index 0000000..28f55fd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/MarkAsSeenAction.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action used to mark all messages as seen
+ */
+public class MarkAsSeenAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+
+    /**
+     * Mark all messages as seen.
+     */
+    public static void markAllAsSeen() {
+        final MarkAsSeenAction action = new MarkAsSeenAction((String) null/*conversationId*/);
+        action.start();
+    }
+
+    /**
+     * Mark all messages of a given conversation as seen.
+     */
+    public static void markAsSeen(final String conversationId) {
+        final MarkAsSeenAction action = new MarkAsSeenAction(conversationId);
+        action.start();
+    }
+
+    /**
+     * ctor for MarkAsSeenAction.
+     * @param conversationId the conversation id for which to mark as seen, or null to mark all
+     *        messages as seen
+     */
+    public MarkAsSeenAction(final String conversationId) {
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String conversationId =
+                actionParameters.getString(KEY_CONVERSATION_ID);
+        final boolean hasSpecificConversation = !TextUtils.isEmpty(conversationId);
+
+        // Everything in telephony should already have the seen bit set.
+        // Possible exception are messages which did not have seen set and
+        // were sync'ed into bugle.
+
+        // Now mark the messages as seen in the bugle db
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+
+        try {
+            final ContentValues values = new ContentValues();
+            values.put(MessageColumns.SEEN, 1);
+
+            if (hasSpecificConversation) {
+                final int count = db.update(DatabaseHelper.MESSAGES_TABLE, values,
+                        MessageColumns.SEEN + " != 1 AND " +
+                                MessageColumns.CONVERSATION_ID + "=?",
+                        new String[] { conversationId });
+                if (count > 0) {
+                    MessagingContentProvider.notifyMessagesChanged(conversationId);
+                }
+            } else {
+                db.update(DatabaseHelper.MESSAGES_TABLE, values,
+                        MessageColumns.SEEN + " != 1", null/*selectionArgs*/);
+            }
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        // After marking messages as seen, update the notifications. This will
+        // clear the now stale notifications.
+        BugleNotifications.update(false/*silent*/, BugleNotifications.UPDATE_ALL);
+        return null;
+    }
+
+    private MarkAsSeenAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<MarkAsSeenAction> CREATOR
+            = new Parcelable.Creator<MarkAsSeenAction>() {
+        @Override
+        public MarkAsSeenAction createFromParcel(final Parcel in) {
+            return new MarkAsSeenAction(in);
+        }
+
+        @Override
+        public MarkAsSeenAction[] newArray(final int size) {
+            return new MarkAsSeenAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ProcessDeliveryReportAction.java b/src/com/android/messaging/datamodel/action/ProcessDeliveryReportAction.java
new file mode 100644
index 0000000..fbd4e82
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ProcessDeliveryReportAction.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.concurrent.TimeUnit;
+
+public class ProcessDeliveryReportAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_URI = "uri";
+    private static final String KEY_STATUS = "status";
+
+    private ProcessDeliveryReportAction(final Uri uri, final int status) {
+        actionParameters.putParcelable(KEY_URI, uri);
+        actionParameters.putInt(KEY_STATUS, status);
+    }
+
+    public static void deliveryReportReceived(final Uri uri, final int status) {
+        final ProcessDeliveryReportAction action = new ProcessDeliveryReportAction(uri, status);
+        action.start();
+    }
+
+    @Override
+    protected Object executeAction() {
+        final Uri smsMessageUri = actionParameters.getParcelable(KEY_URI);
+        final int status = actionParameters.getInt(KEY_STATUS);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final long messageRowId = ContentUris.parseId(smsMessageUri);
+        if (messageRowId < 0) {
+            LogUtil.e(TAG, "ProcessDeliveryReportAction: can't find message");
+            return null;
+        }
+        final long timeSentInMillis = System.currentTimeMillis();
+        // Update telephony provider
+        if (smsMessageUri != null) {
+            MmsUtils.updateSmsStatusAndDateSent(smsMessageUri, status, timeSentInMillis);
+        }
+
+        // Update local message
+        db.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+            final int bugleStatus = SyncMessageBatch.bugleStatusForSms(true /*outgoing*/,
+                    Telephony.Sms.MESSAGE_TYPE_SENT /* type */, status);
+            values.put(DatabaseHelper.MessageColumns.STATUS, bugleStatus);
+            values.put(DatabaseHelper.MessageColumns.SENT_TIMESTAMP,
+                    TimeUnit.MILLISECONDS.toMicros(timeSentInMillis));
+
+            final MessageData messageData =
+                    BugleDatabaseOperations.readMessageData(db, smsMessageUri);
+
+            // Check the message was not removed before the delivery report comes in
+            if (messageData !=  null) {
+                Assert.isTrue(smsMessageUri.equals(messageData.getSmsMessageUri()));
+
+                // Row must exist as was just loaded above (on ActionService thread)
+                BugleDatabaseOperations.updateMessageRow(db, messageData.getMessageId(), values);
+
+                MessagingContentProvider.notifyMessagesChanged(messageData.getConversationId());
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        return null;
+    }
+
+    private ProcessDeliveryReportAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ProcessDeliveryReportAction> CREATOR
+            = new Parcelable.Creator<ProcessDeliveryReportAction>() {
+        @Override
+        public ProcessDeliveryReportAction createFromParcel(final Parcel in) {
+            return new ProcessDeliveryReportAction(in);
+        }
+
+        @Override
+        public ProcessDeliveryReportAction[] newArray(final int size) {
+            return new ProcessDeliveryReportAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java
new file mode 100644
index 0000000..60d3e35
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.Mms;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelException;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.MmsFileProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.mmslib.pdu.RetrieveConf;
+import com.android.messaging.sms.DatabaseMessages;
+import com.android.messaging.sms.MmsSender;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Processes an MMS message after it has been downloaded.
+ * NOTE: This action must queue a ProcessPendingMessagesAction when it is done (success or failure).
+ */
+public class ProcessDownloadedMmsAction extends Action {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    // Always set when message downloaded
+    private static final String KEY_DOWNLOADED_BY_PLATFORM = "downloaded_by_platform";
+    private static final String KEY_MESSAGE_ID = "message_id";
+    private static final String KEY_NOTIFICATION_URI = "notification_uri";
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+    private static final String KEY_PARTICIPANT_ID = "participant_id";
+    private static final String KEY_STATUS_IF_FAILED = "status_if_failed";
+
+    // Set when message downloaded by platform (L+)
+    private static final String KEY_RESULT_CODE = "result_code";
+    private static final String KEY_HTTP_STATUS_CODE = "http_status_code";
+    private static final String KEY_CONTENT_URI = "content_uri";
+    private static final String KEY_SUB_ID = "sub_id";
+    private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
+    private static final String KEY_TRANSACTION_ID = "transaction_id";
+    private static final String KEY_CONTENT_LOCATION = "content_location";
+    private static final String KEY_AUTO_DOWNLOAD = "auto_download";
+    private static final String KEY_RECEIVED_TIMESTAMP = "received_timestamp";
+    private static final String KEY_EXPIRY = "expiry";
+
+    // Set when message downloaded by us (legacy)
+    private static final String KEY_STATUS = "status";
+    private static final String KEY_RAW_STATUS = "raw_status";
+    private static final String KEY_MMS_URI = "mms_uri";
+
+    // Used to send a deferred response in response to auto-download failure
+    private static final String KEY_SEND_DEFERRED_RESP_STATUS = "send_deferred_resp_status";
+
+    // Results passed from background worker to processCompletion
+    private static final String BUNDLE_REQUEST_STATUS = "request_status";
+    private static final String BUNDLE_RAW_TELEPHONY_STATUS = "raw_status";
+    private static final String BUNDLE_MMS_URI = "mms_uri";
+
+    // This is called when MMS lib API returns via PendingIntent
+    public static void processMessageDownloaded(final int resultCode, final Bundle extras) {
+        final String messageId = extras.getString(DownloadMmsAction.EXTRA_MESSAGE_ID);
+        final Uri contentUri = extras.getParcelable(DownloadMmsAction.EXTRA_CONTENT_URI);
+        final Uri notificationUri = extras.getParcelable(DownloadMmsAction.EXTRA_NOTIFICATION_URI);
+        final String conversationId = extras.getString(DownloadMmsAction.EXTRA_CONVERSATION_ID);
+        final String participantId = extras.getString(DownloadMmsAction.EXTRA_PARTICIPANT_ID);
+        Assert.notNull(messageId);
+        Assert.notNull(contentUri);
+        Assert.notNull(notificationUri);
+        Assert.notNull(conversationId);
+        Assert.notNull(participantId);
+
+        final ProcessDownloadedMmsAction action = new ProcessDownloadedMmsAction();
+        final Bundle params = action.actionParameters;
+        params.putBoolean(KEY_DOWNLOADED_BY_PLATFORM, true);
+        params.putString(KEY_MESSAGE_ID, messageId);
+        params.putInt(KEY_RESULT_CODE, resultCode);
+        params.putInt(KEY_HTTP_STATUS_CODE,
+                extras.getInt(SmsManager.EXTRA_MMS_HTTP_STATUS, 0));
+        params.putParcelable(KEY_CONTENT_URI, contentUri);
+        params.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
+        params.putInt(KEY_SUB_ID,
+                extras.getInt(DownloadMmsAction.EXTRA_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID));
+        params.putString(KEY_SUB_PHONE_NUMBER,
+                extras.getString(DownloadMmsAction.EXTRA_SUB_PHONE_NUMBER));
+        params.putString(KEY_TRANSACTION_ID,
+                extras.getString(DownloadMmsAction.EXTRA_TRANSACTION_ID));
+        params.putString(KEY_CONTENT_LOCATION,
+                extras.getString(DownloadMmsAction.EXTRA_CONTENT_LOCATION));
+        params.putBoolean(KEY_AUTO_DOWNLOAD,
+                extras.getBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD));
+        params.putLong(KEY_RECEIVED_TIMESTAMP,
+                extras.getLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP));
+        params.putString(KEY_CONVERSATION_ID, conversationId);
+        params.putString(KEY_PARTICIPANT_ID, participantId);
+        params.putInt(KEY_STATUS_IF_FAILED,
+                extras.getInt(DownloadMmsAction.EXTRA_STATUS_IF_FAILED));
+        params.putLong(KEY_EXPIRY, extras.getLong(DownloadMmsAction.EXTRA_EXPIRY));
+        action.start();
+    }
+
+    // This is called for fast failing downloading (due to airplane mode or mobile data )
+    public static void processMessageDownloadFastFailed(final String messageId,
+            final Uri notificationUri, final String conversationId, final String participantId,
+            final String contentLocation, final int subId, final String subPhoneNumber,
+            final int statusIfFailed, final boolean autoDownload, final String transactionId,
+            final int resultCode) {
+        Assert.notNull(messageId);
+        Assert.notNull(notificationUri);
+        Assert.notNull(conversationId);
+        Assert.notNull(participantId);
+
+        final ProcessDownloadedMmsAction action = new ProcessDownloadedMmsAction();
+        final Bundle params = action.actionParameters;
+        params.putBoolean(KEY_DOWNLOADED_BY_PLATFORM, true);
+        params.putString(KEY_MESSAGE_ID, messageId);
+        params.putInt(KEY_RESULT_CODE, resultCode);
+        params.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
+        params.putInt(KEY_SUB_ID, subId);
+        params.putString(KEY_SUB_PHONE_NUMBER, subPhoneNumber);
+        params.putString(KEY_CONTENT_LOCATION, contentLocation);
+        params.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload);
+        params.putString(KEY_CONVERSATION_ID, conversationId);
+        params.putString(KEY_PARTICIPANT_ID, participantId);
+        params.putInt(KEY_STATUS_IF_FAILED, statusIfFailed);
+        params.putString(KEY_TRANSACTION_ID, transactionId);
+        action.start();
+    }
+
+    public static void processDownloadActionFailure(final String messageId, final int status,
+            final int rawStatus, final String conversationId, final String participantId,
+            final int statusIfFailed, final int subId, final String transactionId) {
+        Assert.notNull(messageId);
+        Assert.notNull(conversationId);
+        Assert.notNull(participantId);
+
+        final ProcessDownloadedMmsAction action = new ProcessDownloadedMmsAction();
+        final Bundle params = action.actionParameters;
+        params.putBoolean(KEY_DOWNLOADED_BY_PLATFORM, false);
+        params.putString(KEY_MESSAGE_ID, messageId);
+        params.putInt(KEY_STATUS, status);
+        params.putInt(KEY_RAW_STATUS, rawStatus);
+        params.putString(KEY_CONVERSATION_ID, conversationId);
+        params.putString(KEY_PARTICIPANT_ID, participantId);
+        params.putInt(KEY_STATUS_IF_FAILED, statusIfFailed);
+        params.putInt(KEY_SUB_ID, subId);
+        params.putString(KEY_TRANSACTION_ID, transactionId);
+        action.start();
+    }
+
+    public static void sendDeferredRespStatus(final String messageId, final String transactionId,
+            final String contentLocation, final int subId) {
+        final ProcessDownloadedMmsAction action = new ProcessDownloadedMmsAction();
+        final Bundle params = action.actionParameters;
+        params.putString(KEY_MESSAGE_ID, messageId);
+        params.putString(KEY_TRANSACTION_ID, transactionId);
+        params.putString(KEY_CONTENT_LOCATION, contentLocation);
+        params.putBoolean(KEY_SEND_DEFERRED_RESP_STATUS, true);
+        params.putInt(KEY_SUB_ID, subId);
+        action.start();
+    }
+
+    private ProcessDownloadedMmsAction() {
+        // Callers must use one of the static methods above
+    }
+
+    @Override
+    protected Object executeAction() {
+        // Fire up the background worker
+        requestBackgroundWork();
+        return null;
+    }
+
+    @Override
+    protected Bundle doBackgroundWork() throws DataModelException {
+        final Context context = Factory.get().getApplicationContext();
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
+        final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION);
+        final boolean sendDeferredRespStatus =
+                actionParameters.getBoolean(KEY_SEND_DEFERRED_RESP_STATUS, false);
+
+        // Send a response indicating that auto-download failed
+        if (sendDeferredRespStatus) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "DownloadMmsAction: Auto-download of message " + messageId
+                        + " failed; sending DEFERRED NotifyRespInd");
+            }
+            MmsUtils.sendNotifyResponseForMmsDownload(
+                    context,
+                    subId,
+                    MmsUtils.stringToBytes(transactionId, "UTF-8"),
+                    contentLocation,
+                    PduHeaders.STATUS_DEFERRED);
+            return null;
+        }
+
+        // Processing a real MMS download
+        final boolean downloadedByPlatform = actionParameters.getBoolean(
+                KEY_DOWNLOADED_BY_PLATFORM);
+
+        final int status;
+        int rawStatus = MmsUtils.PDU_HEADER_VALUE_UNDEFINED;
+        Uri mmsUri = null;
+
+        if (downloadedByPlatform) {
+            final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
+            if (resultCode == Activity.RESULT_OK) {
+                final Uri contentUri = actionParameters.getParcelable(KEY_CONTENT_URI);
+                final File downloadedFile = MmsFileProvider.getFile(contentUri);
+                byte[] downloadedData = null;
+                try {
+                    downloadedData = Files.toByteArray(downloadedFile);
+                } catch (final FileNotFoundException e) {
+                    LogUtil.e(TAG, "ProcessDownloadedMmsAction: MMS download file not found: "
+                            + downloadedFile.getAbsolutePath());
+                } catch (final IOException e) {
+                    LogUtil.e(TAG, "ProcessDownloadedMmsAction: Error reading MMS download file: "
+                            + downloadedFile.getAbsolutePath(), e);
+                }
+
+                // Can delete the temp file now
+                if (downloadedFile.exists()) {
+                    downloadedFile.delete();
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "ProcessDownloadedMmsAction: Deleted temp file with "
+                                + "downloaded MMS pdu: " + downloadedFile.getAbsolutePath());
+                    }
+                }
+
+                if (downloadedData != null) {
+                    final RetrieveConf retrieveConf =
+                            MmsSender.parseRetrieveConf(downloadedData, subId);
+                    if (MmsUtils.isDumpMmsEnabled()) {
+                        MmsUtils.dumpPdu(downloadedData, retrieveConf);
+                    }
+                    if (retrieveConf != null) {
+                        // Insert the downloaded MMS into telephony
+                        final Uri notificationUri = actionParameters.getParcelable(
+                                KEY_NOTIFICATION_URI);
+                        final String subPhoneNumber = actionParameters.getString(
+                                KEY_SUB_PHONE_NUMBER);
+                        final boolean autoDownload = actionParameters.getBoolean(
+                                KEY_AUTO_DOWNLOAD);
+                        final long receivedTimestampInSeconds =
+                                actionParameters.getLong(KEY_RECEIVED_TIMESTAMP);
+                        final long expiry = actionParameters.getLong(KEY_EXPIRY);
+
+                        // Inform sync we're adding a message to telephony
+                        final SyncManager syncManager = DataModel.get().getSyncManager();
+                        syncManager.onNewMessageInserted(receivedTimestampInSeconds * 1000L);
+
+                        final MmsUtils.StatusPlusUri result =
+                                MmsUtils.insertDownloadedMessageAndSendResponse(context,
+                                        notificationUri, subId, subPhoneNumber, transactionId,
+                                        contentLocation, autoDownload, receivedTimestampInSeconds,
+                                        expiry, retrieveConf);
+                        status = result.status;
+                        rawStatus = result.rawStatus;
+                        mmsUri = result.uri;
+                    } else {
+                        // Invalid response PDU
+                        status = MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+                    }
+                } else {
+                    // Failed to read download file
+                    status = MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+                }
+            } else {
+                LogUtil.w(TAG, "ProcessDownloadedMmsAction: Platform returned error resultCode: "
+                        + resultCode);
+                final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
+                status = MmsSender.getErrorResultStatus(resultCode, httpStatusCode);
+            }
+        } else {
+            // Message was already processed by the internal API, or the download action failed.
+            // In either case, we just need to copy the status to the response bundle.
+            status = actionParameters.getInt(KEY_STATUS);
+            rawStatus = actionParameters.getInt(KEY_RAW_STATUS);
+            mmsUri = actionParameters.getParcelable(KEY_MMS_URI);
+        }
+
+        final Bundle response = new Bundle();
+        response.putInt(BUNDLE_REQUEST_STATUS, status);
+        response.putInt(BUNDLE_RAW_TELEPHONY_STATUS, rawStatus);
+        response.putParcelable(BUNDLE_MMS_URI, mmsUri);
+        return response;
+    }
+
+    @Override
+    protected Object processBackgroundResponse(final Bundle response) {
+        if (response == null) {
+            // No message download to process; doBackgroundWork sent a notify deferred response
+            Assert.isTrue(actionParameters.getBoolean(KEY_SEND_DEFERRED_RESP_STATUS));
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(
+                    true /* failed */, this);
+            return null;
+        }
+
+        final int status = response.getInt(BUNDLE_REQUEST_STATUS);
+        final int rawStatus = response.getInt(BUNDLE_RAW_TELEPHONY_STATUS);
+        final Uri messageUri = response.getParcelable(BUNDLE_MMS_URI);
+        final boolean autoDownload = actionParameters.getBoolean(KEY_AUTO_DOWNLOAD);
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+
+        // Do post-processing on downloaded message
+        final MessageData message = processResult(status, rawStatus, messageUri);
+
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        // If we were trying to auto-download but have failed need to send the deferred response
+        final boolean needToSendDeferredResp =
+                autoDownload && (status == MmsUtils.MMS_REQUEST_MANUAL_RETRY);
+        if (needToSendDeferredResp) {
+            final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
+            final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION);
+            sendDeferredRespStatus(messageId, transactionId, contentLocation, subId);
+        }
+
+        if (autoDownload) {
+            final DatabaseWrapper db = DataModel.get().getDatabase();
+            MessageData toastMessage = message;
+            if (toastMessage == null) {
+                // If the downloaded failed (message is null), then we should announce the
+                // receiving of the wap push message. Load the wap push message here instead.
+                toastMessage = BugleDatabaseOperations.readMessageData(db, messageId);
+            }
+            if (toastMessage != null) {
+                final ParticipantData sender = ParticipantData.getFromId(
+                        db, toastMessage.getParticipantId());
+                BugleActionToasts.onMessageReceived(
+                        toastMessage.getConversationId(), sender, toastMessage);
+            }
+        } else {
+            final boolean success = message != null && status == MmsUtils.MMS_REQUEST_SUCCEEDED;
+            BugleActionToasts.onSendMessageOrManualDownloadActionCompleted(
+                    // If download failed, use the wap push message's conversation instead
+                    success ? message.getConversationId()
+                            : actionParameters.getString(KEY_CONVERSATION_ID),
+                    success, status, false/*isSms*/, subId, false /*isSend*/);
+        }
+
+        final boolean failed = (messageUri == null);
+        // Scheduling pending messages. If auto downloading is failed and it needs to send the
+        // deferred response, Skip it here and it will be scheduled after sending the response.
+        if (!needToSendDeferredResp) {
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(failed, this);
+        }
+        if (failed) {
+            BugleNotifications.update(false, BugleNotifications.UPDATE_ERRORS);
+        }
+
+        return message;
+    }
+
+    @Override
+    protected Object processBackgroundFailure() {
+        if (actionParameters.getBoolean(KEY_SEND_DEFERRED_RESP_STATUS)) {
+            // We can early-out for these failures. processResult is only designed to handle
+            // post-processing of MMS downloads (whether successful or not).
+            LogUtil.w(TAG,
+                    "ProcessDownloadedMmsAction: Exception while sending deferred NotifyRespInd");
+            return null;
+        }
+
+        // Background worker threw an exception; require manual retry
+        processResult(MmsUtils.MMS_REQUEST_MANUAL_RETRY, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
+                null /* mmsUri */);
+
+        ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(true /* failed */,
+                this);
+
+        return null;
+    }
+
+    private MessageData processResult(final int status, final int rawStatus, final Uri mmsUri) {
+        final Context context = Factory.get().getApplicationContext();
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final Uri mmsNotificationUri = actionParameters.getParcelable(KEY_NOTIFICATION_URI);
+        final String notificationConversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final String notificationParticipantId = actionParameters.getString(KEY_PARTICIPANT_ID);
+        final int statusIfFailed = actionParameters.getInt(KEY_STATUS_IF_FAILED);
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        Assert.notNull(messageId);
+
+        LogUtil.i(TAG, "ProcessDownloadedMmsAction: Processed MMS download of message " + messageId
+                + "; status is " + MmsUtils.getRequestStatusDescription(status));
+
+        DatabaseMessages.MmsMessage mms = null;
+        if (status == MmsUtils.MMS_REQUEST_SUCCEEDED && mmsUri != null) {
+            // Delete the initial M-Notification.ind from telephony
+            SqliteWrapper.delete(context, context.getContentResolver(),
+                    mmsNotificationUri, null, null);
+
+            // Read the sent MMS from the telephony provider
+            mms = MmsUtils.loadMms(mmsUri);
+        }
+
+        boolean messageInFocusedConversation = false;
+        boolean messageInObservableConversation = false;
+        String conversationId = null;
+        MessageData message = null;
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            if (mms != null) {
+                final ParticipantData self = ParticipantData.getSelfParticipant(mms.getSubId());
+                final String selfId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+
+                final List<String> recipients = MmsUtils.getRecipientsByThread(mms.mThreadId);
+                String from = MmsUtils.getMmsSender(recipients, mms.getUri());
+                if (from == null) {
+                    LogUtil.w(TAG,
+                            "Downloaded an MMS without sender address; using unknown sender.");
+                    from = ParticipantData.getUnknownSenderDestination();
+                }
+                final ParticipantData sender = ParticipantData.getFromRawPhoneBySimLocale(from,
+                        subId);
+                final String senderParticipantId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, sender);
+                if (!senderParticipantId.equals(notificationParticipantId)) {
+                    LogUtil.e(TAG, "ProcessDownloadedMmsAction: Downloaded MMS message "
+                            + messageId + " has different sender (participantId = "
+                            + senderParticipantId + ") than notification ("
+                            + notificationParticipantId + ")");
+                }
+                final boolean blockedSender = BugleDatabaseOperations.isBlockedDestination(
+                        db, sender.getNormalizedDestination());
+                conversationId = BugleDatabaseOperations.getOrCreateConversationFromThreadId(db,
+                        mms.mThreadId, blockedSender, subId);
+
+                messageInFocusedConversation =
+                        DataModel.get().isFocusedConversation(conversationId);
+                messageInObservableConversation =
+                        DataModel.get().isNewMessageObservable(conversationId);
+
+                // TODO: Also write these values to the telephony provider
+                mms.mRead = messageInFocusedConversation;
+                mms.mSeen = messageInObservableConversation;
+
+                // Translate to our format
+                message = MmsUtils.createMmsMessage(mms, conversationId, senderParticipantId,
+                        selfId, MessageData.BUGLE_STATUS_INCOMING_COMPLETE);
+                // Update image sizes.
+                message.updateSizesForImageParts();
+                // Inform sync that message has been added at local received timestamp
+                final SyncManager syncManager = DataModel.get().getSyncManager();
+                syncManager.onNewMessageInserted(message.getReceivedTimeStamp());
+                final MessageData current = BugleDatabaseOperations.readMessageData(db, messageId);
+                if (current == null) {
+                    LogUtil.w(TAG, "Message deleted prior to update");
+                    BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+                } else {
+                    // Overwrite existing notification message
+                    message.updateMessageId(messageId);
+                    // Write message
+                    BugleDatabaseOperations.updateMessageInTransaction(db, message);
+                }
+
+                if (!TextUtils.equals(notificationConversationId, conversationId)) {
+                    // If this is a group conversation, the message is moved. So the original
+                    // 1v1 conversation (as referenced by notificationConversationId) could
+                    // be left with no non-draft message. Delete the conversation if that
+                    // happens. See the comment for the method below for why we need to do this.
+                    if (!BugleDatabaseOperations.deleteConversationIfEmptyInTransaction(
+                            db, notificationConversationId)) {
+                        BugleDatabaseOperations.maybeRefreshConversationMetadataInTransaction(
+                                db, notificationConversationId, messageId,
+                                true /*shouldAutoSwitchSelfId*/, blockedSender /*keepArchived*/);
+                    }
+                }
+
+                BugleDatabaseOperations.refreshConversationMetadataInTransaction(db, conversationId,
+                        true /*shouldAutoSwitchSelfId*/, blockedSender /*keepArchived*/);
+            } else {
+                messageInFocusedConversation =
+                        DataModel.get().isFocusedConversation(notificationConversationId);
+
+                // Default to retry status unless status indicates otherwise
+                int bugleStatus = statusIfFailed;
+                if (status == MmsUtils.MMS_REQUEST_MANUAL_RETRY) {
+                    bugleStatus = MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED;
+                } else if (status == MmsUtils.MMS_REQUEST_NO_RETRY) {
+                    bugleStatus = MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE;
+                }
+                DownloadMmsAction.updateMessageStatus(mmsNotificationUri, messageId,
+                        notificationConversationId, bugleStatus, rawStatus);
+
+                // Log MMS download failed
+                final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
+                final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
+
+                // Just in case this was the latest message update the summary data
+                BugleDatabaseOperations.refreshConversationMetadataInTransaction(db,
+                        notificationConversationId, true /*shouldAutoSwitchSelfId*/,
+                        false /*keepArchived*/);
+            }
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        if (mmsUri != null) {
+            // Update mms table with read status now we know the conversation id
+            final ContentValues values = new ContentValues(1);
+            values.put(Mms.READ, messageInFocusedConversation);
+            SqliteWrapper.update(context, context.getContentResolver(), mmsUri, values,
+                    null, null);
+        }
+
+        // Show a notification to let the user know a new message has arrived
+        BugleNotifications.update(false /*silent*/, conversationId, BugleNotifications.UPDATE_ALL);
+
+        // Messages may have changed in two conversations
+        if (conversationId != null) {
+            MessagingContentProvider.notifyMessagesChanged(conversationId);
+        }
+        MessagingContentProvider.notifyMessagesChanged(notificationConversationId);
+        MessagingContentProvider.notifyPartsChanged();
+
+        return message;
+    }
+
+    private ProcessDownloadedMmsAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ProcessDownloadedMmsAction> CREATOR
+            = new Parcelable.Creator<ProcessDownloadedMmsAction>() {
+        @Override
+        public ProcessDownloadedMmsAction createFromParcel(final Parcel in) {
+            return new ProcessDownloadedMmsAction(in);
+        }
+
+        @Override
+        public ProcessDownloadedMmsAction[] newArray(final int size) {
+            return new ProcessDownloadedMmsAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ProcessPendingMessagesAction.java b/src/com/android/messaging/datamodel/action/ProcessPendingMessagesAction.java
new file mode 100644
index 0000000..a897ce0
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ProcessPendingMessagesAction.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.ServiceState;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelImpl;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.ConnectivityUtil;
+import com.android.messaging.util.ConnectivityUtil.ConnectivityListener;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Action used to lookup any messages in the pending send/download state and either fail them or
+ * retry their action based on subscriptions. This action only initiates one retry at a time for
+ * both sending/downloading. Further retries should be triggered by successful sending/downloading
+ * of a message, network status change or exponential backoff timer.
+ */
+public class ProcessPendingMessagesAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    // PENDING_INTENT_BASE_REQUEST_CODE + subId(-1 for pre-L_MR1) is used per subscription uniquely.
+    private static final int PENDING_INTENT_BASE_REQUEST_CODE = 103;
+
+    private static final String KEY_SUB_ID = "sub_id";
+
+    public static void processFirstPendingMessage() {
+        PhoneUtils.forEachActiveSubscription(new PhoneUtils.SubscriptionRunnable() {
+            @Override
+            public void runForSubscription(final int subId) {
+                // Clear any pending alarms or connectivity events
+                unregister(subId);
+                // Clear retry count
+                setRetry(0, subId);
+                // Start action
+                final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction();
+                action.actionParameters.putInt(KEY_SUB_ID, subId);
+                action.start();
+            }
+        });
+    }
+
+    public static void scheduleProcessPendingMessagesAction(final boolean failed,
+            final Action processingAction) {
+        final int subId = processingAction.actionParameters
+                .getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        LogUtil.i(TAG, "ProcessPendingMessagesAction: Scheduling pending messages"
+                + (failed ? "(message failed)" : "") + " for subId " + subId);
+        // Can safely clear any pending alarms or connectivity events as either an action
+        // is currently running or we will run now or register if pending actions possible.
+        unregister(subId);
+
+        final boolean isDefaultSmsApp = PhoneUtils.getDefault().isDefaultSmsApp();
+        boolean scheduleAlarm = false;
+        // If message succeeded and if Bugle is default SMS app just carry on with next message
+        if (!failed && isDefaultSmsApp) {
+            // Clear retry attempt count as something just succeeded
+            setRetry(0, subId);
+
+            // Lookup and queue next message for each sending/downloading for immediate processing
+            // by background worker. If there are no pending messages, this will do nothing and
+            // return true.
+            final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction();
+            if (action.queueActions(processingAction)) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    if (processingAction.hasBackgroundActions()) {
+                        LogUtil.v(TAG, "ProcessPendingMessagesAction: Action queued");
+                    } else {
+                        LogUtil.v(TAG, "ProcessPendingMessagesAction: No actions to queue");
+                    }
+                }
+                // Have queued next action if needed, nothing more to do
+                return;
+            }
+            // In case of error queuing schedule a retry
+            scheduleAlarm = true;
+            LogUtil.w(TAG, "ProcessPendingMessagesAction: Action failed to queue; retrying");
+        }
+        if (getHavePendingMessages(subId) || scheduleAlarm) {
+            // Still have a pending message that needs to be queued for processing
+            final ConnectivityListener listener = new ConnectivityListener() {
+                @Override
+                public void onPhoneStateChanged(final int serviceState) {
+                    if (serviceState == ServiceState.STATE_IN_SERVICE) {
+                        LogUtil.i(TAG, "ProcessPendingMessagesAction: Now connected for subId "
+                                + subId + ", starting action");
+
+                        // Clear any pending alarms or connectivity events but leave attempt count
+                        // alone
+                        unregister(subId);
+
+                        // Start action
+                        final ProcessPendingMessagesAction action =
+                                new ProcessPendingMessagesAction();
+                        action.actionParameters.putInt(KEY_SUB_ID, subId);
+                        action.start();
+                    }
+                }
+            };
+            // Read and increment attempt number from shared prefs
+            final int retryAttempt = getNextRetry(subId);
+            register(listener, retryAttempt, subId);
+        } else {
+            // No more pending messages (presumably the message that failed has expired) or it
+            // may be possible that a send and a download are already in process.
+            // Clear retry attempt count.
+            // TODO Might be premature if send and download in process...
+            // but worst case means we try to send a bit more often.
+            setRetry(0, subId);
+            LogUtil.i(TAG, "ProcessPendingMessagesAction: No more pending messages");
+        }
+    }
+
+    private static void register(final ConnectivityListener listener, final int retryAttempt,
+            int subId) {
+        int retryNumber = retryAttempt;
+
+        // Register to be notified about connectivity changes
+        ConnectivityUtil connectivityUtil = DataModelImpl.getConnectivityUtil(subId);
+        if (connectivityUtil != null) {
+            connectivityUtil.register(listener);
+        }
+
+        final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction();
+        action.actionParameters.putInt(KEY_SUB_ID, subId);
+        final long initialBackoffMs = BugleGservices.get().getLong(
+                BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS,
+                BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT);
+        final long maxDelayMs = BugleGservices.get().getLong(
+                BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS,
+                BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT);
+        long delayMs;
+        long nextDelayMs = initialBackoffMs;
+        do {
+            delayMs = nextDelayMs;
+            retryNumber--;
+            nextDelayMs = delayMs * 2;
+        }
+        while (retryNumber > 0 && nextDelayMs < maxDelayMs);
+
+        LogUtil.i(TAG, "ProcessPendingMessagesAction: Registering for retry #" + retryAttempt
+                + " in " + delayMs + " ms for subId " + subId);
+
+        action.schedule(PENDING_INTENT_BASE_REQUEST_CODE + subId, delayMs);
+    }
+
+    private static void unregister(final int subId) {
+        // Clear any pending alarms or connectivity events
+        ConnectivityUtil connectivityUtil = DataModelImpl.getConnectivityUtil(subId);
+        if (connectivityUtil != null) {
+            connectivityUtil.unregister();
+        }
+
+        final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction();
+        action.schedule(PENDING_INTENT_BASE_REQUEST_CODE + subId, Long.MAX_VALUE);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "ProcessPendingMessagesAction: Unregistering for connectivity changed "
+                    + "events and clearing scheduled alarm for subId " + subId);
+        }
+    }
+
+    private static void setRetry(final int retryAttempt, int subId) {
+        final BuglePrefs prefs = Factory.get().getSubscriptionPrefs(subId);
+        prefs.putInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, retryAttempt);
+    }
+
+    private static int getNextRetry(int subId) {
+        final BuglePrefs prefs = Factory.get().getSubscriptionPrefs(subId);
+        final int retryAttempt =
+                prefs.getInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, 0) + 1;
+        prefs.putInt(BuglePrefsKeys.PROCESS_PENDING_MESSAGES_RETRY_COUNT, retryAttempt);
+        return retryAttempt;
+    }
+
+    private ProcessPendingMessagesAction() {
+    }
+
+    /**
+     * Read from the DB and determine if there are any messages we should process
+     *
+     * @param subId the subId
+     * @return true if we have pending messages
+     */
+    private static boolean getHavePendingMessages(final int subId) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final long now = System.currentTimeMillis();
+        final String selfId = ParticipantData.getParticipantId(db, subId);
+        if (selfId == null) {
+            // This could be happened before refreshing participant.
+            LogUtil.w(TAG, "ProcessPendingMessagesAction: selfId is null for subId " + subId);
+            return false;
+        }
+
+        final String toSendMessageId = findNextMessageToSend(db, now, selfId);
+        if (toSendMessageId != null) {
+            return true;
+        } else {
+            final String toDownloadMessageId = findNextMessageToDownload(db, now, selfId);
+            if (toDownloadMessageId != null) {
+                return true;
+            }
+        }
+        // Messages may be in the process of sending/downloading even when there are no pending
+        // messages...
+        return false;
+    }
+
+    /**
+     * Queue any pending actions
+     *
+     * @param actionState
+     * @return true if action queued (or no actions to queue) else false
+     */
+    private boolean queueActions(final Action processingAction) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final long now = System.currentTimeMillis();
+        boolean succeeded = true;
+        final int subId = processingAction.actionParameters
+                .getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        LogUtil.i(TAG, "ProcessPendingMessagesAction: Start queueing for subId " + subId);
+
+        final String selfId = ParticipantData.getParticipantId(db, subId);
+        if (selfId == null) {
+            // This could be happened before refreshing participant.
+            LogUtil.w(TAG, "ProcessPendingMessagesAction: selfId is null");
+            return false;
+        }
+
+        // Will queue no more than one message to send plus one message to download
+        // This keeps outgoing messages "in order" but allow downloads to happen even if sending
+        // gets blocked until messages time out. Manual resend bumps messages to head of queue.
+        final String toSendMessageId = findNextMessageToSend(db, now, selfId);
+        final String toDownloadMessageId = findNextMessageToDownload(db, now, selfId);
+        if (toSendMessageId != null) {
+            LogUtil.i(TAG, "ProcessPendingMessagesAction: Queueing message " + toSendMessageId
+                    + " for sending");
+            // This could queue nothing
+            if (!SendMessageAction.queueForSendInBackground(toSendMessageId, processingAction)) {
+                LogUtil.w(TAG, "ProcessPendingMessagesAction: Failed to queue message "
+                        + toSendMessageId + " for sending");
+                succeeded = false;
+            }
+        }
+        if (toDownloadMessageId != null) {
+            LogUtil.i(TAG, "ProcessPendingMessagesAction: Queueing message " + toDownloadMessageId
+                    + " for download");
+            // This could queue nothing
+            if (!DownloadMmsAction.queueMmsForDownloadInBackground(toDownloadMessageId,
+                    processingAction)) {
+                LogUtil.w(TAG, "ProcessPendingMessagesAction: Failed to queue message "
+                        + toDownloadMessageId + " for download");
+                succeeded = false;
+            }
+        }
+        if (toSendMessageId == null && toDownloadMessageId == null) {
+            LogUtil.i(TAG, "ProcessPendingMessagesAction: No messages to send or download");
+        }
+        return succeeded;
+    }
+
+    @Override
+    protected Object executeAction() {
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        // If triggered by alarm will not have unregistered yet
+        unregister(subId);
+
+        if (PhoneUtils.getDefault().isDefaultSmsApp()) {
+            if (!queueActions(this)) {
+                LogUtil.v(TAG, "ProcessPendingMessagesAction: rescheduling");
+                // TODO: Need to clear retry count here?
+                scheduleProcessPendingMessagesAction(true /* failed */, this);
+            }
+        } else {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "ProcessPendingMessagesAction: Not default SMS app; rescheduling");
+            }
+            scheduleProcessPendingMessagesAction(true /* failed */, this);
+        }
+
+        return null;
+    }
+
+    private static String findNextMessageToSend(final DatabaseWrapper db, final long now,
+            final String selfId) {
+        String toSendMessageId = null;
+        Cursor cursor = null;
+        int sendingCnt = 0;
+        int pendingCnt = 0;
+        int failedCnt = 0;
+        db.beginTransaction();
+        try {
+            // First check to see if we have any messages already sending
+            sendingCnt = (int) db.queryNumEntries(DatabaseHelper.MESSAGES_TABLE,
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?) AND "
+                    + DatabaseHelper.MessageColumns.SELF_PARTICIPANT_ID + " =? ",
+                    new String[] {
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_SENDING),
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_RESENDING),
+                        selfId}
+                    );
+
+            // Look for messages we could send
+            cursor = db.query(DatabaseHelper.MESSAGES_TABLE,
+                    MessageData.getProjection(),
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?) AND "
+                    + DatabaseHelper.MessageColumns.SELF_PARTICIPANT_ID + " =? ",
+                    new String[] {
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND),
+                        Integer.toString(MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY),
+                        selfId
+                    },
+                    null,
+                    null,
+                    DatabaseHelper.MessageColumns.RECEIVED_TIMESTAMP + " ASC");
+            pendingCnt = cursor.getCount();
+
+            final ContentValues values = new ContentValues();
+            values.put(DatabaseHelper.MessageColumns.STATUS,
+                    MessageData.BUGLE_STATUS_OUTGOING_FAILED);
+
+            // Prior to L_MR1, isActiveSubscription is true always
+            boolean isActiveSubscription = true;
+            if (OsUtil.isAtLeastL_MR1()) {
+                final ParticipantData messageSelf =
+                        BugleDatabaseOperations.getExistingParticipant(db, selfId);
+                if (messageSelf == null || !messageSelf.isActiveSubscription()) {
+                    isActiveSubscription = false;
+                }
+            }
+            while (cursor.moveToNext()) {
+                final MessageData message = new MessageData();
+                message.bind(cursor);
+
+                // Mark this message as failed if the message's self is inactive or the message is
+                // outside of resend window
+                if (!isActiveSubscription || !message.getInResendWindow(now)) {
+                    failedCnt++;
+
+                    // Mark message as failed
+                    BugleDatabaseOperations.updateMessageRow(db, message.getMessageId(), values);
+                    MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+                } else {
+                    // If no messages currently sending
+                    if (sendingCnt == 0) {
+                        // Send this message
+                        toSendMessageId = message.getMessageId();
+                    }
+                    break;
+                }
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "ProcessPendingMessagesAction: "
+                    + sendingCnt + " messages already sending, "
+                    + pendingCnt + " messages to send, "
+                    + failedCnt + " failed messages");
+        }
+
+        return toSendMessageId;
+    }
+
+    private static String findNextMessageToDownload(final DatabaseWrapper db, final long now,
+            final String selfId) {
+        String toDownloadMessageId = null;
+        Cursor cursor = null;
+        int downloadingCnt = 0;
+        int pendingCnt = 0;
+        db.beginTransaction();
+        try {
+            // First check if we have any messages already downloading
+            downloadingCnt = (int) db.queryNumEntries(DatabaseHelper.MESSAGES_TABLE,
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?) AND "
+                    + DatabaseHelper.MessageColumns.SELF_PARTICIPANT_ID + " =?",
+                    new String[] {
+                        Integer.toString(MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING),
+                        Integer.toString(MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING),
+                        selfId
+                    });
+
+            // TODO: This query is not actually needed if downloadingCnt == 0.
+            cursor = db.query(DatabaseHelper.MESSAGES_TABLE,
+                    MessageData.getProjection(),
+                    DatabaseHelper.MessageColumns.STATUS + " IN (?, ?) AND "
+                    + DatabaseHelper.MessageColumns.SELF_PARTICIPANT_ID + " =? ",
+                    new String[]{
+                        Integer.toString(MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD),
+                        Integer.toString(
+                                MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD),
+                        selfId
+                    },
+                    null,
+                    null,
+                    DatabaseHelper.MessageColumns.RECEIVED_TIMESTAMP + " ASC");
+
+            pendingCnt = cursor.getCount();
+
+            // If no messages are currently downloading and there is a download pending,
+            // queue the download of the oldest pending message.
+            if (downloadingCnt == 0 && cursor.moveToNext()) {
+                // Always start the next pending message. We will check if a download has
+                // expired in DownloadMmsAction and mark message failed there.
+                final MessageData message = new MessageData();
+                message.bind(cursor);
+                toDownloadMessageId = message.getMessageId();
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "ProcessPendingMessagesAction: "
+                    + downloadingCnt + " messages already downloading, "
+                    + pendingCnt + " messages to download");
+        }
+
+        return toDownloadMessageId;
+    }
+
+    private ProcessPendingMessagesAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ProcessPendingMessagesAction> CREATOR
+            = new Parcelable.Creator<ProcessPendingMessagesAction>() {
+        @Override
+        public ProcessPendingMessagesAction createFromParcel(final Parcel in) {
+            return new ProcessPendingMessagesAction(in);
+        }
+
+        @Override
+        public ProcessPendingMessagesAction[] newArray(final int size) {
+            return new ProcessPendingMessagesAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ProcessSentMessageAction.java b/src/com/android/messaging/datamodel/action/ProcessSentMessageAction.java
new file mode 100644
index 0000000..489a0f1
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ProcessSentMessageAction.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SmsManager;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MmsFileProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.pdu.SendConf;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.sms.MmsSender;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+* Update message status to reflect success or failure
+* Can also update the message itself if a "final" message is now available from telephony db
+*/
+public class ProcessSentMessageAction extends Action {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    // These are always set
+    private static final String KEY_SMS = "is_sms";
+    private static final String KEY_SENT_BY_PLATFORM = "sent_by_platform";
+
+    // These are set when we're processing a message sent by the user. They are null for messages
+    // sent automatically (e.g. a NotifyRespInd/AcknowledgeInd sent in response to a download).
+    private static final String KEY_MESSAGE_ID = "message_id";
+    private static final String KEY_MESSAGE_URI = "message_uri";
+    private static final String KEY_UPDATED_MESSAGE_URI = "updated_message_uri";
+    private static final String KEY_SUB_ID = "sub_id";
+
+    // These are set for messages sent by the platform (L+)
+    public static final String KEY_RESULT_CODE = "result_code";
+    public static final String KEY_HTTP_STATUS_CODE = "http_status_code";
+    private static final String KEY_CONTENT_URI = "content_uri";
+    private static final String KEY_RESPONSE = "response";
+    private static final String KEY_RESPONSE_IMPORTANT = "response_important";
+
+    // These are set for messages we sent ourself (legacy), or which we fast-failed before sending.
+    private static final String KEY_STATUS = "status";
+    private static final String KEY_RAW_STATUS = "raw_status";
+
+    // This is called when MMS lib API returns via PendingIntent
+    public static void processMmsSent(final int resultCode, final Uri messageUri,
+            final Bundle extras) {
+        final ProcessSentMessageAction action = new ProcessSentMessageAction();
+        final Bundle params = action.actionParameters;
+        params.putBoolean(KEY_SMS, false);
+        params.putBoolean(KEY_SENT_BY_PLATFORM, true);
+        params.putString(KEY_MESSAGE_ID, extras.getString(SendMessageAction.EXTRA_MESSAGE_ID));
+        params.putParcelable(KEY_MESSAGE_URI, messageUri);
+        params.putParcelable(KEY_UPDATED_MESSAGE_URI,
+                extras.getParcelable(SendMessageAction.EXTRA_UPDATED_MESSAGE_URI));
+        params.putInt(KEY_SUB_ID,
+                extras.getInt(SendMessageAction.KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID));
+        params.putInt(KEY_RESULT_CODE, resultCode);
+        params.putInt(KEY_HTTP_STATUS_CODE, extras.getInt(SmsManager.EXTRA_MMS_HTTP_STATUS, 0));
+        params.putParcelable(KEY_CONTENT_URI,
+                extras.getParcelable(SendMessageAction.EXTRA_CONTENT_URI));
+        params.putByteArray(KEY_RESPONSE, extras.getByteArray(SmsManager.EXTRA_MMS_DATA));
+        params.putBoolean(KEY_RESPONSE_IMPORTANT,
+                extras.getBoolean(SendMessageAction.EXTRA_RESPONSE_IMPORTANT));
+        action.start();
+    }
+
+    public static void processMessageSentFastFailed(final String messageId,
+            final Uri messageUri, final Uri updatedMessageUri, final int subId, final boolean isSms,
+            final int status, final int rawStatus, final int resultCode) {
+        final ProcessSentMessageAction action = new ProcessSentMessageAction();
+        final Bundle params = action.actionParameters;
+        params.putBoolean(KEY_SMS, isSms);
+        params.putBoolean(KEY_SENT_BY_PLATFORM, false);
+        params.putString(KEY_MESSAGE_ID, messageId);
+        params.putParcelable(KEY_MESSAGE_URI, messageUri);
+        params.putParcelable(KEY_UPDATED_MESSAGE_URI, updatedMessageUri);
+        params.putInt(KEY_SUB_ID, subId);
+        params.putInt(KEY_STATUS, status);
+        params.putInt(KEY_RAW_STATUS, rawStatus);
+        params.putInt(KEY_RESULT_CODE, resultCode);
+        action.start();
+    }
+
+    private ProcessSentMessageAction() {
+        // Callers must use one of the static methods above
+    }
+
+    /**
+    * Update message status to reflect success or failure
+    * Can also update the message itself if a "final" message is now available from telephony db
+    */
+    @Override
+    protected Object executeAction() {
+        final Context context = Factory.get().getApplicationContext();
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final Uri messageUri = actionParameters.getParcelable(KEY_MESSAGE_URI);
+        final Uri updatedMessageUri = actionParameters.getParcelable(KEY_UPDATED_MESSAGE_URI);
+        final boolean isSms = actionParameters.getBoolean(KEY_SMS);
+        final boolean sentByPlatform = actionParameters.getBoolean(KEY_SENT_BY_PLATFORM);
+
+        int status = actionParameters.getInt(KEY_STATUS, MmsUtils.MMS_REQUEST_MANUAL_RETRY);
+        int rawStatus = actionParameters.getInt(KEY_RAW_STATUS,
+                MmsUtils.PDU_HEADER_VALUE_UNDEFINED);
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+
+        if (sentByPlatform) {
+            // Delete temporary file backing the contentUri passed to MMS service
+            final Uri contentUri = actionParameters.getParcelable(KEY_CONTENT_URI);
+            Assert.isTrue(contentUri != null);
+            final File tempFile = MmsFileProvider.getFile(contentUri);
+            long messageSize = 0;
+            if (tempFile.exists()) {
+                messageSize = tempFile.length();
+                tempFile.delete();
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "ProcessSentMessageAction: Deleted temp file with outgoing "
+                            + "MMS pdu: " + contentUri);
+                }
+            }
+
+            final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
+            final boolean responseImportant = actionParameters.getBoolean(KEY_RESPONSE_IMPORTANT);
+            if (resultCode == Activity.RESULT_OK) {
+                if (responseImportant) {
+                    // Get the status from the response PDU and update telephony
+                    final byte[] response = actionParameters.getByteArray(KEY_RESPONSE);
+                    final SendConf sendConf = MmsSender.parseSendConf(response, subId);
+                    if (sendConf != null) {
+                        final MmsUtils.StatusPlusUri result =
+                                MmsUtils.updateSentMmsMessageStatus(context, messageUri, sendConf);
+                        status = result.status;
+                        rawStatus = result.rawStatus;
+                    }
+                }
+            } else {
+                String errorMsg = "ProcessSentMessageAction: Platform returned error resultCode: "
+                        + resultCode;
+                final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
+                if (httpStatusCode != 0) {
+                    errorMsg += (", HTTP status code: " + httpStatusCode);
+                }
+                LogUtil.w(TAG, errorMsg);
+                status = MmsSender.getErrorResultStatus(resultCode, httpStatusCode);
+
+                // Check for MMS messages that failed because they exceeded the maximum size,
+                // indicated by an I/O error from the platform.
+                if (resultCode == SmsManager.MMS_ERROR_IO_ERROR) {
+                    if (messageSize > MmsConfig.get(subId).getMaxMessageSize()) {
+                        rawStatus = MessageData.RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG;
+                    }
+                }
+            }
+        }
+        if (messageId != null) {
+            final int resultCode = actionParameters.getInt(KEY_RESULT_CODE);
+            final int httpStatusCode = actionParameters.getInt(KEY_HTTP_STATUS_CODE);
+            processResult(
+                    messageId, updatedMessageUri, status, rawStatus, isSms, this, subId,
+                    resultCode, httpStatusCode);
+        } else {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "ProcessSentMessageAction: No sent message to process (it was "
+                        + "probably a notify response for an MMS download)");
+            }
+        }
+        return null;
+    }
+
+    static void processResult(final String messageId, Uri updatedMessageUri, int status,
+            final int rawStatus, final boolean isSms, final Action processingAction,
+            final int subId, final int resultCode, final int httpStatusCode) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+        final MessageData originalMessage = message;
+        if (message == null) {
+            LogUtil.w(TAG, "ProcessSentMessageAction: Sent message " + messageId
+                    + " missing from local database");
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(
+                    true /* failed */, processingAction);
+            return;
+        }
+        final String conversationId = message.getConversationId();
+        if (updatedMessageUri != null) {
+            // Update message if we have newly written final message in the telephony db
+            final MessageData update = MmsUtils.readSendingMmsMessage(updatedMessageUri,
+                    conversationId, message.getParticipantId(), message.getSelfId());
+            if (update != null) {
+                // Set message Id of final message to that of the existing place holder.
+                update.updateMessageId(message.getMessageId());
+                // Update image sizes.
+                update.updateSizesForImageParts();
+                // Temp attachments are no longer needed
+                for (final MessagePartData part : message.getParts()) {
+                    part.destroySync();
+                }
+                message = update;
+                // processResult will rewrite the complete message as part of update
+            } else {
+                updatedMessageUri = null;
+                status = MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+                LogUtil.e(TAG, "ProcessSentMessageAction: Unable to read sending message");
+            }
+        }
+
+        final long timestamp = System.currentTimeMillis();
+        boolean failed;
+        if (status == MmsUtils.MMS_REQUEST_SUCCEEDED) {
+            message.markMessageSent(timestamp);
+            failed = false;
+        } else if (status == MmsUtils.MMS_REQUEST_AUTO_RETRY
+                && message.getInResendWindow(timestamp)) {
+            message.markMessageNotSent(timestamp);
+            message.setRawTelephonyStatus(rawStatus);
+            failed = false;
+        } else {
+            message.markMessageFailed(timestamp);
+            message.setRawTelephonyStatus(rawStatus);
+            message.setMessageSeen(false);
+            failed = true;
+        }
+
+        // We have special handling for when a message to an emergency number fails. In this case,
+        // we notify immediately of any failure (even if we auto-retry), and instruct the user to
+        // try calling the emergency number instead.
+        if (status != MmsUtils.MMS_REQUEST_SUCCEEDED) {
+            final ArrayList<String> recipients =
+                    BugleDatabaseOperations.getRecipientsForConversation(db, conversationId);
+            for (final String recipient : recipients) {
+                if (PhoneNumberUtils.isEmergencyNumber(recipient)) {
+                    BugleNotifications.notifyEmergencySmsFailed(recipient, conversationId);
+                    message.markMessageFailedEmergencyNumber(timestamp);
+                    failed = true;
+                    break;
+                }
+            }
+        }
+
+        // Update the message status and optionally refresh the message with final parts/values.
+        if (SendMessageAction.updateMessageAndStatus(isSms, message, updatedMessageUri, failed)) {
+            // We shouldn't show any notifications if we're not allowed to modify Telephony for
+            // this message.
+            if (failed) {
+                BugleNotifications.update(false, BugleNotifications.UPDATE_ERRORS);
+            }
+            BugleActionToasts.onSendMessageOrManualDownloadActionCompleted(
+                    conversationId, !failed, status, isSms, subId, true/*isSend*/);
+        }
+
+        LogUtil.i(TAG, "ProcessSentMessageAction: Done sending " + (isSms ? "SMS" : "MMS")
+                + " message " + message.getMessageId()
+                + " in conversation " + conversationId
+                + "; status is " + MmsUtils.getRequestStatusDescription(status));
+
+        // Whether we succeeded or failed we will check and maybe schedule some more work
+        ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(
+                status != MmsUtils.MMS_REQUEST_SUCCEEDED, processingAction);
+    }
+
+    private ProcessSentMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ProcessSentMessageAction> CREATOR
+            = new Parcelable.Creator<ProcessSentMessageAction>() {
+        @Override
+        public ProcessSentMessageAction createFromParcel(final Parcel in) {
+            return new ProcessSentMessageAction(in);
+        }
+
+        @Override
+        public ProcessSentMessageAction[] newArray(final int size) {
+            return new ProcessSentMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ReadDraftDataAction.java b/src/com/android/messaging/datamodel/action/ReadDraftDataAction.java
new file mode 100644
index 0000000..7ac646b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ReadDraftDataAction.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+public class ReadDraftDataAction extends Action implements Parcelable {
+
+    /**
+     * Interface for ReadDraftDataAction listeners
+     */
+    public interface ReadDraftDataActionListener {
+        @RunsOnMainThread
+        abstract void onReadDraftDataSucceeded(final ReadDraftDataAction action,
+                final Object data, final MessageData message,
+                final ConversationListItemData conversation);
+        @RunsOnMainThread
+        abstract void onReadDraftDataFailed(final ReadDraftDataAction action, final Object data);
+    }
+
+    /**
+     * Read draft message and associated data (with listener)
+     */
+    public static ReadDraftDataActionMonitor readDraftData(final String conversationId,
+            final MessageData incomingDraft, final Object data,
+            final ReadDraftDataActionListener listener) {
+        final ReadDraftDataActionMonitor monitor = new ReadDraftDataActionMonitor(data,
+                listener);
+        final ReadDraftDataAction action = new ReadDraftDataAction(conversationId,
+                incomingDraft, monitor.getActionKey());
+        action.start(monitor);
+        return monitor;
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversationId";
+    private static final String KEY_INCOMING_DRAFT = "draftMessage";
+
+    private ReadDraftDataAction(final String conversationId, final MessageData incomingDraft,
+            final String actionKey) {
+        super(actionKey);
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+        actionParameters.putParcelable(KEY_INCOMING_DRAFT, incomingDraft);
+    }
+
+    @VisibleForTesting
+    class DraftData {
+        public final MessageData message;
+        public final ConversationListItemData conversation;
+
+        DraftData(final MessageData message, final ConversationListItemData conversation) {
+            this.message = message;
+            this.conversation = conversation;
+        }
+    }
+
+    @Override
+    protected Object executeAction() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final MessageData incomingDraft = actionParameters.getParcelable(KEY_INCOMING_DRAFT);
+        final ConversationListItemData conversation =
+                ConversationListItemData.getExistingConversation(db, conversationId);
+        MessageData message = null;
+        if (conversation != null) {
+            if (incomingDraft == null) {
+                message = BugleDatabaseOperations.readDraftMessageData(db, conversationId,
+                        conversation.getSelfId());
+            }
+            if (message == null) {
+                message = MessageData.createDraftMessage(conversationId, conversation.getSelfId(),
+                        incomingDraft);
+                LogUtil.d(LogUtil.BUGLE_TAG, "ReadDraftMessage: created draft. "
+                        + "conversationId=" + conversationId
+                        + " selfId=" + conversation.getSelfId());
+            } else {
+                LogUtil.d(LogUtil.BUGLE_TAG, "ReadDraftMessage: read draft. "
+                        + "conversationId=" + conversationId
+                        + " selfId=" + conversation.getSelfId());
+            }
+            return new DraftData(message, conversation);
+        }
+        return null;
+    }
+
+    /**
+     * An operation that notifies a listener upon completion
+     */
+    public static class ReadDraftDataActionMonitor extends ActionMonitor
+            implements ActionCompletedListener {
+
+        private final ReadDraftDataActionListener mListener;
+
+        ReadDraftDataActionMonitor(final Object data,
+                final ReadDraftDataActionListener completed) {
+            super(STATE_CREATED, generateUniqueActionKey("ReadDraftDataAction"), data);
+            setCompletedListener(this);
+            mListener = completed;
+        }
+
+        @Override
+        public void onActionSucceeded(final ActionMonitor monitor,
+                final Action action, final Object data, final Object result) {
+            final DraftData draft = (DraftData) result;
+            if (draft == null) {
+                mListener.onReadDraftDataFailed((ReadDraftDataAction) action, data);
+            } else {
+                mListener.onReadDraftDataSucceeded((ReadDraftDataAction) action, data,
+                        draft.message, draft.conversation);
+            }
+        }
+
+        @Override
+        public void onActionFailed(final ActionMonitor monitor,
+                final Action action, final Object data, final Object result) {
+            Assert.fail("Reading draft should not fail");
+        }
+    }
+
+    private ReadDraftDataAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ReadDraftDataAction> CREATOR
+            = new Parcelable.Creator<ReadDraftDataAction>() {
+        @Override
+        public ReadDraftDataAction createFromParcel(final Parcel in) {
+            return new ReadDraftDataAction(in);
+        }
+
+        @Override
+        public ReadDraftDataAction[] newArray(final int size) {
+            return new ReadDraftDataAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java b/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java
new file mode 100644
index 0000000..6794b17
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DataModelException;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.sms.DatabaseMessages;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.LogUtil;
+
+import java.util.List;
+
+/**
+ * Action used to "receive" an incoming message
+ */
+public class ReceiveMmsMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_SUB_ID = "sub_id";
+    private static final String KEY_PUSH_DATA = "push_data";
+    private static final String KEY_TRANSACTION_ID = "transaction_id";
+    private static final String KEY_CONTENT_LOCATION = "content_location";
+
+    /**
+     * Create a message received from a particular number in a particular conversation
+     */
+    public ReceiveMmsMessageAction(final int subId, final byte[] pushData) {
+        actionParameters.putInt(KEY_SUB_ID, subId);
+        actionParameters.putByteArray(KEY_PUSH_DATA, pushData);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final Context context = Factory.get().getApplicationContext();
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        final byte[] pushData = actionParameters.getByteArray(KEY_PUSH_DATA);
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // Write received message to telephony DB
+        MessageData message = null;
+        final ParticipantData self = BugleDatabaseOperations.getOrCreateSelf(db, subId);
+
+        final long received = System.currentTimeMillis();
+        // Inform sync that message has been added at local received timestamp
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        syncManager.onNewMessageInserted(received);
+
+        // TODO: Should use local time to set received time in MMS message
+        final DatabaseMessages.MmsMessage mms = MmsUtils.processReceivedPdu(
+                context, pushData, self.getSubId(), self.getNormalizedDestination());
+
+        if (mms != null) {
+            final List<String> recipients = MmsUtils.getRecipientsByThread(mms.mThreadId);
+            String from = MmsUtils.getMmsSender(recipients, mms.getUri());
+            if (from == null) {
+                LogUtil.w(TAG, "Received an MMS without sender address; using unknown sender.");
+                from = ParticipantData.getUnknownSenderDestination();
+            }
+            final ParticipantData rawSender = ParticipantData.getFromRawPhoneBySimLocale(
+                    from, subId);
+            final boolean blocked = BugleDatabaseOperations.isBlockedDestination(
+                    db, rawSender.getNormalizedDestination());
+            final boolean autoDownload = (!blocked && MmsUtils.allowMmsAutoRetrieve(subId));
+            final String conversationId =
+                    BugleDatabaseOperations.getOrCreateConversationFromThreadId(db, mms.mThreadId,
+                            blocked, subId);
+
+            final boolean messageInFocusedConversation =
+                    DataModel.get().isFocusedConversation(conversationId);
+            final boolean messageInObservableConversation =
+                    DataModel.get().isNewMessageObservable(conversationId);
+
+            // TODO: Also write these values to the telephony provider
+            mms.mRead = messageInFocusedConversation;
+            mms.mSeen = messageInObservableConversation || blocked;
+
+            // Write received placeholder message to our DB
+            db.beginTransaction();
+            try {
+                final String participantId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, rawSender);
+                final String selfId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+
+                message = MmsUtils.createMmsMessage(mms, conversationId, participantId, selfId,
+                        (autoDownload ? MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD :
+                            MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD));
+                // Write the message
+                BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+
+                if (!autoDownload) {
+                    BugleDatabaseOperations.updateConversationMetadataInTransaction(db,
+                            conversationId, message.getMessageId(), message.getReceivedTimeStamp(),
+                            blocked, true /* shouldAutoSwitchSelfId */);
+                    final ParticipantData sender = ParticipantData .getFromId(
+                            db, participantId);
+                    BugleActionToasts.onMessageReceived(conversationId, sender, message);
+                }
+                // else update the conversation once we have downloaded final message (or failed)
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+            // Update conversation if not immediately initiating a download
+            if (!autoDownload) {
+                MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+                MessagingContentProvider.notifyPartsChanged();
+
+                // Show a notification to let the user know a new message has arrived
+                BugleNotifications.update(false/*silent*/, conversationId,
+                        BugleNotifications.UPDATE_ALL);
+
+                // Send the NotifyRespInd with DEFERRED status since no auto download
+                actionParameters.putString(KEY_TRANSACTION_ID, mms.mTransactionId);
+                actionParameters.putString(KEY_CONTENT_LOCATION, mms.mContentLocation);
+                requestBackgroundWork();
+            }
+
+            LogUtil.i(TAG, "ReceiveMmsMessageAction: Received MMS message " + message.getMessageId()
+                    + " in conversation " + message.getConversationId()
+                    + ", uri = " + message.getSmsMessageUri());
+        } else {
+            LogUtil.e(TAG, "ReceiveMmsMessageAction: Skipping processing of incoming PDU");
+        }
+
+        ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
+
+        return message;
+    }
+
+    @Override
+    protected Bundle doBackgroundWork() throws DataModelException {
+        final Context context = Factory.get().getApplicationContext();
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        final String transactionId = actionParameters.getString(KEY_TRANSACTION_ID);
+        final String contentLocation = actionParameters.getString(KEY_CONTENT_LOCATION);
+        MmsUtils.sendNotifyResponseForMmsDownload(
+                context,
+                subId,
+                MmsUtils.stringToBytes(transactionId, "UTF-8"),
+                contentLocation,
+                PduHeaders.STATUS_DEFERRED);
+        // We don't need to return anything.
+        return null;
+    }
+
+    private ReceiveMmsMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ReceiveMmsMessageAction> CREATOR
+            = new Parcelable.Creator<ReceiveMmsMessageAction>() {
+        @Override
+        public ReceiveMmsMessageAction createFromParcel(final Parcel in) {
+            return new ReceiveMmsMessageAction(in);
+        }
+
+        @Override
+        public ReceiveMmsMessageAction[] newArray(final int size) {
+            return new ReceiveMmsMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java b/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java
new file mode 100644
index 0000000..cb7a35d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.Sms;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Action used to "receive" an incoming message
+ */
+public class ReceiveSmsMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_MESSAGE_VALUES = "message_values";
+    private static final String KEY_SUB_ID = "sub_id";
+
+    /**
+     * Create a message received from a particular number in a particular conversation
+     */
+    public ReceiveSmsMessageAction(final ContentValues messageValues) {
+        actionParameters.putParcelable(KEY_MESSAGE_VALUES, messageValues);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final Context context = Factory.get().getApplicationContext();
+        final ContentValues messageValues = actionParameters.getParcelable(KEY_MESSAGE_VALUES);
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // Get the SIM subscription ID
+        Integer subId = messageValues.getAsInteger(Sms.SUBSCRIPTION_ID);
+        if (subId == null) {
+            subId = ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+        // Make sure we have a sender address
+        String address = messageValues.getAsString(Sms.ADDRESS);
+        if (TextUtils.isEmpty(address)) {
+            LogUtil.w(TAG, "Received an SMS without an address; using unknown sender.");
+            address = ParticipantData.getUnknownSenderDestination();
+            messageValues.put(Sms.ADDRESS, address);
+        }
+        final ParticipantData rawSender = ParticipantData.getFromRawPhoneBySimLocale(
+                address, subId);
+
+        // TODO: Should use local timestamp for this?
+        final long received = messageValues.getAsLong(Sms.DATE);
+        // Inform sync that message has been added at local received timestamp
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        syncManager.onNewMessageInserted(received);
+
+        // Make sure we've got a thread id
+        final long threadId = MmsSmsUtils.Threads.getOrCreateThreadId(context, address);
+        messageValues.put(Sms.THREAD_ID, threadId);
+        final boolean blocked = BugleDatabaseOperations.isBlockedDestination(
+                db, rawSender.getNormalizedDestination());
+        final String conversationId = BugleDatabaseOperations.
+                getOrCreateConversationFromRecipient(db, threadId, blocked, rawSender);
+
+        final boolean messageInFocusedConversation =
+                DataModel.get().isFocusedConversation(conversationId);
+        final boolean messageInObservableConversation =
+                DataModel.get().isNewMessageObservable(conversationId);
+
+        MessageData message = null;
+        // Only the primary user gets to insert the message into the telephony db and into bugle's
+        // db. The secondary user goes through this path, but skips doing the actual insert. It
+        // goes through this path because it needs to compute messageInFocusedConversation in order
+        // to calculate whether to skip the notification and play a soft sound if the user is
+        // already in the conversation.
+        if (!OsUtil.isSecondaryUser()) {
+            final boolean read = messageValues.getAsBoolean(Sms.Inbox.READ)
+                    || messageInFocusedConversation;
+            // If you have read it you have seen it
+            final boolean seen = read || messageInObservableConversation || blocked;
+            messageValues.put(Sms.Inbox.READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
+
+            // incoming messages are marked as seen in the telephony db
+            messageValues.put(Sms.Inbox.SEEN, 1);
+
+            // Insert into telephony
+            final Uri messageUri = context.getContentResolver().insert(Sms.Inbox.CONTENT_URI,
+                    messageValues);
+
+            if (messageUri != null) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "ReceiveSmsMessageAction: Inserted SMS message into telephony, "
+                            + "uri = " + messageUri);
+                }
+            } else {
+                LogUtil.e(TAG, "ReceiveSmsMessageAction: Failed to insert SMS into telephony!");
+            }
+
+            final String text = messageValues.getAsString(Sms.BODY);
+            final String subject = messageValues.getAsString(Sms.SUBJECT);
+            final long sent = messageValues.getAsLong(Sms.DATE_SENT);
+            final ParticipantData self = ParticipantData.getSelfParticipant(subId);
+            final Integer pathPresent = messageValues.getAsInteger(Sms.REPLY_PATH_PRESENT);
+            final String smsServiceCenter = messageValues.getAsString(Sms.SERVICE_CENTER);
+            String conversationServiceCenter = null;
+            // Only set service center if message REPLY_PATH_PRESENT = 1
+            if (pathPresent != null && pathPresent == 1 && !TextUtils.isEmpty(smsServiceCenter)) {
+                conversationServiceCenter = smsServiceCenter;
+            }
+            db.beginTransaction();
+            try {
+                final String participantId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, rawSender);
+                final String selfId =
+                        BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+
+                message = MessageData.createReceivedSmsMessage(messageUri, conversationId,
+                        participantId, selfId, text, subject, sent, received, seen, read);
+
+                BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+
+                BugleDatabaseOperations.updateConversationMetadataInTransaction(db, conversationId,
+                        message.getMessageId(), message.getReceivedTimeStamp(), blocked,
+                        conversationServiceCenter, true /* shouldAutoSwitchSelfId */);
+
+                final ParticipantData sender = ParticipantData.getFromId(db, participantId);
+                BugleActionToasts.onMessageReceived(conversationId, sender, message);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+            LogUtil.i(TAG, "ReceiveSmsMessageAction: Received SMS message " + message.getMessageId()
+                    + " in conversation " + message.getConversationId()
+                    + ", uri = " + messageUri);
+
+            actionParameters.putInt(KEY_SUB_ID, subId);
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
+        } else {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "ReceiveSmsMessageAction: Not inserting received SMS message for "
+                        + "secondary user.");
+            }
+        }
+        // Show a notification to let the user know a new message has arrived
+        BugleNotifications.update(false/*silent*/, conversationId, BugleNotifications.UPDATE_ALL);
+
+        MessagingContentProvider.notifyMessagesChanged(conversationId);
+        MessagingContentProvider.notifyPartsChanged();
+
+        return message;
+    }
+
+    private ReceiveSmsMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ReceiveSmsMessageAction> CREATOR
+            = new Parcelable.Creator<ReceiveSmsMessageAction>() {
+        @Override
+        public ReceiveSmsMessageAction createFromParcel(final Parcel in) {
+            return new ReceiveSmsMessageAction(in);
+        }
+
+        @Override
+        public ReceiveSmsMessageAction[] newArray(final int size) {
+            return new ReceiveSmsMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/RedownloadMmsAction.java b/src/com/android/messaging/datamodel/action/RedownloadMmsAction.java
new file mode 100644
index 0000000..69c34da
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/RedownloadMmsAction.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action to manually start an MMS download (after failed or manual mms download)
+ */
+public class RedownloadMmsAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final int REQUEST_CODE_PENDING_INTENT = 101;
+
+    private static final String KEY_SUB_ID = "sub_id";
+
+    /**
+     * Download an MMS message
+     */
+    public static void redownloadMessage(final String messageId) {
+        final RedownloadMmsAction action = new RedownloadMmsAction(messageId);
+        action.start();
+    }
+
+    /**
+     * Get a pending intent of for downloading an MMS
+     */
+    public static PendingIntent getPendingIntentForRedownloadMms(
+            final Context context, final String messageId) {
+        final Action action = new RedownloadMmsAction(messageId);
+        return ActionService.makeStartActionPendingIntent(context,
+                action, REQUEST_CODE_PENDING_INTENT, false /*launchesAnActivity*/);
+    }
+
+    // Core parameters needed for all types of message
+    private static final String KEY_MESSAGE_ID = "message_id";
+
+    /**
+     * Constructor used for retrying sending in the background (only message id available)
+     */
+    RedownloadMmsAction(final String messageId) {
+        super();
+        actionParameters.putString(KEY_MESSAGE_ID, messageId);
+    }
+
+    /**
+     * Read message from database and change status to allow downloading
+     */
+    @Override
+    protected Object executeAction() {
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+        // Check message can be redownloaded
+        if (message != null && message.canRedownloadMessage()) {
+            final long timestamp = System.currentTimeMillis();
+
+            final ContentValues values = new ContentValues(2);
+            values.put(DatabaseHelper.MessageColumns.STATUS,
+                    MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD);
+            values.put(DatabaseHelper.MessageColumns.RETRY_START_TIMESTAMP, timestamp);
+
+            // Row must exist as was just loaded above (on ActionService thread)
+            BugleDatabaseOperations.updateMessageRow(db, message.getMessageId(), values);
+
+            MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+            actionParameters.putInt(KEY_SUB_ID,
+                    BugleDatabaseOperations.getSelfSubscriptionId(db, message.getSelfId()));
+            // Whether we succeeded or failed we will check and maybe schedule some more work
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
+        } else {
+            message = null;
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "Attempt to download a missing or un-redownloadable message");
+        }
+        // Immediately update the notifications in case we came from the download action from a
+        // heads-up notification. This will dismiss the heads-up notification.
+        BugleNotifications.update(false/*silent*/, BugleNotifications.UPDATE_ALL);
+        return message;
+    }
+
+    private RedownloadMmsAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<RedownloadMmsAction> CREATOR
+            = new Parcelable.Creator<RedownloadMmsAction>() {
+        @Override
+        public RedownloadMmsAction createFromParcel(final Parcel in) {
+            return new RedownloadMmsAction(in);
+        }
+
+        @Override
+        public RedownloadMmsAction[] newArray(final int size) {
+            return new RedownloadMmsAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/ResendMessageAction.java b/src/com/android/messaging/datamodel/action/ResendMessageAction.java
new file mode 100644
index 0000000..b442ae6
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/ResendMessageAction.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Action used to manually resend an outgoing message
+ */
+public class ResendMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_SUB_ID = "sub_id";
+
+    /**
+     * Manual send of existing message (no listener)
+     */
+    public static void resendMessage(final String messageId) {
+        final ResendMessageAction action = new ResendMessageAction(messageId);
+        action.start();
+    }
+
+    // Core parameters needed for all types of message
+    private static final String KEY_MESSAGE_ID = "message_id";
+
+    /**
+     * Constructor used for retrying sending in the background (only message id available)
+     */
+    ResendMessageAction(final String messageId) {
+        super();
+        actionParameters.putString(KEY_MESSAGE_ID, messageId);
+    }
+
+    /**
+     * Read message from database and change status to allow sending
+     */
+    @Override
+    protected Object executeAction() {
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+        // Check message can be resent
+        if (message != null && message.canResendMessage()) {
+            final boolean isMms = message.getIsMms();
+            long timestamp = System.currentTimeMillis();
+            if (isMms) {
+                // MMS expects timestamp rounded to nearest second
+                timestamp = 1000 * ((timestamp + 500) / 1000);
+            }
+
+            LogUtil.i(TAG, "ResendMessageAction: Resending message " + messageId
+                    + "; changed timestamp from " + message.getReceivedTimeStamp() + " to "
+                    + timestamp);
+
+            final ContentValues values = new ContentValues();
+            values.put(MessageColumns.STATUS, MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND);
+            values.put(MessageColumns.RETRY_START_TIMESTAMP, timestamp);
+
+            // Row must exist as was just loaded above (on ActionService thread)
+            BugleDatabaseOperations.updateMessageRow(db, message.getMessageId(), values);
+
+            MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+
+            actionParameters.putInt(KEY_SUB_ID,
+                    BugleDatabaseOperations.getSelfSubscriptionId(db, message.getSelfId()));
+
+            // Whether we succeeded or failed we will check and maybe schedule some more work
+            ProcessPendingMessagesAction.scheduleProcessPendingMessagesAction(false, this);
+
+            return message;
+        } else {
+            String error = "ResendMessageAction: Cannot resend message " + messageId + "; ";
+            if (message != null) {
+                error += ("status = " + MessageData.getStatusDescription(message.getStatus()));
+            } else {
+                error += "not found in database";
+            }
+            LogUtil.e(TAG, error);
+        }
+
+        return null;
+    }
+
+    private ResendMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<ResendMessageAction> CREATOR
+            = new Parcelable.Creator<ResendMessageAction>() {
+        @Override
+        public ResendMessageAction createFromParcel(final Parcel in) {
+            return new ResendMessageAction(in);
+        }
+
+        @Override
+        public ResendMessageAction[] newArray(final int size) {
+            return new ResendMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/SendMessageAction.java b/src/com/android/messaging/datamodel/action/SendMessageAction.java
new file mode 100644
index 0000000..44c661d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/SendMessageAction.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Sms;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+
+/**
+ * Action used to send an outgoing message. It writes MMS messages to the telephony db
+ * ({@link InsertNewMessageAction}) writes SMS messages to the telephony db). It also
+ * initiates the actual sending. It will all be used for re-sending a failed message.
+ * <p>
+ * This class is public (not package-private) because the SMS/MMS (e.g. MmsUtils) classes need to
+ * access the EXTRA_* fields for setting up the 'sent' pending intent.
+ */
+public class SendMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    /**
+     * Queue sending of existing message (can only be called during execute of action)
+     */
+    static boolean queueForSendInBackground(final String messageId,
+            final Action processingAction) {
+        final SendMessageAction action = new SendMessageAction();
+        return action.queueAction(messageId, processingAction);
+    }
+
+    public static final boolean DEFAULT_DELIVERY_REPORT_MODE  = false;
+    public static final int MAX_SMS_RETRY = 3;
+
+    // Core parameters needed for all types of message
+    private static final String KEY_MESSAGE_ID = "message_id";
+    private static final String KEY_MESSAGE = "message";
+    private static final String KEY_MESSAGE_URI = "message_uri";
+    private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
+
+    // For sms messages a few extra values are included in the bundle
+    private static final String KEY_RECIPIENT = "recipient";
+    private static final String KEY_RECIPIENTS = "recipients";
+    private static final String KEY_SMS_SERVICE_CENTER = "sms_service_center";
+
+    // Values we attach to the pending intent that's fired when the message is sent.
+    // Only applicable when sending via the platform APIs on L+.
+    public static final String KEY_SUB_ID = "sub_id";
+    public static final String EXTRA_MESSAGE_ID = "message_id";
+    public static final String EXTRA_UPDATED_MESSAGE_URI = "updated_message_uri";
+    public static final String EXTRA_CONTENT_URI = "content_uri";
+    public static final String EXTRA_RESPONSE_IMPORTANT = "response_important";
+
+    /**
+     * Constructor used for retrying sending in the background (only message id available)
+     */
+    private SendMessageAction() {
+        super();
+    }
+
+    /**
+     * Read message from database and queue actual sending
+     */
+    private boolean queueAction(final String messageId, final Action processingAction) {
+        actionParameters.putString(KEY_MESSAGE_ID, messageId);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
+        // Check message can be resent
+        if (message != null && message.canSendMessage()) {
+            final boolean isSms = message.getIsSms();
+            long timestamp = System.currentTimeMillis();
+            if (!isSms) {
+                // MMS expects timestamp rounded to nearest second
+                timestamp = 1000 * ((timestamp + 500) / 1000);
+            }
+
+            final ParticipantData self = BugleDatabaseOperations.getExistingParticipant(
+                    db, message.getSelfId());
+            final Uri messageUri = message.getSmsMessageUri();
+            final String conversationId = message.getConversationId();
+
+            // Update message status
+            if (message.getYetToSend()) {
+                if (message.getReceivedTimeStamp() == message.getRetryStartTimestamp()) {
+                    // Initial sending of message
+                    message.markMessageSending(timestamp);
+                } else {
+                    // Manual resend of message
+                    message.markMessageManualResend(timestamp);
+                }
+            } else {
+                // Automatic resend of message
+                message.markMessageResending(timestamp);
+            }
+            if (!updateMessageAndStatus(isSms, message, null /* messageUri */, false /*notify*/)) {
+                // If message is missing in the telephony database we don't need to send it
+                return false;
+            }
+
+            final ArrayList<String> recipients =
+                    BugleDatabaseOperations.getRecipientsForConversation(db, conversationId);
+
+            // Update action state with parameters needed for background sending
+            actionParameters.putParcelable(KEY_MESSAGE_URI, messageUri);
+            actionParameters.putParcelable(KEY_MESSAGE, message);
+            actionParameters.putStringArrayList(KEY_RECIPIENTS, recipients);
+            actionParameters.putInt(KEY_SUB_ID, self.getSubId());
+            actionParameters.putString(KEY_SUB_PHONE_NUMBER, self.getNormalizedDestination());
+
+            if (isSms) {
+                final String smsc = BugleDatabaseOperations.getSmsServiceCenterForConversation(
+                        db, conversationId);
+                actionParameters.putString(KEY_SMS_SERVICE_CENTER, smsc);
+
+                if (recipients.size() == 1) {
+                    final String recipient = recipients.get(0);
+
+                    actionParameters.putString(KEY_RECIPIENT, recipient);
+                    // Queue actual sending for SMS
+                    processingAction.requestBackgroundWork(this);
+
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "SendMessageAction: Queued SMS message " + messageId
+                                + " for sending");
+                    }
+                    return true;
+                } else {
+                    LogUtil.wtf(TAG, "Trying to resend a broadcast SMS - not allowed");
+                }
+            } else {
+                // Queue actual sending for MMS
+                processingAction.requestBackgroundWork(this);
+
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SendMessageAction: Queued MMS message " + messageId
+                            + " for sending");
+                }
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Never called
+     */
+    @Override
+    protected Object executeAction() {
+        Assert.fail("SendMessageAction must be queued rather than started");
+        return null;
+    }
+
+    /**
+     * Send message on background worker thread
+     */
+    @Override
+    protected Bundle doBackgroundWork() {
+        final MessageData message = actionParameters.getParcelable(KEY_MESSAGE);
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        Uri messageUri = actionParameters.getParcelable(KEY_MESSAGE_URI);
+        Uri updatedMessageUri = null;
+        final boolean isSms = message.getProtocol() == MessageData.PROTOCOL_SMS;
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        final String subPhoneNumber = actionParameters.getString(KEY_SUB_PHONE_NUMBER);
+
+        LogUtil.i(TAG, "SendMessageAction: Sending " + (isSms ? "SMS" : "MMS") + " message "
+                + messageId + " in conversation " + message.getConversationId());
+
+        int status;
+        int rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+        int resultCode = MessageData.UNKNOWN_RESULT_CODE;
+        if (isSms) {
+            Assert.notNull(messageUri);
+            final String recipient = actionParameters.getString(KEY_RECIPIENT);
+            final String messageText = message.getMessageText();
+            final String smsServiceCenter = actionParameters.getString(KEY_SMS_SERVICE_CENTER);
+            final boolean deliveryReportRequired = MmsUtils.isDeliveryReportRequired(subId);
+
+            status = MmsUtils.sendSmsMessage(recipient, messageText, messageUri, subId,
+                    smsServiceCenter, deliveryReportRequired);
+        } else {
+            final Context context = Factory.get().getApplicationContext();
+            final ArrayList<String> recipients =
+                    actionParameters.getStringArrayList(KEY_RECIPIENTS);
+            if (messageUri == null) {
+                final long timestamp = message.getReceivedTimeStamp();
+
+                // Inform sync that message has been added at local received timestamp
+                final SyncManager syncManager = DataModel.get().getSyncManager();
+                syncManager.onNewMessageInserted(timestamp);
+
+                // For MMS messages first need to write to telephony (resizing images if needed)
+                updatedMessageUri = MmsUtils.insertSendingMmsMessage(context, recipients,
+                        message, subId, subPhoneNumber, timestamp);
+                if (updatedMessageUri != null) {
+                    messageUri = updatedMessageUri;
+                    // To prevent Sync seeing inconsistent state must write to DB on this thread
+                    updateMessageUri(messageId, updatedMessageUri);
+
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "SendMessageAction: Updated message " + messageId
+                                + " with new uri " + messageUri);
+                    }
+                 }
+            }
+            if (messageUri != null) {
+                // Actually send the MMS
+                final Bundle extras = new Bundle();
+                extras.putString(EXTRA_MESSAGE_ID, messageId);
+                extras.putParcelable(EXTRA_UPDATED_MESSAGE_URI, updatedMessageUri);
+                final MmsUtils.StatusPlusUri result = MmsUtils.sendMmsMessage(context, subId,
+                        messageUri, extras);
+                if (result == MmsUtils.STATUS_PENDING) {
+                    // Async send, so no status yet
+                    LogUtil.d(TAG, "SendMessageAction: Sending MMS message " + messageId
+                            + " asynchronously; waiting for callback to finish processing");
+                    return null;
+                }
+                status = result.status;
+                rawStatus = result.rawStatus;
+                resultCode = result.resultCode;
+            } else {
+                status = MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+            }
+        }
+
+        // When we fast-fail before calling the MMS lib APIs (e.g. airplane mode,
+        // sending message is deleted).
+        ProcessSentMessageAction.processMessageSentFastFailed(messageId, messageUri,
+                updatedMessageUri, subId, isSms, status, rawStatus, resultCode);
+        return null;
+    }
+
+    private void updateMessageUri(final String messageId, final Uri updatedMessageUri) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+            values.put(MessageColumns.SMS_MESSAGE_URI, updatedMessageUri.toString());
+            BugleDatabaseOperations.updateMessageRow(db, messageId, values);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    @Override
+    protected Object processBackgroundResponse(final Bundle response) {
+        // Nothing to do here, post-send tasks handled by ProcessSentMessageAction
+        return null;
+    }
+
+    /**
+     * Update message status to reflect success or failure
+     */
+    @Override
+    protected Object processBackgroundFailure() {
+        final String messageId = actionParameters.getString(KEY_MESSAGE_ID);
+        final MessageData message = actionParameters.getParcelable(KEY_MESSAGE);
+        final boolean isSms = message.getProtocol() == MessageData.PROTOCOL_SMS;
+        final int subId = actionParameters.getInt(KEY_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID);
+        final int resultCode = actionParameters.getInt(ProcessSentMessageAction.KEY_RESULT_CODE);
+        final int httpStatusCode =
+                actionParameters.getInt(ProcessSentMessageAction.KEY_HTTP_STATUS_CODE);
+
+        ProcessSentMessageAction.processResult(messageId, null /* updatedMessageUri */,
+                MmsUtils.MMS_REQUEST_MANUAL_RETRY, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
+                isSms, this, subId, resultCode, httpStatusCode);
+
+        return null;
+    }
+
+    /**
+     * Update the message status (and message itself if necessary)
+     * @param isSms whether this is an SMS or MMS
+     * @param message message to update
+     * @param updatedMessageUri message uri for newly-inserted messages; null otherwise
+     * @param clearSeen whether the message 'seen' status should be reset if error occurs
+     */
+    public static boolean updateMessageAndStatus(final boolean isSms, final MessageData message,
+            final Uri updatedMessageUri, final boolean clearSeen) {
+        final Context context = Factory.get().getApplicationContext();
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        // TODO: We're optimistically setting the type/box of outgoing messages to
+        // 'SENT' even before they actually are. We should technically be using QUEUED or OUTBOX
+        // instead, but if we do that, it's possible that the Messaging app will try to send them
+        // as part of its clean-up logic that runs when it starts (http://b/18155366).
+        //
+        // We also use the wrong status when inserting queued SMS messages in
+        // InsertNewMessageAction.insertBroadcastSmsMessage and insertSendingSmsMessage (should be
+        // QUEUED or OUTBOX), and in MmsUtils.insertSendReq (should be OUTBOX).
+
+        boolean updatedTelephony = true;
+        int messageBox;
+        int type;
+        switch(message.getStatus()) {
+            case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE:
+            case MessageData.BUGLE_STATUS_OUTGOING_DELIVERED:
+                type = Sms.MESSAGE_TYPE_SENT;
+                messageBox = Mms.MESSAGE_BOX_SENT;
+                break;
+            case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND:
+            case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY:
+                type = Sms.MESSAGE_TYPE_SENT;
+                messageBox = Mms.MESSAGE_BOX_SENT;
+                break;
+            case MessageData.BUGLE_STATUS_OUTGOING_SENDING:
+            case MessageData.BUGLE_STATUS_OUTGOING_RESENDING:
+                type = Sms.MESSAGE_TYPE_SENT;
+                messageBox = Mms.MESSAGE_BOX_SENT;
+                break;
+            case MessageData.BUGLE_STATUS_OUTGOING_FAILED:
+            case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER:
+                type = Sms.MESSAGE_TYPE_FAILED;
+                messageBox = Mms.MESSAGE_BOX_FAILED;
+                break;
+            default:
+                type = Sms.MESSAGE_TYPE_ALL;
+                messageBox = Mms.MESSAGE_BOX_ALL;
+                break;
+        }
+        // First in the telephony DB
+        if (isSms) {
+            // Ignore update message Uri
+            if (type != Sms.MESSAGE_TYPE_ALL) {
+                if (!MmsUtils.updateSmsMessageSendingStatus(context, message.getSmsMessageUri(),
+                        type, message.getReceivedTimeStamp())) {
+                    message.markMessageFailed(message.getSentTimeStamp());
+                    updatedTelephony = false;
+                }
+            }
+        } else if (message.getSmsMessageUri() != null) {
+            if (messageBox != Mms.MESSAGE_BOX_ALL) {
+                if (!MmsUtils.updateMmsMessageSendingStatus(context, message.getSmsMessageUri(),
+                        messageBox, message.getReceivedTimeStamp())) {
+                    message.markMessageFailed(message.getSentTimeStamp());
+                    updatedTelephony = false;
+                }
+            }
+        }
+        if (updatedTelephony) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "SendMessageAction: Updated " + (isSms ? "SMS" : "MMS")
+                        + " message " + message.getMessageId()
+                        + " in telephony (" + message.getSmsMessageUri() + ")");
+            }
+        } else {
+            LogUtil.w(TAG, "SendMessageAction: Failed to update " + (isSms ? "SMS" : "MMS")
+                    + " message " + message.getMessageId()
+                    + " in telephony (" + message.getSmsMessageUri() + "); marking message failed");
+        }
+
+        // Update the local DB
+        db.beginTransaction();
+        try {
+            if (updatedMessageUri != null) {
+                // Update all message and part fields
+                BugleDatabaseOperations.updateMessageInTransaction(db, message);
+                BugleDatabaseOperations.refreshConversationMetadataInTransaction(
+                        db, message.getConversationId(), false/* shouldAutoSwitchSelfId */,
+                        false/*archived*/);
+            } else {
+                final ContentValues values = new ContentValues();
+                values.put(MessageColumns.STATUS, message.getStatus());
+
+                if (clearSeen) {
+                    // When a message fails to send, the message needs to
+                    // be unseen to be selected as an error notification.
+                    values.put(MessageColumns.SEEN, 0);
+                }
+                values.put(MessageColumns.RECEIVED_TIMESTAMP, message.getReceivedTimeStamp());
+                values.put(MessageColumns.RAW_TELEPHONY_STATUS, message.getRawTelephonyStatus());
+
+                BugleDatabaseOperations.updateMessageRowIfExists(db, message.getMessageId(),
+                        values);
+            }
+            db.setTransactionSuccessful();
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "SendMessageAction: Updated " + (isSms ? "SMS" : "MMS")
+                        + " message " + message.getMessageId() + " in local db. Timestamp = "
+                        + message.getReceivedTimeStamp());
+            }
+        } finally {
+            db.endTransaction();
+        }
+
+        MessagingContentProvider.notifyMessagesChanged(message.getConversationId());
+        if (updatedMessageUri != null) {
+            MessagingContentProvider.notifyPartsChanged();
+        }
+
+        return updatedTelephony;
+    }
+
+    private SendMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<SendMessageAction> CREATOR
+            = new Parcelable.Creator<SendMessageAction>() {
+        @Override
+        public SendMessageAction createFromParcel(final Parcel in) {
+            return new SendMessageAction(in);
+        }
+
+        @Override
+        public SendMessageAction[] newArray(final int size) {
+            return new SendMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/SyncCursorPair.java b/src/com/android/messaging/datamodel/action/SyncCursorPair.java
new file mode 100644
index 0000000..e2fd7ec
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/SyncCursorPair.java
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Sms;
+import androidx.collection.LongSparseArray;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.SyncManager.ThreadInfoCache;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.sms.DatabaseMessages;
+import com.android.messaging.sms.DatabaseMessages.DatabaseMessage;
+import com.android.messaging.sms.DatabaseMessages.LocalDatabaseMessage;
+import com.android.messaging.sms.DatabaseMessages.MmsMessage;
+import com.android.messaging.sms.DatabaseMessages.SmsMessage;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.google.common.collect.Sets;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Class holding a pair of cursors - one for local db and one for telephony provider - allowing
+ * synchronous stepping through messages as part of sync.
+ */
+class SyncCursorPair {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    static final long SYNC_COMPLETE = -1L;
+    static final long SYNC_STARTING = Long.MAX_VALUE;
+
+    private CursorIterator mLocalCursorIterator;
+    private CursorIterator mRemoteCursorsIterator;
+
+    private final String mLocalSelection;
+    private final String mRemoteSmsSelection;
+    private final String mRemoteMmsSelection;
+
+    /**
+     * Check if SMS has been synchronized. We compare the counts of messages on both
+     * sides and return true if they are equal.
+     *
+     * Note that this may not be the most reliable way to tell if messages are in sync.
+     * For example, the local misses one message and has one obsolete message.
+     * However, we have background sms sync once a while, also some other events might
+     * trigger a full sync. So we will eventually catch up. And this should be rare to
+     * happen.
+     *
+     * @return If sms is in sync with telephony sms/mms providers
+     */
+    static boolean allSynchronized(final DatabaseWrapper db) {
+        return isSynchronized(db, LOCAL_MESSAGES_SELECTION, null,
+                getSmsTypeSelectionSql(), null, getMmsTypeSelectionSql(), null);
+    }
+
+    SyncCursorPair(final long lowerBound, final long upperBound) {
+        mLocalSelection = getTimeConstrainedQuery(
+                LOCAL_MESSAGES_SELECTION,
+                MessageColumns.RECEIVED_TIMESTAMP,
+                lowerBound,
+                upperBound,
+                null /* threadColumn */, null /* threadId */);
+        mRemoteSmsSelection = getTimeConstrainedQuery(
+                getSmsTypeSelectionSql(),
+                "date",
+                lowerBound,
+                upperBound,
+                null /* threadColumn */, null /* threadId */);
+        mRemoteMmsSelection = getTimeConstrainedQuery(
+                getMmsTypeSelectionSql(),
+                "date",
+                ((lowerBound < 0) ? lowerBound : (lowerBound + 999) / 1000), /*seconds*/
+                ((upperBound < 0) ? upperBound : (upperBound + 999) / 1000),  /*seconds*/
+                null /* threadColumn */, null /* threadId */);
+    }
+
+    SyncCursorPair(final long threadId, final String conversationId) {
+        mLocalSelection = getTimeConstrainedQuery(
+                LOCAL_MESSAGES_SELECTION,
+                MessageColumns.RECEIVED_TIMESTAMP,
+                -1L,
+                -1L,
+                MessageColumns.CONVERSATION_ID, conversationId);
+        // Find all SMS messages (excluding drafts) within the sync window
+        mRemoteSmsSelection = getTimeConstrainedQuery(
+                getSmsTypeSelectionSql(),
+                "date",
+                -1L,
+                -1L,
+                Sms.THREAD_ID, Long.toString(threadId));
+        mRemoteMmsSelection = getTimeConstrainedQuery(
+                getMmsTypeSelectionSql(),
+                "date",
+                -1L, /*seconds*/
+                -1L,  /*seconds*/
+                Mms.THREAD_ID, Long.toString(threadId));
+    }
+
+    void query(final DatabaseWrapper db) {
+        // Load local messages in the sync window
+        mLocalCursorIterator = new LocalCursorIterator(db, mLocalSelection);
+        // Load remote messages in the sync window
+        mRemoteCursorsIterator = new RemoteCursorsIterator(mRemoteSmsSelection,
+                mRemoteMmsSelection);
+    }
+
+    boolean isSynchronized(final DatabaseWrapper db) {
+        return isSynchronized(db, mLocalSelection, null, mRemoteSmsSelection,
+                null, mRemoteMmsSelection, null);
+    }
+
+    void close() {
+        if (mLocalCursorIterator != null) {
+            mLocalCursorIterator.close();
+        }
+        if (mRemoteCursorsIterator != null) {
+            mRemoteCursorsIterator.close();
+        }
+    }
+
+    long scan(final int maxMessagesToScan,
+            final int maxMessagesToUpdate, final ArrayList<SmsMessage> smsToAdd,
+            final LongSparseArray<MmsMessage> mmsToAdd,
+            final ArrayList<LocalDatabaseMessage> messagesToDelete,
+            final SyncManager.ThreadInfoCache threadInfoCache) {
+        // Set of local messages matched with the timestamp of a remote message
+        final Set<DatabaseMessage> matchedLocalMessages = Sets.newHashSet();
+        // Set of remote messages matched with the timestamp of a local message
+        final Set<DatabaseMessage> matchedRemoteMessages = Sets.newHashSet();
+        long lastTimestampMillis = SYNC_STARTING;
+        // Number of messages scanned local and remote
+        int localCount = 0;
+        int remoteCount = 0;
+        // Seed the initial values of remote and local messages for comparison
+        DatabaseMessage remoteMessage = mRemoteCursorsIterator.next();
+        DatabaseMessage localMessage = mLocalCursorIterator.next();
+        // Iterate through messages on both sides in reverse time order
+        // Import messages in remote not in local, delete messages in local not in remote
+        while (localCount + remoteCount < maxMessagesToScan && smsToAdd.size()
+                + mmsToAdd.size() + messagesToDelete.size() < maxMessagesToUpdate) {
+            if (remoteMessage == null && localMessage == null) {
+                // No more message on both sides - scan complete
+                lastTimestampMillis = SYNC_COMPLETE;
+                break;
+            } else if ((remoteMessage == null && localMessage != null) ||
+                    (localMessage != null && remoteMessage != null &&
+                        localMessage.getTimestampInMillis()
+                            > remoteMessage.getTimestampInMillis())) {
+                // Found a local message that is not in remote db
+                // Delete the local message
+                messagesToDelete.add((LocalDatabaseMessage) localMessage);
+                lastTimestampMillis = Math.min(lastTimestampMillis,
+                        localMessage.getTimestampInMillis());
+                // Advance to next local message
+                localMessage = mLocalCursorIterator.next();
+                localCount += 1;
+            } else if ((localMessage == null && remoteMessage != null) ||
+                    (localMessage != null && remoteMessage != null &&
+                        localMessage.getTimestampInMillis()
+                            < remoteMessage.getTimestampInMillis())) {
+                // Found a remote message that is not in local db
+                // Add the remote message
+                saveMessageToAdd(smsToAdd, mmsToAdd, remoteMessage, threadInfoCache);
+                lastTimestampMillis = Math.min(lastTimestampMillis,
+                        remoteMessage.getTimestampInMillis());
+                // Advance to next remote message
+                remoteMessage = mRemoteCursorsIterator.next();
+                remoteCount += 1;
+            } else {
+                // Found remote and local messages at the same timestamp
+                final long matchedTimestamp = localMessage.getTimestampInMillis();
+                lastTimestampMillis = Math.min(lastTimestampMillis, matchedTimestamp);
+                // Get the next local and remote messages
+                final DatabaseMessage remoteMessagePeek = mRemoteCursorsIterator.next();
+                final DatabaseMessage localMessagePeek = mLocalCursorIterator.next();
+                // Check if only one message on each side matches the current timestamp
+                // by looking at the next messages on both sides. If they are either null
+                // (meaning no more messages) or having a different timestamp. We want
+                // to optimize for this since this is the most common case when majority
+                // of the messages are in sync (so they one-to-one pair up at each timestamp),
+                // by not allocating the data structures required to compare a set of
+                // messages from both sides.
+                if ((remoteMessagePeek == null ||
+                        remoteMessagePeek.getTimestampInMillis() != matchedTimestamp) &&
+                        (localMessagePeek == null ||
+                            localMessagePeek.getTimestampInMillis() != matchedTimestamp)) {
+                    // Optimize the common case where only one message on each side
+                    // that matches the same timestamp
+                    if (!remoteMessage.equals(localMessage)) {
+                        // local != remote
+                        // Delete local message
+                        messagesToDelete.add((LocalDatabaseMessage) localMessage);
+                        // Add remote message
+                        saveMessageToAdd(smsToAdd, mmsToAdd, remoteMessage, threadInfoCache);
+                    }
+                    // Get next local and remote messages
+                    localMessage = localMessagePeek;
+                    remoteMessage = remoteMessagePeek;
+                    localCount += 1;
+                    remoteCount += 1;
+                } else {
+                    // Rare case in which multiple messages are in the same timestamp
+                    // on either or both sides
+                    // Gather all the matched remote messages
+                    matchedRemoteMessages.clear();
+                    matchedRemoteMessages.add(remoteMessage);
+                    remoteCount += 1;
+                    remoteMessage = remoteMessagePeek;
+                    while (remoteMessage != null &&
+                        remoteMessage.getTimestampInMillis() == matchedTimestamp) {
+                        Assert.isTrue(!matchedRemoteMessages.contains(remoteMessage));
+                        matchedRemoteMessages.add(remoteMessage);
+                        remoteCount += 1;
+                        remoteMessage = mRemoteCursorsIterator.next();
+                    }
+                    // Gather all the matched local messages
+                    matchedLocalMessages.clear();
+                    matchedLocalMessages.add(localMessage);
+                    localCount += 1;
+                    localMessage = localMessagePeek;
+                    while (localMessage != null &&
+                            localMessage.getTimestampInMillis() == matchedTimestamp) {
+                        if (matchedLocalMessages.contains(localMessage)) {
+                            // Duplicate message is local database is deleted
+                            messagesToDelete.add((LocalDatabaseMessage) localMessage);
+                        } else {
+                            matchedLocalMessages.add(localMessage);
+                        }
+                        localCount += 1;
+                        localMessage = mLocalCursorIterator.next();
+                    }
+                    // Delete messages local only
+                    for (final DatabaseMessage msg : Sets.difference(
+                            matchedLocalMessages, matchedRemoteMessages)) {
+                        messagesToDelete.add((LocalDatabaseMessage) msg);
+                    }
+                    // Add messages remote only
+                    for (final DatabaseMessage msg : Sets.difference(
+                            matchedRemoteMessages, matchedLocalMessages)) {
+                        saveMessageToAdd(smsToAdd, mmsToAdd, msg, threadInfoCache);
+                    }
+                }
+            }
+        }
+        return lastTimestampMillis;
+    }
+
+    DatabaseMessage getLocalMessage() {
+        return mLocalCursorIterator.next();
+    }
+
+    DatabaseMessage getRemoteMessage() {
+        return mRemoteCursorsIterator.next();
+    }
+
+    int getLocalPosition() {
+        return mLocalCursorIterator.getPosition();
+    }
+
+    int getRemotePosition() {
+        return mRemoteCursorsIterator.getPosition();
+    }
+
+    int getLocalCount() {
+        return mLocalCursorIterator.getCount();
+    }
+
+    int getRemoteCount() {
+        return mRemoteCursorsIterator.getCount();
+    }
+
+    /**
+     * An iterator for a database cursor
+     */
+    interface CursorIterator {
+        /**
+         * Move to next element in the cursor
+         *
+         * @return The next element (which becomes the current)
+         */
+        public DatabaseMessage next();
+        /**
+         * Close the cursor
+         */
+        public void close();
+        /**
+         * Get the position
+         */
+        public int getPosition();
+        /**
+         * Get the count
+         */
+        public int getCount();
+    }
+
+    private static final String ORDER_BY_DATE_DESC = "date DESC";
+
+    // A subquery that selects SMS/MMS messages in Bugle which are also in telephony
+    private static final String LOCAL_MESSAGES_SELECTION = String.format(
+            Locale.US,
+            "(%s NOTNULL)",
+            MessageColumns.SMS_MESSAGE_URI);
+
+    private static final String ORDER_BY_TIMESTAMP_DESC =
+            MessageColumns.RECEIVED_TIMESTAMP + " DESC";
+
+    // TODO : This should move into the provider
+    private static class LocalMessageQuery {
+        private static final String[] PROJECTION = new String[] {
+                MessageColumns._ID,
+                MessageColumns.RECEIVED_TIMESTAMP,
+                MessageColumns.SMS_MESSAGE_URI,
+                MessageColumns.PROTOCOL,
+                MessageColumns.CONVERSATION_ID,
+        };
+        private static final int INDEX_MESSAGE_ID = 0;
+        private static final int INDEX_MESSAGE_TIMESTAMP = 1;
+        private static final int INDEX_SMS_MESSAGE_URI = 2;
+        private static final int INDEX_MESSAGE_SMS_TYPE = 3;
+        private static final int INDEX_CONVERSATION_ID = 4;
+    }
+
+    /**
+     * This class provides the same DatabaseMessage interface over a local SMS db message
+     */
+    private static LocalDatabaseMessage getLocalDatabaseMessage(final Cursor cursor) {
+        if (cursor == null) {
+            return null;
+        }
+        return new LocalDatabaseMessage(
+                cursor.getLong(LocalMessageQuery.INDEX_MESSAGE_ID),
+                cursor.getInt(LocalMessageQuery.INDEX_MESSAGE_SMS_TYPE),
+                cursor.getString(LocalMessageQuery.INDEX_SMS_MESSAGE_URI),
+                cursor.getLong(LocalMessageQuery.INDEX_MESSAGE_TIMESTAMP),
+                cursor.getString(LocalMessageQuery.INDEX_CONVERSATION_ID));
+    }
+
+    /**
+     * The buffered cursor iterator for local SMS
+     */
+    private static class LocalCursorIterator implements CursorIterator {
+        private Cursor mCursor;
+        private final DatabaseWrapper mDatabase;
+
+        LocalCursorIterator(final DatabaseWrapper database, final String selection)
+                throws SQLiteException {
+            mDatabase = database;
+            try {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "SyncCursorPair: Querying for local messages; selection = "
+                            + selection);
+                }
+                mCursor = mDatabase.query(
+                        DatabaseHelper.MESSAGES_TABLE,
+                        LocalMessageQuery.PROJECTION,
+                        selection,
+                        null /*selectionArgs*/,
+                        null/*groupBy*/,
+                        null/*having*/,
+                        ORDER_BY_TIMESTAMP_DESC);
+            } catch (final SQLiteException e) {
+                LogUtil.e(TAG, "SyncCursorPair: failed to query local sms/mms", e);
+                // Can't query local database. So let's throw up the exception and abort sync
+                // because we may end up import duplicate messages.
+                throw e;
+            }
+        }
+
+        @Override
+        public DatabaseMessage next() {
+            if (mCursor != null && mCursor.moveToNext()) {
+                return getLocalDatabaseMessage(mCursor);
+            }
+            return null;
+        }
+
+        @Override
+        public int getCount() {
+            return (mCursor == null ? 0 : mCursor.getCount());
+        }
+
+        @Override
+        public int getPosition() {
+            return (mCursor == null ? 0 : mCursor.getPosition());
+        }
+
+        @Override
+        public void close() {
+            if (mCursor != null) {
+                mCursor.close();
+                mCursor = null;
+            }
+        }
+    }
+
+    /**
+     * The cursor iterator for remote sms.
+     * Since SMS and MMS are stored in different tables in telephony provider,
+     * this class merges the two cursors and provides a unified view of messages
+     * from both cursors. Note that the order is DESC.
+     */
+    private static class RemoteCursorsIterator implements CursorIterator {
+        private Cursor mSmsCursor;
+        private Cursor mMmsCursor;
+        private DatabaseMessage mNextSms;
+        private DatabaseMessage mNextMms;
+
+        RemoteCursorsIterator(final String smsSelection, final String mmsSelection)
+                throws SQLiteException {
+            mSmsCursor = null;
+            mMmsCursor = null;
+            try {
+                final Context context = Factory.get().getApplicationContext();
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "SyncCursorPair: Querying for remote SMS; selection = "
+                            + smsSelection);
+                }
+                mSmsCursor = SqliteWrapper.query(
+                        context,
+                        context.getContentResolver(),
+                        Sms.CONTENT_URI,
+                        SmsMessage.getProjection(),
+                        smsSelection,
+                        null /* selectionArgs */,
+                        ORDER_BY_DATE_DESC);
+                if (mSmsCursor == null) {
+                    LogUtil.w(TAG, "SyncCursorPair: Remote SMS query returned null cursor; "
+                            + "need to cancel sync");
+                    throw new RuntimeException("Null cursor from remote SMS query");
+                }
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "SyncCursorPair: Querying for remote MMS; selection = "
+                            + mmsSelection);
+                }
+                mMmsCursor = SqliteWrapper.query(
+                        context,
+                        context.getContentResolver(),
+                        Mms.CONTENT_URI,
+                        DatabaseMessages.MmsMessage.getProjection(),
+                        mmsSelection,
+                        null /* selectionArgs */,
+                        ORDER_BY_DATE_DESC);
+                if (mMmsCursor == null) {
+                    LogUtil.w(TAG, "SyncCursorPair: Remote MMS query returned null cursor; "
+                            + "need to cancel sync");
+                    throw new RuntimeException("Null cursor from remote MMS query");
+                }
+                // Move to the first element in the combined stream from both cursors
+                mNextSms = getSmsCursorNext();
+                mNextMms = getMmsCursorNext();
+            } catch (final SQLiteException e) {
+                LogUtil.e(TAG, "SyncCursorPair: failed to query remote messages", e);
+                // If we ignore this, the following code would think there is no remote message
+                // and will delete all the local sms. We should be cautious here. So instead,
+                // let's throw the exception to the caller and abort sms sync. We do the same
+                // thing if either of the remote cursors is null.
+                throw e;
+            }
+        }
+
+        @Override
+        public DatabaseMessage next() {
+            DatabaseMessage result = null;
+            if (mNextSms != null && mNextMms != null) {
+                if (mNextSms.getTimestampInMillis() >= mNextMms.getTimestampInMillis()) {
+                    result = mNextSms;
+                    mNextSms = getSmsCursorNext();
+                } else {
+                    result = mNextMms;
+                    mNextMms = getMmsCursorNext();
+                }
+            } else {
+                if (mNextSms != null) {
+                    result = mNextSms;
+                    mNextSms = getSmsCursorNext();
+                } else {
+                    result = mNextMms;
+                    mNextMms = getMmsCursorNext();
+                }
+            }
+            return result;
+        }
+
+        private DatabaseMessage getSmsCursorNext() {
+            if (mSmsCursor != null && mSmsCursor.moveToNext()) {
+                return SmsMessage.get(mSmsCursor);
+            }
+            return null;
+        }
+
+        private DatabaseMessage getMmsCursorNext() {
+            if (mMmsCursor != null && mMmsCursor.moveToNext()) {
+                return MmsMessage.get(mMmsCursor);
+            }
+            return null;
+        }
+
+        @Override
+        // Return approximate cursor position allowing for read ahead on two cursors (hence -1)
+        public int getPosition() {
+            return (mSmsCursor == null ? 0 : mSmsCursor.getPosition()) +
+                    (mMmsCursor == null ? 0 : mMmsCursor.getPosition()) - 1;
+        }
+
+        @Override
+        public int getCount() {
+            return (mSmsCursor == null ? 0 : mSmsCursor.getCount()) +
+                    (mMmsCursor == null ? 0 : mMmsCursor.getCount());
+        }
+
+        @Override
+        public void close() {
+            if (mSmsCursor != null) {
+                mSmsCursor.close();
+                mSmsCursor = null;
+            }
+            if (mMmsCursor != null) {
+                mMmsCursor.close();
+                mMmsCursor = null;
+            }
+        }
+    }
+
+    /**
+     * Type selection for importing sms messages. Only SENT and INBOX messages are imported.
+     *
+     * @return The SQL selection for importing sms messages
+     */
+    public static String getSmsTypeSelectionSql() {
+        return MmsUtils.getSmsTypeSelectionSql();
+    }
+
+    /**
+     * Type selection for importing mms messages.
+     *
+     * Criteria:
+     * MESSAGE_BOX is INBOX, SENT or OUTBOX
+     * MESSAGE_TYPE is SEND_REQ (sent), RETRIEVE_CONF (received) or NOTIFICATION_IND (download)
+     *
+     * @return The SQL selection for importing mms messages. This selects the message type,
+     * not including the selection on timestamp.
+     */
+    public static String getMmsTypeSelectionSql() {
+        return MmsUtils.getMmsTypeSelectionSql();
+    }
+
+    /**
+     * Get a SQL selection string using an existing selection and time window limits
+     * The limits are not applied if the value is < 0
+     *
+     * @param typeSelection The existing selection
+     * @param from The inclusive lower bound
+     * @param to The exclusive upper bound
+     * @return The created SQL selection
+     */
+    private static String getTimeConstrainedQuery(final String typeSelection,
+            final String timeColumn, final long from, final long to,
+            final String threadColumn, final String threadId) {
+        final StringBuilder queryBuilder = new StringBuilder();
+        queryBuilder.append(typeSelection);
+        if (from > 0) {
+            queryBuilder.append(" AND ").append(timeColumn).append(">=").append(from);
+        }
+        if (to > 0) {
+            queryBuilder.append(" AND ").append(timeColumn).append("<").append(to);
+        }
+        if (!TextUtils.isEmpty(threadColumn) && !TextUtils.isEmpty(threadId)) {
+            queryBuilder.append(" AND ").append(threadColumn).append("=").append(threadId);
+        }
+        return queryBuilder.toString();
+    }
+
+    private static final String[] COUNT_PROJECTION = new String[] { "count()" };
+
+    private static int getCountFromCursor(final Cursor cursor) {
+        if (cursor != null && cursor.moveToFirst()) {
+            return cursor.getInt(0);
+        }
+        // We should only return a number if we were able to read it from the cursor.
+        // Otherwise, we throw an exception to cancel the sync.
+        String cursorDesc = "";
+        if (cursor == null) {
+            cursorDesc = "null";
+        } else if (cursor.getCount() == 0) {
+            cursorDesc = "empty";
+        }
+        throw new IllegalArgumentException("Cannot get count from " + cursorDesc + " cursor");
+    }
+
+    private void saveMessageToAdd(final List<SmsMessage> smsToAdd,
+            final LongSparseArray<MmsMessage> mmsToAdd, final DatabaseMessage message,
+            final ThreadInfoCache threadInfoCache) {
+        long threadId;
+        if (message.getProtocol() == MessageData.PROTOCOL_MMS) {
+            final MmsMessage mms = (MmsMessage) message;
+            mmsToAdd.append(mms.getId(), mms);
+            threadId = mms.mThreadId;
+        } else {
+            final SmsMessage sms = (SmsMessage) message;
+            smsToAdd.add(sms);
+            threadId = sms.mThreadId;
+        }
+        // Cache the lookup and canonicalization of the phone number outside of the transaction...
+        threadInfoCache.getThreadRecipients(threadId);
+    }
+
+    /**
+     * Check if SMS has been synchronized. We compare the counts of messages on both
+     * sides and return true if they are equal.
+     *
+     * Note that this may not be the most reliable way to tell if messages are in sync.
+     * For example, the local misses one message and has one obsolete message.
+     * However, we have background sms sync once a while, also some other events might
+     * trigger a full sync. So we will eventually catch up. And this should be rare to
+     * happen.
+     *
+     * @return If sms is in sync with telephony sms/mms providers
+     */
+    private static boolean isSynchronized(final DatabaseWrapper db, final String localSelection,
+            final String[] localSelectionArgs, final String smsSelection,
+            final String[] smsSelectionArgs, final String mmsSelection,
+            final String[] mmsSelectionArgs) {
+        final Context context = Factory.get().getApplicationContext();
+        Cursor localCursor = null;
+        Cursor remoteSmsCursor = null;
+        Cursor remoteMmsCursor = null;
+        try {
+            localCursor = db.query(
+                    DatabaseHelper.MESSAGES_TABLE,
+                    COUNT_PROJECTION,
+                    localSelection,
+                    localSelectionArgs,
+                    null/*groupBy*/,
+                    null/*having*/,
+                    null/*orderBy*/);
+            final int localCount = getCountFromCursor(localCursor);
+            remoteSmsCursor = SqliteWrapper.query(
+                    context,
+                    context.getContentResolver(),
+                    Sms.CONTENT_URI,
+                    COUNT_PROJECTION,
+                    smsSelection,
+                    smsSelectionArgs,
+                    null/*orderBy*/);
+            final int smsCount = getCountFromCursor(remoteSmsCursor);
+            remoteMmsCursor = SqliteWrapper.query(
+                    context,
+                    context.getContentResolver(),
+                    Mms.CONTENT_URI,
+                    COUNT_PROJECTION,
+                    mmsSelection,
+                    mmsSelectionArgs,
+                    null/*orderBy*/);
+            final int mmsCount = getCountFromCursor(remoteMmsCursor);
+            final int remoteCount = smsCount + mmsCount;
+            final boolean isInSync = (localCount == remoteCount);
+            if (isInSync) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SyncCursorPair: Same # of local and remote messages = "
+                            + localCount);
+                }
+            } else {
+                LogUtil.i(TAG, "SyncCursorPair: Not in sync; # local messages = " + localCount
+                        + ", # remote message = " + remoteCount);
+            }
+            return isInSync;
+        } catch (final Exception e) {
+            LogUtil.e(TAG, "SyncCursorPair: failed to query local or remote message counts", e);
+            // If something is wrong in querying database, assume we are synced so
+            // we don't retry indefinitely
+        } finally {
+            if (localCursor != null) {
+                localCursor.close();
+            }
+            if (remoteSmsCursor != null) {
+                remoteSmsCursor.close();
+            }
+            if (remoteMmsCursor != null) {
+                remoteMmsCursor.close();
+            }
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/SyncMessageBatch.java b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java
new file mode 100644
index 0000000..a623666
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteConstraintException;
+import android.provider.Telephony;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Sms;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.SyncManager.ThreadInfoCache;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.sms.DatabaseMessages.LocalDatabaseMessage;
+import com.android.messaging.sms.DatabaseMessages.MmsMessage;
+import com.android.messaging.sms.DatabaseMessages.SmsMessage;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Update local database with a batch of messages to add/delete in one transaction
+ */
+class SyncMessageBatch {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    // Variables used during executeAction
+    private final HashSet<String> mConversationsToUpdate;
+    // Cache of thread->conversationId map
+    private final ThreadInfoCache mCache;
+
+    // Set of SMS messages to add
+    private final ArrayList<SmsMessage> mSmsToAdd;
+    // Set of MMS messages to add
+    private final ArrayList<MmsMessage> mMmsToAdd;
+    // Set of local messages to delete
+    private final ArrayList<LocalDatabaseMessage> mMessagesToDelete;
+
+    SyncMessageBatch(final ArrayList<SmsMessage> smsToAdd,
+            final ArrayList<MmsMessage> mmsToAdd,
+            final ArrayList<LocalDatabaseMessage> messagesToDelete,
+            final ThreadInfoCache cache) {
+        mSmsToAdd = smsToAdd;
+        mMmsToAdd = mmsToAdd;
+        mMessagesToDelete = messagesToDelete;
+        mCache = cache;
+        mConversationsToUpdate = new HashSet<String>();
+    }
+
+    void updateLocalDatabase() {
+        // Perform local database changes in one transaction
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            // Store all the SMS messages
+            for (final SmsMessage sms : mSmsToAdd) {
+                storeSms(db, sms);
+            }
+            // Store all the MMS messages
+            for (final MmsMessage mms : mMmsToAdd) {
+                storeMms(db, mms);
+            }
+            // Keep track of conversations with messages deleted
+            for (final LocalDatabaseMessage message : mMessagesToDelete) {
+                mConversationsToUpdate.add(message.getConversationId());
+            }
+            // Batch delete local messages
+            batchDelete(db, DatabaseHelper.MESSAGES_TABLE, MessageColumns._ID,
+                    messageListToIds(mMessagesToDelete));
+
+            for (final LocalDatabaseMessage message : mMessagesToDelete) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "SyncMessageBatch: Deleted message " + message.getLocalId()
+                            + " for SMS/MMS " + message.getUri() + " with timestamp "
+                            + message.getTimestampInMillis());
+                }
+            }
+
+            // Update conversation state for imported messages, like snippet,
+            updateConversations(db);
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    private static String[] messageListToIds(final List<LocalDatabaseMessage> messagesToDelete) {
+        final String[] ids = new String[messagesToDelete.size()];
+        for (int i = 0; i < ids.length; i++) {
+            ids[i] = Long.toString(messagesToDelete.get(i).getLocalId());
+        }
+        return ids;
+    }
+
+    /**
+     * Store the SMS message into local database.
+     *
+     * @param sms
+     */
+    private void storeSms(final DatabaseWrapper db, final SmsMessage sms) {
+        if (sms.mBody == null) {
+            LogUtil.w(TAG, "SyncMessageBatch: SMS " + sms.mUri + " has no body; adding empty one");
+            // try to fix it
+            sms.mBody = "";
+        }
+
+        if (TextUtils.isEmpty(sms.mAddress)) {
+            LogUtil.e(TAG, "SyncMessageBatch: SMS has no address; using unknown sender");
+            // try to fix it
+            sms.mAddress = ParticipantData.getUnknownSenderDestination();
+        }
+
+        // TODO : We need to also deal with messages in a failed/retry state
+        final boolean isOutgoing = sms.mType != Sms.MESSAGE_TYPE_INBOX;
+
+        final String otherPhoneNumber = sms.mAddress;
+
+        // A forced resync of all messages should still keep the archived states.
+        // The database upgrade code notifies sync manager of this. We need to
+        // honor the original customization to this conversation if created.
+        final String conversationId = mCache.getOrCreateConversation(db, sms.mThreadId, sms.mSubId,
+                DataModel.get().getSyncManager().getCustomizationForThread(sms.mThreadId));
+        if (conversationId == null) {
+            // Cannot create conversation for this message? This should not happen.
+            LogUtil.e(TAG, "SyncMessageBatch: Failed to create conversation for SMS thread "
+                    + sms.mThreadId);
+            return;
+        }
+        final ParticipantData self = ParticipantData.getSelfParticipant(sms.getSubId());
+        final String selfId =
+                BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+        final ParticipantData sender = isOutgoing ?
+                self :
+                ParticipantData.getFromRawPhoneBySimLocale(otherPhoneNumber, sms.getSubId());
+        final String participantId = (isOutgoing ? selfId :
+                BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, sender));
+
+        final int bugleStatus = bugleStatusForSms(isOutgoing, sms.mType, sms.mStatus);
+
+        final MessageData message = MessageData.createSmsMessage(
+                sms.mUri,
+                participantId,
+                selfId,
+                conversationId,
+                bugleStatus,
+                sms.mSeen,
+                sms.mRead,
+                sms.mTimestampSentInMillis,
+                sms.mTimestampInMillis,
+                sms.mBody);
+
+        // Inserting sms content into messages table
+        try {
+            BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+        } catch (SQLiteConstraintException e) {
+            rethrowSQLiteConstraintExceptionWithDetails(e, db, sms.mUri, sms.mThreadId,
+                    conversationId, selfId, participantId);
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "SyncMessageBatch: Inserted new message " + message.getMessageId()
+                    + " for SMS " + message.getSmsMessageUri() + " received at "
+                    + message.getReceivedTimeStamp());
+        }
+
+        // Keep track of updated conversation for later updating the conversation snippet, etc.
+        mConversationsToUpdate.add(conversationId);
+    }
+
+    public static int bugleStatusForSms(final boolean isOutgoing, final int type,
+            final int status) {
+        int bugleStatus = MessageData.BUGLE_STATUS_UNKNOWN;
+        // For a message we sync either
+        if (isOutgoing) {
+            // Outgoing message not yet been sent
+            if (type == Telephony.Sms.MESSAGE_TYPE_FAILED
+                    || type == Telephony.Sms.MESSAGE_TYPE_OUTBOX
+                    || type == Telephony.Sms.MESSAGE_TYPE_QUEUED
+                    || (type == Telephony.Sms.MESSAGE_TYPE_SENT
+                            && status >= Telephony.Sms.STATUS_FAILED)) {
+                // Not sent counts as failed and available for manual resend
+                bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_FAILED;
+            } else if (status == Sms.STATUS_COMPLETE) {
+                bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_DELIVERED;
+            } else {
+                // Otherwise outgoing message is complete
+                bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_COMPLETE;
+            }
+        } else {
+            // All incoming SMS messages are complete
+            bugleStatus = MessageData.BUGLE_STATUS_INCOMING_COMPLETE;
+        }
+        return bugleStatus;
+    }
+
+    /**
+     * Store the MMS message into local database
+     *
+     * @param mms
+     */
+    private void storeMms(final DatabaseWrapper db, final MmsMessage mms) {
+        if (mms.mParts.size() < 1) {
+            LogUtil.w(TAG, "SyncMessageBatch: MMS " + mms.mUri + " has no parts");
+        }
+
+        // TODO : We need to also deal with messages in a failed/retry state
+        final boolean isOutgoing = mms.mType != Mms.MESSAGE_BOX_INBOX;
+        final boolean isNotification = (mms.mMmsMessageType ==
+                PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
+
+        final String senderId = mms.mSender;
+
+        // A forced resync of all messages should still keep the archived states.
+        // The database upgrade code notifies sync manager of this. We need to
+        // honor the original customization to this conversation if created.
+        final String conversationId = mCache.getOrCreateConversation(db, mms.mThreadId, mms.mSubId,
+                DataModel.get().getSyncManager().getCustomizationForThread(mms.mThreadId));
+        if (conversationId == null) {
+            LogUtil.e(TAG, "SyncMessageBatch: Failed to create conversation for MMS thread "
+                    + mms.mThreadId);
+            return;
+        }
+        final ParticipantData self = ParticipantData.getSelfParticipant(mms.getSubId());
+        final String selfId =
+                BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, self);
+        final ParticipantData sender = isOutgoing ?
+                self : ParticipantData.getFromRawPhoneBySimLocale(senderId, mms.getSubId());
+        final String participantId = (isOutgoing ? selfId :
+                BugleDatabaseOperations.getOrCreateParticipantInTransaction(db, sender));
+
+        final int bugleStatus = MmsUtils.bugleStatusForMms(isOutgoing, isNotification, mms.mType);
+
+        // Import message and all of the parts.
+        // TODO : For now we are importing these in the order we found them in the MMS
+        // database. Ideally we would load and parse the SMIL which describes how the parts relate
+        // to one another.
+
+        // TODO: Need to set correct status on message
+        final MessageData message = MmsUtils.createMmsMessage(mms, conversationId, participantId,
+                selfId, bugleStatus);
+
+        // Inserting mms content into messages table
+        try {
+            BugleDatabaseOperations.insertNewMessageInTransaction(db, message);
+        } catch (SQLiteConstraintException e) {
+            rethrowSQLiteConstraintExceptionWithDetails(e, db, mms.mUri, mms.mThreadId,
+                    conversationId, selfId, participantId);
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "SyncMessageBatch: Inserted new message " + message.getMessageId()
+                    + " for MMS " + message.getSmsMessageUri() + " received at "
+                    + message.getReceivedTimeStamp());
+        }
+
+        // Keep track of updated conversation for later updating the conversation snippet, etc.
+        mConversationsToUpdate.add(conversationId);
+    }
+
+    // TODO: Remove this after we no longer see this crash (b/18375758)
+    private static void rethrowSQLiteConstraintExceptionWithDetails(SQLiteConstraintException e,
+            DatabaseWrapper db, String messageUri, long threadId, String conversationId,
+            String selfId, String senderId) {
+        // Add some extra debug information to the exception for tracking down b/18375758.
+        // The default detail message for SQLiteConstraintException tells us that a foreign
+        // key constraint failed, but not which one! Messages have foreign keys to 3 tables:
+        // conversations, participants (self), participants (sender). We'll query each one
+        // to determine which one(s) violated the constraint, and then throw a new exception
+        // with those details.
+
+        String foundConversationId = null;
+        Cursor cursor = null;
+        try {
+            // Look for an existing conversation in the db with the conversation id
+            cursor = db.rawQuery("SELECT " + ConversationColumns._ID
+                    + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE
+                    + " WHERE " + ConversationColumns._ID + "=" + conversationId,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+                Assert.isTrue(cursor.getCount() == 1);
+                foundConversationId = cursor.getString(0);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        ParticipantData foundSelfParticipant =
+                BugleDatabaseOperations.getExistingParticipant(db, selfId);
+        ParticipantData foundSenderParticipant =
+                BugleDatabaseOperations.getExistingParticipant(db, senderId);
+
+        String errorMsg = "SQLiteConstraintException while inserting message for " + messageUri
+                + "; conversation id from getOrCreateConversation = " + conversationId
+                + " (lookup thread = " + threadId + "), found conversation id = "
+                + foundConversationId + ", found self participant = "
+                + LogUtil.sanitizePII(foundSelfParticipant.getNormalizedDestination())
+                + " (lookup id = " + selfId + "), found sender participant = "
+                + LogUtil.sanitizePII(foundSenderParticipant.getNormalizedDestination())
+                + " (lookup id = " + senderId + ")";
+        throw new RuntimeException(errorMsg, e);
+    }
+
+    /**
+     * Use the tracked latest message info to update conversations, including
+     * latest chat message and sort timestamp.
+     */
+    private void updateConversations(final DatabaseWrapper db) {
+        for (final String conversationId : mConversationsToUpdate) {
+            if (BugleDatabaseOperations.deleteConversationIfEmptyInTransaction(db,
+                    conversationId)) {
+                continue;
+            }
+
+            final boolean archived = mCache.isArchived(conversationId);
+            // Always attempt to auto-switch conversation self id for sync/import case.
+            BugleDatabaseOperations.maybeRefreshConversationMetadataInTransaction(db,
+                    conversationId, true /*shouldAutoSwitchSelfId*/, archived /*keepArchived*/);
+        }
+    }
+
+
+    /**
+     * Batch delete database rows by matching a column with a list of values, usually some
+     * kind of IDs.
+     *
+     * @param table
+     * @param column
+     * @param ids
+     * @return Total number of deleted messages
+     */
+    private static int batchDelete(final DatabaseWrapper db, final String table,
+            final String column, final String[] ids) {
+        int totalDeleted = 0;
+        final int totalIds = ids.length;
+        for (int start = 0; start < totalIds; start += MmsUtils.MAX_IDS_PER_QUERY) {
+            final int end = Math.min(start + MmsUtils.MAX_IDS_PER_QUERY, totalIds); //excluding
+            final int count = end - start;
+            final String batchSelection = String.format(
+                    Locale.US,
+                    "%s IN %s",
+                    column,
+                    MmsUtils.getSqlInOperand(count));
+            final String[] batchSelectionArgs = Arrays.copyOfRange(ids, start, end);
+            final int deleted = db.delete(
+                    table,
+                    batchSelection,
+                    batchSelectionArgs);
+            totalDeleted += deleted;
+        }
+        return totalDeleted;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/SyncMessagesAction.java b/src/com/android/messaging/datamodel/action/SyncMessagesAction.java
new file mode 100644
index 0000000..a11d5bb
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/SyncMessagesAction.java
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.provider.Telephony.Mms;
+import androidx.collection.LongSparseArray;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.SyncManager.ThreadInfoCache;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.sms.DatabaseMessages;
+import com.android.messaging.sms.DatabaseMessages.LocalDatabaseMessage;
+import com.android.messaging.sms.DatabaseMessages.MmsMessage;
+import com.android.messaging.sms.DatabaseMessages.SmsMessage;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Action used to sync messages from smsmms db to local database
+ */
+public class SyncMessagesAction extends Action implements Parcelable {
+    static final long SYNC_FAILED = Long.MIN_VALUE;
+
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    private static final String KEY_START_TIMESTAMP = "start_timestamp";
+    private static final String KEY_MAX_UPDATE = "max_update";
+    private static final String KEY_LOWER_BOUND = "lower_bound";
+    private static final String KEY_UPPER_BOUND = "upper_bound";
+    private static final String BUNDLE_KEY_LAST_TIMESTAMP = "last_timestamp";
+    private static final String BUNDLE_KEY_SMS_MESSAGES = "sms_to_add";
+    private static final String BUNDLE_KEY_MMS_MESSAGES = "mms_to_add";
+    private static final String BUNDLE_KEY_MESSAGES_TO_DELETE = "messages_to_delete";
+
+    /**
+     * Start a full sync (backed off a few seconds to avoid pulling sending/receiving messages).
+     */
+    public static void fullSync() {
+        final BugleGservices bugleGservices = BugleGservices.get();
+        final long smsSyncBackoffTimeMillis = bugleGservices.getLong(
+                BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS,
+                BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
+
+        final long now = System.currentTimeMillis();
+        // TODO: Could base this off most recent message in db but now should be okay...
+        final long startTimestamp = now - smsSyncBackoffTimeMillis;
+
+        final SyncMessagesAction action = new SyncMessagesAction(-1L, startTimestamp,
+                0, startTimestamp);
+        action.start();
+    }
+
+    /**
+     * Start an incremental sync to pull messages since last sync (backed off a few seconds)..
+     */
+    public static void sync() {
+        final BugleGservices bugleGservices = BugleGservices.get();
+        final long smsSyncBackoffTimeMillis = bugleGservices.getLong(
+                BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS,
+                BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
+
+        final long now = System.currentTimeMillis();
+        // TODO: Could base this off most recent message in db but now should be okay...
+        final long startTimestamp = now - smsSyncBackoffTimeMillis;
+
+        sync(startTimestamp);
+    }
+
+    /**
+     * Start an incremental sync when the application starts up (no back off as not yet
+     *  sending/receiving).
+     */
+    public static void immediateSync() {
+        final long now = System.currentTimeMillis();
+        // TODO: Could base this off most recent message in db but now should be okay...
+        final long startTimestamp = now;
+
+        sync(startTimestamp);
+    }
+
+    private static void sync(final long startTimestamp) {
+        if (!OsUtil.hasSmsPermission()) {
+            // Sync requires READ_SMS permission
+            return;
+        }
+
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        // Lower bound is end of previous sync
+        final long syncLowerBoundTimeMillis = prefs.getLong(BuglePrefsKeys.LAST_SYNC_TIME,
+                    BuglePrefsKeys.LAST_SYNC_TIME_DEFAULT);
+
+        final SyncMessagesAction action = new SyncMessagesAction(syncLowerBoundTimeMillis,
+                startTimestamp, 0, startTimestamp);
+        action.start();
+    }
+
+    private SyncMessagesAction(final long lowerBound, final long upperBound,
+            final int maxMessagesToUpdate, final long startTimestamp) {
+        actionParameters.putLong(KEY_LOWER_BOUND, lowerBound);
+        actionParameters.putLong(KEY_UPPER_BOUND, upperBound);
+        actionParameters.putInt(KEY_MAX_UPDATE, maxMessagesToUpdate);
+        actionParameters.putLong(KEY_START_TIMESTAMP, startTimestamp);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND);
+        final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND);
+        final int initialMaxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE);
+        final long startTimestamp = actionParameters.getLong(KEY_START_TIMESTAMP);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncMessagesAction: Request to sync messages from "
+                    + lowerBoundTimeMillis + " to " + upperBoundTimeMillis + " (start timestamp = "
+                    + startTimestamp + ", message update limit = " + initialMaxMessagesToUpdate
+                    + ")");
+        }
+
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        if (lowerBoundTimeMillis >= 0) {
+            // Cursors
+            final SyncCursorPair cursors = new SyncCursorPair(-1L, lowerBoundTimeMillis);
+            final boolean inSync = cursors.isSynchronized(db);
+            if (!inSync) {
+                if (syncManager.delayUntilFullSync(startTimestamp) == 0) {
+                    lowerBoundTimeMillis = -1;
+                    actionParameters.putLong(KEY_LOWER_BOUND, lowerBoundTimeMillis);
+
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "SyncMessagesAction: Messages before "
+                                + lowerBoundTimeMillis + " not in sync; promoting to full sync");
+                    }
+                } else if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SyncMessagesAction: Messages before "
+                            + lowerBoundTimeMillis + " not in sync; will do incremental sync");
+                }
+            } else {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SyncMessagesAction: Messages before " + lowerBoundTimeMillis
+                            + " are in sync");
+                }
+            }
+        }
+
+        // Check if sync allowed (can be too soon after last or one is already running)
+        if (syncManager.shouldSync(lowerBoundTimeMillis < 0, startTimestamp)) {
+            syncManager.startSyncBatch(upperBoundTimeMillis);
+            requestBackgroundWork();
+        }
+
+        return null;
+    }
+
+    @Override
+    protected Bundle doBackgroundWork() {
+        final BugleGservices bugleGservices = BugleGservices.get();
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final int maxMessagesToScan = bugleGservices.getInt(
+                BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN,
+                BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT);
+
+        final int initialMaxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE);
+        final int smsSyncSubsequentBatchSizeMin = bugleGservices.getInt(
+                BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN,
+                BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN_DEFAULT);
+        final int smsSyncSubsequentBatchSizeMax = bugleGservices.getInt(
+                BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX,
+                BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX_DEFAULT);
+
+        // Cap sync size to GServices limits
+        final int maxMessagesToUpdate = Math.max(smsSyncSubsequentBatchSizeMin,
+                Math.min(initialMaxMessagesToUpdate, smsSyncSubsequentBatchSizeMax));
+
+        final long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND);
+        final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND);
+
+        LogUtil.i(TAG, "SyncMessagesAction: Starting batch for messages from "
+                + lowerBoundTimeMillis + " to " + upperBoundTimeMillis
+                + " (message update limit = " + maxMessagesToUpdate + ", message scan limit = "
+                + maxMessagesToScan + ")");
+
+        // Clear last change time so that we can work out if this batch is dirty when it completes
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+
+        // Clear the singleton cache that maps threads to recipients and to conversations.
+        final SyncManager.ThreadInfoCache cache = syncManager.getThreadInfoCache();
+        cache.clear();
+
+        // Sms messages to store
+        final ArrayList<SmsMessage> smsToAdd = new ArrayList<SmsMessage>();
+        // Mms messages to store
+        final LongSparseArray<MmsMessage> mmsToAdd = new LongSparseArray<MmsMessage>();
+        // List of local SMS/MMS to remove
+        final ArrayList<LocalDatabaseMessage> messagesToDelete =
+                new ArrayList<LocalDatabaseMessage>();
+
+        long lastTimestampMillis = SYNC_FAILED;
+        if (syncManager.isSyncing(upperBoundTimeMillis)) {
+            // Cursors
+            final SyncCursorPair cursors = new SyncCursorPair(lowerBoundTimeMillis,
+                    upperBoundTimeMillis);
+
+            // Actually compare the messages using cursor pair
+            lastTimestampMillis = syncCursorPair(db, cursors, smsToAdd, mmsToAdd,
+                    messagesToDelete, maxMessagesToScan, maxMessagesToUpdate, cache);
+        }
+        final Bundle response = new Bundle();
+
+        // If comparison succeeds bundle up the changes for processing in ActionService
+        if (lastTimestampMillis > SYNC_FAILED) {
+            final ArrayList<MmsMessage> mmsToAddList = new ArrayList<MmsMessage>();
+            for (int i = 0; i < mmsToAdd.size(); i++) {
+                final MmsMessage mms = mmsToAdd.valueAt(i);
+                mmsToAddList.add(mms);
+            }
+
+            response.putParcelableArrayList(BUNDLE_KEY_SMS_MESSAGES, smsToAdd);
+            response.putParcelableArrayList(BUNDLE_KEY_MMS_MESSAGES, mmsToAddList);
+            response.putParcelableArrayList(BUNDLE_KEY_MESSAGES_TO_DELETE, messagesToDelete);
+        }
+        response.putLong(BUNDLE_KEY_LAST_TIMESTAMP, lastTimestampMillis);
+
+        return response;
+    }
+
+    /**
+     * Compare messages based on timestamp and uri
+     * @param db local database wrapper
+     * @param cursors cursor pair holding references to local and remote messages
+     * @param smsToAdd newly found sms messages to add
+     * @param mmsToAdd newly found mms messages to add
+     * @param messagesToDelete messages not found needing deletion
+     * @param maxMessagesToScan max messages to scan for changes
+     * @param maxMessagesToUpdate max messages to return for updates
+     * @param cache cache for conversation id / thread id / recipient set mapping
+     * @return timestamp of the oldest message seen during the sync scan
+     */
+    private long syncCursorPair(final DatabaseWrapper db, final SyncCursorPair cursors,
+            final ArrayList<SmsMessage> smsToAdd, final LongSparseArray<MmsMessage> mmsToAdd,
+            final ArrayList<LocalDatabaseMessage> messagesToDelete, final int maxMessagesToScan,
+            final int maxMessagesToUpdate, final ThreadInfoCache cache) {
+        long lastTimestampMillis;
+        final long startTimeMillis = SystemClock.elapsedRealtime();
+
+        // Number of messages scanned local and remote
+        int localPos = 0;
+        int remotePos = 0;
+        int localTotal = 0;
+        int remoteTotal = 0;
+        // Scan through the messages on both sides and prepare messages for local message table
+        // changes (including adding and deleting)
+        try {
+            cursors.query(db);
+
+            localTotal = cursors.getLocalCount();
+            remoteTotal = cursors.getRemoteCount();
+
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "SyncMessagesAction: Scanning cursors (local count = " + localTotal
+                        + ", remote count = " + remoteTotal + ", message update limit = "
+                        + maxMessagesToUpdate + ", message scan limit = " + maxMessagesToScan
+                        + ")");
+            }
+
+            lastTimestampMillis = cursors.scan(maxMessagesToScan, maxMessagesToUpdate,
+                    smsToAdd, mmsToAdd, messagesToDelete, cache);
+
+            localPos = cursors.getLocalPosition();
+            remotePos = cursors.getRemotePosition();
+
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "SyncMessagesAction: Scanned cursors (local position = " + localPos
+                        + " of " + localTotal + ", remote position = " + remotePos + " of "
+                        + remoteTotal + ")");
+            }
+
+            // Batch loading the parts of the MMS messages in this batch
+            loadMmsParts(mmsToAdd);
+            // Lookup senders for incoming mms messages
+            setMmsSenders(mmsToAdd, cache);
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "SyncMessagesAction: Database exception", e);
+            // Let's abort
+            lastTimestampMillis = SYNC_FAILED;
+        } catch (final Exception e) {
+            // We want to catch anything unexpected since this is running in a separate thread
+            // and any unexpected exception will just fail this thread silently.
+            // Let's crash for dogfooders!
+            LogUtil.wtf(TAG, "SyncMessagesAction: unexpected failure in scan", e);
+            lastTimestampMillis = SYNC_FAILED;
+        } finally {
+            if (cursors != null) {
+                cursors.close();
+            }
+        }
+
+        final long endTimeMillis = SystemClock.elapsedRealtime();
+
+        if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+            LogUtil.d(TAG, "SyncMessagesAction: Scan complete (took "
+                    + (endTimeMillis - startTimeMillis) + " ms). " + smsToAdd.size()
+                    + " remote SMS to add, " + mmsToAdd.size() + " MMS to add, "
+                    + messagesToDelete.size() + " local messages to delete. "
+                    + "Oldest timestamp seen = " + lastTimestampMillis);
+        }
+
+        return lastTimestampMillis;
+    }
+
+    /**
+     * Perform local database updates and schedule follow on sync actions
+     */
+    @Override
+    protected Object processBackgroundResponse(final Bundle response) {
+        final long lastTimestampMillis = response.getLong(BUNDLE_KEY_LAST_TIMESTAMP);
+        final long lowerBoundTimeMillis = actionParameters.getLong(KEY_LOWER_BOUND);
+        final long upperBoundTimeMillis = actionParameters.getLong(KEY_UPPER_BOUND);
+        final int maxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE);
+        final long startTimestamp = actionParameters.getLong(KEY_START_TIMESTAMP);
+
+        // Check with the sync manager if any conflicting updates have been made to databases
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        final boolean orphan = !syncManager.isSyncing(upperBoundTimeMillis);
+
+        // lastTimestampMillis used to indicate failure
+        if (orphan) {
+            // This batch does not match current in progress timestamp.
+            LogUtil.w(TAG, "SyncMessagesAction: Ignoring orphan sync batch for messages from "
+                    + lowerBoundTimeMillis + " to " + upperBoundTimeMillis);
+        } else {
+            final boolean dirty = syncManager.isBatchDirty(lastTimestampMillis);
+            if (lastTimestampMillis == SYNC_FAILED) {
+                LogUtil.e(TAG, "SyncMessagesAction: Sync failed - terminating");
+
+                // Failed - update last sync times to throttle our failure rate
+                final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+                // Save sync completion time so next sync will start from here
+                prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, startTimestamp);
+                // Remember last full sync so that don't start background full sync right away
+                prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, startTimestamp);
+
+                syncManager.complete();
+            } else if (dirty) {
+                LogUtil.w(TAG, "SyncMessagesAction: Redoing dirty sync batch of messages from "
+                        + lowerBoundTimeMillis + " to " + upperBoundTimeMillis);
+
+                // Redo this batch
+                final SyncMessagesAction nextBatch =
+                        new SyncMessagesAction(lowerBoundTimeMillis, upperBoundTimeMillis,
+                                maxMessagesToUpdate, startTimestamp);
+
+                syncManager.startSyncBatch(upperBoundTimeMillis);
+                requestBackgroundWork(nextBatch);
+            } else {
+                // Succeeded
+                final ArrayList<SmsMessage> smsToAdd =
+                        response.getParcelableArrayList(BUNDLE_KEY_SMS_MESSAGES);
+                final ArrayList<MmsMessage> mmsToAdd =
+                        response.getParcelableArrayList(BUNDLE_KEY_MMS_MESSAGES);
+                final ArrayList<LocalDatabaseMessage> messagesToDelete =
+                        response.getParcelableArrayList(BUNDLE_KEY_MESSAGES_TO_DELETE);
+
+                final int messagesUpdated = smsToAdd.size() + mmsToAdd.size()
+                        + messagesToDelete.size();
+
+                // Perform local database changes in one transaction
+                long txnTimeMillis = 0;
+                if (messagesUpdated > 0) {
+                    final long startTimeMillis = SystemClock.elapsedRealtime();
+                    final SyncMessageBatch batch = new SyncMessageBatch(smsToAdd, mmsToAdd,
+                            messagesToDelete, syncManager.getThreadInfoCache());
+                    batch.updateLocalDatabase();
+                    final long endTimeMillis = SystemClock.elapsedRealtime();
+                    txnTimeMillis = endTimeMillis - startTimeMillis;
+
+                    LogUtil.i(TAG, "SyncMessagesAction: Updated local database "
+                            + "(took " + txnTimeMillis + " ms). Added "
+                            + smsToAdd.size() + " SMS, added " + mmsToAdd.size() + " MMS, deleted "
+                            + messagesToDelete.size() + " messages.");
+
+                    // TODO: Investigate whether we can make this more fine-grained.
+                    MessagingContentProvider.notifyEverythingChanged();
+                } else {
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "SyncMessagesAction: No local database updates to make");
+                    }
+
+                    if (!syncManager.getHasFirstSyncCompleted()) {
+                        // If we have never completed a sync before (fresh install) and there are
+                        // no messages, still inform the UI of a change so it can update syncing
+                        // messages shown to the user
+                        MessagingContentProvider.notifyConversationListChanged();
+                        MessagingContentProvider.notifyPartsChanged();
+                    }
+                }
+                // Determine if there are more messages that need to be scanned
+                if (lastTimestampMillis >= 0 && lastTimestampMillis >= lowerBoundTimeMillis) {
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "SyncMessagesAction: More messages to sync; scheduling next "
+                                + "sync batch now.");
+                    }
+
+                    // Include final millisecond of last sync in next sync
+                    final long newUpperBoundTimeMillis = lastTimestampMillis + 1;
+                    final int newMaxMessagesToUpdate = nextBatchSize(messagesUpdated,
+                            txnTimeMillis);
+
+                    final SyncMessagesAction nextBatch =
+                            new SyncMessagesAction(lowerBoundTimeMillis, newUpperBoundTimeMillis,
+                                    newMaxMessagesToUpdate, startTimestamp);
+
+                    // Proceed with next batch
+                    syncManager.startSyncBatch(newUpperBoundTimeMillis);
+                    requestBackgroundWork(nextBatch);
+                } else {
+                    final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+                    // Save sync completion time so next sync will start from here
+                    prefs.putLong(BuglePrefsKeys.LAST_SYNC_TIME, startTimestamp);
+                    if (lowerBoundTimeMillis < 0) {
+                        // Remember last full sync so that don't start another full sync right away
+                        prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, startTimestamp);
+                    }
+
+                    final long now = System.currentTimeMillis();
+
+                    // After any sync check if new messages have arrived
+                    final SyncCursorPair recents = new SyncCursorPair(startTimestamp, now);
+                    final SyncCursorPair olders = new SyncCursorPair(-1L, startTimestamp);
+                    final DatabaseWrapper db = DataModel.get().getDatabase();
+                    if (!recents.isSynchronized(db)) {
+                        LogUtil.i(TAG, "SyncMessagesAction: Changed messages after sync; "
+                                + "scheduling an incremental sync now.");
+
+                        // Just add a new batch for recent messages
+                        final SyncMessagesAction nextBatch =
+                                new SyncMessagesAction(startTimestamp, now, 0, startTimestamp);
+                        syncManager.startSyncBatch(now);
+                        requestBackgroundWork(nextBatch);
+                        // After partial sync verify sync state
+                    } else if (lowerBoundTimeMillis >= 0 && !olders.isSynchronized(db)) {
+                        // Add a batch going back to start of time
+                        LogUtil.w(TAG, "SyncMessagesAction: Changed messages before sync batch; "
+                                + "scheduling a full sync now.");
+
+                        final SyncMessagesAction nextBatch =
+                                new SyncMessagesAction(-1L, startTimestamp, 0, startTimestamp);
+
+                        syncManager.startSyncBatch(startTimestamp);
+                        requestBackgroundWork(nextBatch);
+                    } else {
+                        LogUtil.i(TAG, "SyncMessagesAction: All messages now in sync");
+
+                        // All done, in sync
+                        syncManager.complete();
+                    }
+                }
+                // Either sync should be complete or we should have a follow up request
+                Assert.isTrue(hasBackgroundActions() || !syncManager.isSyncing());
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Decide the next batch size based on the stats we collected with past batch
+     * @param messagesUpdated number of messages updated in this batch
+     * @param txnTimeMillis time the transaction took in ms
+     * @return Target number of messages to sync for next batch
+     */
+    private static int nextBatchSize(final int messagesUpdated, final long txnTimeMillis) {
+        final BugleGservices bugleGservices = BugleGservices.get();
+        final long smsSyncSubsequentBatchTimeLimitMillis = bugleGservices.getLong(
+                BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS,
+                BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT);
+
+        if (txnTimeMillis <= 0) {
+            return 0;
+        }
+        // Number of messages we can sync within the batch time limit using
+        // the average sync time calculated based on the stats we collected
+        // in previous batch
+        return (int) ((double) (messagesUpdated) / (double) txnTimeMillis
+                        * smsSyncSubsequentBatchTimeLimitMillis);
+    }
+
+    /**
+     * Batch loading MMS parts for the messages in current batch
+     */
+    private void loadMmsParts(final LongSparseArray<MmsMessage> mmses) {
+        final Context context = Factory.get().getApplicationContext();
+        final int totalIds = mmses.size();
+        for (int start = 0; start < totalIds; start += MmsUtils.MAX_IDS_PER_QUERY) {
+            final int end = Math.min(start + MmsUtils.MAX_IDS_PER_QUERY, totalIds); //excluding
+            final int count = end - start;
+            final String batchSelection = String.format(
+                    Locale.US,
+                    "%s != '%s' AND %s IN %s",
+                    Mms.Part.CONTENT_TYPE,
+                    ContentType.APP_SMIL,
+                    Mms.Part.MSG_ID,
+                    MmsUtils.getSqlInOperand(count));
+            final String[] batchSelectionArgs = new String[count];
+            for (int i = 0; i < count; i++) {
+                batchSelectionArgs[i] = Long.toString(mmses.valueAt(start + i).getId());
+            }
+            final Cursor cursor = SqliteWrapper.query(
+                    context,
+                    context.getContentResolver(),
+                    MmsUtils.MMS_PART_CONTENT_URI,
+                    DatabaseMessages.MmsPart.PROJECTION,
+                    batchSelection,
+                    batchSelectionArgs,
+                    null/*sortOrder*/);
+            if (cursor != null) {
+                try {
+                    while (cursor.moveToNext()) {
+                        // Delay loading the media content for parsing for efficiency
+                        // TODO: load the media and fill in the dimensions when
+                        // we actually display it
+                        final DatabaseMessages.MmsPart part =
+                                DatabaseMessages.MmsPart.get(cursor, false/*loadMedia*/);
+                        final DatabaseMessages.MmsMessage mms = mmses.get(part.mMessageId);
+                        if (mms != null) {
+                            mms.addPart(part);
+                        }
+                    }
+                } finally {
+                    cursor.close();
+                }
+            }
+        }
+    }
+
+    /**
+     * Batch loading MMS sender for the messages in current batch
+     */
+    private void setMmsSenders(final LongSparseArray<MmsMessage> mmses,
+            final ThreadInfoCache cache) {
+        // Store all the MMS messages
+        for (int i = 0; i < mmses.size(); i++) {
+            final MmsMessage mms = mmses.valueAt(i);
+
+            final boolean isOutgoing = mms.mType != Mms.MESSAGE_BOX_INBOX;
+            String senderId = null;
+            if (!isOutgoing) {
+                // We only need to find out sender phone number for received message
+                senderId = getMmsSender(mms, cache);
+                if (senderId == null) {
+                    LogUtil.w(TAG, "SyncMessagesAction: Could not find sender of incoming MMS "
+                            + "message " + mms.getUri() + "; using 'unknown sender' instead");
+                    senderId = ParticipantData.getUnknownSenderDestination();
+                }
+            }
+            mms.setSender(senderId);
+        }
+    }
+
+    /**
+     * Find out the sender of an MMS message
+     */
+    private String getMmsSender(final MmsMessage mms, final ThreadInfoCache cache) {
+        final List<String> recipients = cache.getThreadRecipients(mms.mThreadId);
+        Assert.notNull(recipients);
+        Assert.isTrue(recipients.size() > 0);
+
+        if (recipients.size() == 1
+                && recipients.get(0).equals(ParticipantData.getUnknownSenderDestination())) {
+            LogUtil.w(TAG, "SyncMessagesAction: MMS message " + mms.mUri + " has unknown sender "
+                    + "(thread id = " + mms.mThreadId + ")");
+        }
+
+        return MmsUtils.getMmsSender(recipients, mms.mUri);
+    }
+
+    private SyncMessagesAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<SyncMessagesAction> CREATOR
+            = new Parcelable.Creator<SyncMessagesAction>() {
+        @Override
+        public SyncMessagesAction createFromParcel(final Parcel in) {
+            return new SyncMessagesAction(in);
+        }
+
+        @Override
+        public SyncMessagesAction[] newArray(final int size) {
+            return new SyncMessagesAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/UpdateConversationArchiveStatusAction.java b/src/com/android/messaging/datamodel/action/UpdateConversationArchiveStatusAction.java
new file mode 100644
index 0000000..066ad74
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/UpdateConversationArchiveStatusAction.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.util.Assert;
+
+public class UpdateConversationArchiveStatusAction extends Action {
+
+    public static void archiveConversation(final String conversationId) {
+        final UpdateConversationArchiveStatusAction action =
+                new UpdateConversationArchiveStatusAction(conversationId, true /* isArchive */);
+        action.start();
+    }
+
+    public static void unarchiveConversation(final String conversationId) {
+        final UpdateConversationArchiveStatusAction action =
+                new UpdateConversationArchiveStatusAction(conversationId, false /* isArchive */);
+        action.start();
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+    private static final String KEY_IS_ARCHIVE = "is_archive";
+
+    protected UpdateConversationArchiveStatusAction(
+            final String conversationId, final boolean isArchive) {
+        Assert.isTrue(!TextUtils.isEmpty(conversationId));
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+        actionParameters.putBoolean(KEY_IS_ARCHIVE, isArchive);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final boolean isArchived = actionParameters.getBoolean(KEY_IS_ARCHIVE);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            BugleDatabaseOperations.updateConversationArchiveStatusInTransaction(
+                    db, conversationId, isArchived);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        MessagingContentProvider.notifyConversationListChanged();
+        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
+        return null;
+    }
+
+    protected UpdateConversationArchiveStatusAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<UpdateConversationArchiveStatusAction> CREATOR
+            = new Parcelable.Creator<UpdateConversationArchiveStatusAction>() {
+        @Override
+        public UpdateConversationArchiveStatusAction createFromParcel(final Parcel in) {
+            return new UpdateConversationArchiveStatusAction(in);
+        }
+
+        @Override
+        public UpdateConversationArchiveStatusAction[] newArray(final int size) {
+            return new UpdateConversationArchiveStatusAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/UpdateConversationOptionsAction.java b/src/com/android/messaging/datamodel/action/UpdateConversationOptionsAction.java
new file mode 100644
index 0000000..6c9e739
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/UpdateConversationOptionsAction.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.util.Assert;
+
+/**
+ * Action used to update conversation options such as notification settings.
+ */
+public class UpdateConversationOptionsAction extends Action
+        implements Parcelable {
+    /**
+     * Enable/disable conversation notifications.
+     */
+    public static void enableConversationNotifications(final String conversationId,
+            final boolean enableNotification) {
+        Assert.notNull(conversationId);
+
+        final UpdateConversationOptionsAction action = new UpdateConversationOptionsAction(
+                conversationId, enableNotification, null, null);
+        action.start();
+    }
+
+    /**
+     * Sets conversation notification sound.
+     */
+    public static void setConversationNotificationSound(final String conversationId,
+            final String ringtoneUri) {
+        Assert.notNull(conversationId);
+
+        final UpdateConversationOptionsAction action = new UpdateConversationOptionsAction(
+                conversationId, null, ringtoneUri, null);
+        action.start();
+    }
+
+    /**
+     * Enable/disable vibrations for conversation notification.
+     */
+    public static void enableVibrationForConversationNotification(final String conversationId,
+            final boolean enableVibration) {
+        Assert.notNull(conversationId);
+
+        final UpdateConversationOptionsAction action = new UpdateConversationOptionsAction(
+                conversationId, null, null, enableVibration);
+        action.start();
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+
+    // Keys for all settable settings.
+    private static final String KEY_ENABLE_NOTIFICATION = "enable_notification";
+    private static final String KEY_RINGTONE_URI = "ringtone_uri";
+    private static final String KEY_ENABLE_VIBRATION = "enable_vibration";
+
+    protected UpdateConversationOptionsAction(final String conversationId,
+            final Boolean enableNotification, final String ringtoneUri,
+            final Boolean enableVibration) {
+        Assert.notNull(conversationId);
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+        if (enableNotification != null) {
+            actionParameters.putBoolean(KEY_ENABLE_NOTIFICATION, enableNotification);
+        }
+
+        if (ringtoneUri != null) {
+            actionParameters.putString(KEY_RINGTONE_URI, ringtoneUri);
+        }
+
+        if (enableVibration != null) {
+            actionParameters.putBoolean(KEY_ENABLE_VIBRATION, enableVibration);
+        }
+    }
+
+    protected void putOptionValuesInTransaction(final ContentValues values,
+            final DatabaseWrapper dbWrapper) {
+        Assert.isTrue(dbWrapper.getDatabase().inTransaction());
+        if (actionParameters.containsKey(KEY_ENABLE_NOTIFICATION)) {
+            values.put(ConversationColumns.NOTIFICATION_ENABLED,
+                    actionParameters.getBoolean(KEY_ENABLE_NOTIFICATION));
+        }
+
+        if (actionParameters.containsKey(KEY_RINGTONE_URI)) {
+            values.put(ConversationColumns.NOTIFICATION_SOUND_URI,
+                    actionParameters.getString(KEY_RINGTONE_URI));
+        }
+
+        if (actionParameters.containsKey(KEY_ENABLE_VIBRATION)) {
+            values.put(ConversationColumns.NOTIFICATION_VIBRATION,
+                    actionParameters.getBoolean(KEY_ENABLE_VIBRATION));
+        }
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+            putOptionValuesInTransaction(values, db);
+
+            BugleDatabaseOperations.updateConversationRowIfExists(db, conversationId, values);
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
+        return null;
+    }
+
+    protected UpdateConversationOptionsAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<UpdateConversationOptionsAction> CREATOR
+            = new Parcelable.Creator<UpdateConversationOptionsAction>() {
+        @Override
+        public UpdateConversationOptionsAction createFromParcel(final Parcel in) {
+            return new UpdateConversationOptionsAction(in);
+        }
+
+        @Override
+        public UpdateConversationOptionsAction[] newArray(final int size) {
+            return new UpdateConversationOptionsAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/UpdateDestinationBlockedAction.java b/src/com/android/messaging/datamodel/action/UpdateDestinationBlockedAction.java
new file mode 100644
index 0000000..c74096d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/UpdateDestinationBlockedAction.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.util.Assert;
+
+public class UpdateDestinationBlockedAction extends Action {
+    public interface UpdateDestinationBlockedActionListener {
+        @Assert.RunsOnMainThread
+        abstract void onUpdateDestinationBlockedAction(final UpdateDestinationBlockedAction action,
+                                                       final boolean success,
+                                                       final boolean block,
+                                                       final String destination);
+    }
+
+    public static class UpdateDestinationBlockedActionMonitor extends ActionMonitor
+            implements ActionMonitor.ActionCompletedListener {
+        private final UpdateDestinationBlockedActionListener mListener;
+
+        public UpdateDestinationBlockedActionMonitor(
+                Object data, UpdateDestinationBlockedActionListener mListener) {
+            super(STATE_CREATED, generateUniqueActionKey("UpdateDestinationBlockedAction"), data);
+            setCompletedListener(this);
+            this.mListener = mListener;
+        }
+
+        private void onActionDone(final boolean succeeded,
+                                  final ActionMonitor monitor,
+                                  final Action action,
+                                  final Object data,
+                                  final Object result) {
+            mListener.onUpdateDestinationBlockedAction(
+                    (UpdateDestinationBlockedAction) action,
+                    succeeded,
+                    action.actionParameters.getBoolean(KEY_BLOCKED),
+                    action.actionParameters.getString(KEY_DESTINATION));
+        }
+
+        @Override
+        public void onActionSucceeded(final ActionMonitor monitor,
+                                      final Action action,
+                                      final Object data,
+                                      final Object result) {
+            onActionDone(true, monitor, action, data, result);
+        }
+
+        @Override
+        public void onActionFailed(final ActionMonitor monitor,
+                                   final Action action,
+                                   final Object data,
+                                   final Object result) {
+            onActionDone(false, monitor, action, data, result);
+        }
+    }
+
+
+    public static UpdateDestinationBlockedActionMonitor updateDestinationBlocked(
+            final String destination, final boolean blocked, final String conversationId,
+            final UpdateDestinationBlockedActionListener listener) {
+        Assert.notNull(listener);
+        final UpdateDestinationBlockedActionMonitor monitor =
+                new UpdateDestinationBlockedActionMonitor(null, listener);
+        final UpdateDestinationBlockedAction action =
+                new UpdateDestinationBlockedAction(destination, blocked, conversationId,
+                        monitor.getActionKey());
+        action.start(monitor);
+        return monitor;
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversation_id";
+    private static final String KEY_DESTINATION = "destination";
+    private static final String KEY_BLOCKED = "blocked";
+
+    protected UpdateDestinationBlockedAction(
+            final String destination, final boolean blocked, final String conversationId,
+            final String actionKey) {
+        super(actionKey);
+        Assert.isTrue(!TextUtils.isEmpty(destination));
+        actionParameters.putString(KEY_DESTINATION, destination);
+        actionParameters.putBoolean(KEY_BLOCKED, blocked);
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String destination = actionParameters.getString(KEY_DESTINATION);
+        final boolean isBlocked = actionParameters.getBoolean(KEY_BLOCKED);
+        String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        BugleDatabaseOperations.updateDestination(db, destination, isBlocked);
+        if (conversationId == null) {
+            conversationId = BugleDatabaseOperations
+                    .getConversationFromOtherParticipantDestination(db, destination);
+        }
+        if (conversationId != null) {
+            if (isBlocked) {
+                UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
+            } else {
+                UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
+            }
+            MessagingContentProvider.notifyParticipantsChanged(conversationId);
+        }
+        return null;
+    }
+
+    protected UpdateDestinationBlockedAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<UpdateDestinationBlockedAction> CREATOR
+            = new Parcelable.Creator<UpdateDestinationBlockedAction>() {
+        @Override
+        public UpdateDestinationBlockedAction createFromParcel(final Parcel in) {
+            return new UpdateDestinationBlockedAction(in);
+        }
+
+        @Override
+        public UpdateDestinationBlockedAction[] newArray(final int size) {
+            return new UpdateDestinationBlockedAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/UpdateMessageNotificationAction.java b/src/com/android/messaging/datamodel/action/UpdateMessageNotificationAction.java
new file mode 100644
index 0000000..94e6f3b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/UpdateMessageNotificationAction.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleNotifications;
+
+/**
+ * Updates the message notification (generally, to include voice replies we've
+ * made since the notification was first posted).
+ */
+public class UpdateMessageNotificationAction extends Action {
+
+    public static void updateMessageNotification() {
+        new UpdateMessageNotificationAction().start();
+    }
+
+    private UpdateMessageNotificationAction() {
+    }
+
+    @Override
+    protected Object executeAction() {
+        BugleNotifications.update(true /* silent */, BugleNotifications.UPDATE_MESSAGES);
+        return null;
+    }
+
+    private UpdateMessageNotificationAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<UpdateMessageNotificationAction> CREATOR
+            = new Parcelable.Creator<UpdateMessageNotificationAction>() {
+        @Override
+        public UpdateMessageNotificationAction createFromParcel(final Parcel in) {
+            return new UpdateMessageNotificationAction(in);
+        }
+
+        @Override
+        public UpdateMessageNotificationAction[] newArray(final int size) {
+            return new UpdateMessageNotificationAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/UpdateMessagePartSizeAction.java b/src/com/android/messaging/datamodel/action/UpdateMessagePartSizeAction.java
new file mode 100644
index 0000000..273dce9
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/UpdateMessagePartSizeAction.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentValues;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.util.Assert;
+
+/**
+ * Action used to update size fields of a single part
+ */
+public class UpdateMessagePartSizeAction extends Action implements Parcelable {
+    /**
+     * Update size of part
+     */
+    public static void updateSize(final String partId, final int width, final int height) {
+        Assert.notNull(partId);
+        Assert.inRange(width, 0, Integer.MAX_VALUE);
+        Assert.inRange(height, 0, Integer.MAX_VALUE);
+
+        final UpdateMessagePartSizeAction action = new UpdateMessagePartSizeAction(
+                partId, width, height);
+        action.start();
+    }
+
+    private static final String KEY_PART_ID = "part_id";
+    private static final String KEY_WIDTH = "width";
+    private static final String KEY_HEIGHT = "height";
+
+    private UpdateMessagePartSizeAction(final String partId, final int width, final int height) {
+        actionParameters.putString(KEY_PART_ID, partId);
+        actionParameters.putInt(KEY_WIDTH, width);
+        actionParameters.putInt(KEY_HEIGHT, height);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final String partId = actionParameters.getString(KEY_PART_ID);
+        final int width = actionParameters.getInt(KEY_WIDTH);
+        final int height = actionParameters.getInt(KEY_HEIGHT);
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+
+            values.put(PartColumns.WIDTH, width);
+            values.put(PartColumns.HEIGHT, height);
+
+            // Part may have been deleted so allow update to fail without asserting
+            BugleDatabaseOperations.updateRowIfExists(db, DatabaseHelper.PARTS_TABLE,
+                    PartColumns._ID, partId, values);
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        return null;
+    }
+
+    private UpdateMessagePartSizeAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<UpdateMessagePartSizeAction> CREATOR
+            = new Parcelable.Creator<UpdateMessagePartSizeAction>() {
+        @Override
+        public UpdateMessagePartSizeAction createFromParcel(final Parcel in) {
+            return new UpdateMessagePartSizeAction(in);
+        }
+
+        @Override
+        public UpdateMessagePartSizeAction[] newArray(final int size) {
+            return new UpdateMessagePartSizeAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/action/WriteDraftMessageAction.java b/src/com/android/messaging/datamodel/action/WriteDraftMessageAction.java
new file mode 100644
index 0000000..c1f39e1
--- /dev/null
+++ b/src/com/android/messaging/datamodel/action/WriteDraftMessageAction.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.LogUtil;
+
+public class WriteDraftMessageAction extends Action implements Parcelable {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+
+    /**
+     * Set draft message (no listener)
+     */
+    public static void writeDraftMessage(final String conversationId, final MessageData message) {
+        final WriteDraftMessageAction action = new WriteDraftMessageAction(conversationId, message);
+        action.start();
+    }
+
+    private static final String KEY_CONVERSATION_ID = "conversationId";
+    private static final String KEY_MESSAGE = "message";
+
+    private WriteDraftMessageAction(final String conversationId, final MessageData message) {
+        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
+        actionParameters.putParcelable(KEY_MESSAGE, message);
+    }
+
+    @Override
+    protected Object executeAction() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
+        final MessageData message = actionParameters.getParcelable(KEY_MESSAGE);
+        if (message.getSelfId() == null || message.getParticipantId() == null) {
+            // This could happen when this occurs before the draft message is loaded
+            // In this case, we just use the conversation's current self id as draft's
+            // self id and/or participant id
+            final ConversationListItemData conversation =
+                    ConversationListItemData.getExistingConversation(db, conversationId);
+            if (conversation != null) {
+                final String senderAndSelf = conversation.getSelfId();
+                if (message.getSelfId() == null) {
+                    message.bindSelfId(senderAndSelf);
+                }
+                if (message.getParticipantId() == null) {
+                    message.bindParticipantId(senderAndSelf);
+                }
+            } else {
+                LogUtil.w(LogUtil.BUGLE_DATAMODEL_TAG, "Conversation " + conversationId +
+                        "already deleted before saving draft message " +
+                        message.getMessageId() + ". Aborting WriteDraftMessageAction.");
+                return null;
+            }
+        }
+        // Drafts are only kept in the local DB...
+        final String messageId = BugleDatabaseOperations.updateDraftMessageData(
+                db, conversationId, message, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+        MessagingContentProvider.notifyConversationListChanged();
+        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
+        return messageId;
+    }
+
+    private WriteDraftMessageAction(final Parcel in) {
+        super(in);
+    }
+
+    public static final Parcelable.Creator<WriteDraftMessageAction> CREATOR
+            = new Parcelable.Creator<WriteDraftMessageAction>() {
+        @Override
+        public WriteDraftMessageAction createFromParcel(final Parcel in) {
+            return new WriteDraftMessageAction(in);
+        }
+
+        @Override
+        public WriteDraftMessageAction[] newArray(final int size) {
+            return new WriteDraftMessageAction[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(final Parcel parcel, final int flags) {
+        writeActionToParcel(parcel, flags);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/binding/BindableData.java b/src/com/android/messaging/datamodel/binding/BindableData.java
new file mode 100644
index 0000000..5446098
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/BindableData.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.binding;
+
+/**
+ * Base class for data objects that will be bound to a piece of the UI
+ */
+public abstract class BindableData {
+    /**
+     * Called by Binding during unbind to allow data to proactively unregister callbacks
+     * Data instance should release all listeners that may call back to the host UI
+     */
+    protected abstract void unregisterListeners();
+
+    /**
+     * Key used to identify the piece of UI that the data is currently bound to
+     */
+    private String mBindingId;
+
+    /**
+     * Bind this data to the ui host - checks data is currently unbound
+     */
+    public void bind(final String bindingId) {
+        if (isBound() || bindingId == null) {
+            throw new IllegalStateException();
+        }
+        mBindingId = bindingId;
+    }
+
+    /**
+     * Unbind this data from the ui host - checks that the data is currently bound to specified id
+     */
+    public void unbind(final String bindingId) {
+        if (!isBound(bindingId)) {
+            throw new IllegalStateException();
+        }
+        unregisterListeners();
+        mBindingId = null;
+    }
+
+    /**
+     * Check to see if the data is bound to anything
+     *
+     * TODO: This should be package private because it's supposed to only be used by Binding,
+     * however, several classes call this directly.  We want the classes to track what they are
+     * bound to.
+     */
+    protected boolean isBound() {
+        return (mBindingId != null);
+    }
+
+    /**
+     * Check to see if data is still bound with specified bindingId before calling over to ui
+     */
+    public boolean isBound(final String bindingId) {
+        return (bindingId.equals(mBindingId));
+    }
+}
diff --git a/src/com/android/messaging/datamodel/binding/BindableOnceData.java b/src/com/android/messaging/datamodel/binding/BindableOnceData.java
new file mode 100644
index 0000000..08e11da
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/BindableOnceData.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.binding;
+
+/**
+ * A BindableData that's only used to be bound once. If the client needs to rebind, it needs
+ * to create a new instance of the BindableOnceData.
+ */
+public abstract class BindableOnceData extends BindableData {
+    private boolean boundOnce = false;
+
+    @Override
+    public void bind(final String bindingId) {
+        // Ensures that we can't re-bind again after the first binding.
+        if (boundOnce) {
+            throw new IllegalStateException();
+        }
+        super.bind(bindingId);
+        boundOnce = true;
+    }
+
+    /**
+     * Checks if the instance is bound to anything.
+     */
+    @Override
+    public boolean isBound() {
+        return super.isBound();
+    }
+}
diff --git a/src/com/android/messaging/datamodel/binding/Binding.java b/src/com/android/messaging/datamodel/binding/Binding.java
new file mode 100644
index 0000000..3ec01dd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/Binding.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.binding;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class Binding<T extends BindableData> extends BindingBase<T> {
+    private static AtomicLong sBindingIdx = new AtomicLong(System.currentTimeMillis() * 1000);
+
+    private String mBindingId;
+    private T mData;
+    private final Object mOwner;
+    private boolean mWasBound;
+
+    /**
+     * Initialize a binding instance - the owner is typically the containing class
+     */
+    Binding(final Object owner) {
+        mOwner = owner;
+    }
+
+    @Override
+    public T getData() {
+        ensureBound();
+        return mData;
+    }
+
+    @Override
+    public boolean isBound() {
+        return (mData != null && mData.isBound(mBindingId));
+    }
+
+    @Override
+    public boolean isBound(final T data) {
+        return (isBound() && data == mData);
+    }
+
+    @Override
+    public void ensureBound() {
+        if (!isBound()) {
+            throw new IllegalStateException("not bound; wasBound = " + mWasBound);
+        }
+    }
+
+    @Override
+    public void ensureBound(final T data) {
+        if (!isBound()) {
+            throw new IllegalStateException("not bound; wasBound = " + mWasBound);
+        } else if (data != mData) {
+            throw new IllegalStateException("not bound to correct data " + data + " vs " + mData);
+        }
+    }
+
+    @Override
+    public String getBindingId() {
+        return mBindingId;
+    }
+
+    public void bind(final T data) {
+        // Check both this binding and the data not already bound
+        if (mData != null || data.isBound()) {
+            throw new IllegalStateException("already bound when binding to " + data);
+        }
+        // Generate a unique identifier for this bind call
+        mBindingId = Long.toHexString(sBindingIdx.getAndIncrement());
+        data.bind(mBindingId);
+        mData = data;
+        mWasBound = true;
+    }
+
+    public void unbind() {
+        // Check this binding is bound and that data is bound to this binding
+        if (mData == null || !mData.isBound(mBindingId)) {
+            throw new IllegalStateException("not bound when unbind");
+        }
+        mData.unbind(mBindingId);
+        mData = null;
+        mBindingId = null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/binding/BindingBase.java b/src/com/android/messaging/datamodel/binding/BindingBase.java
new file mode 100644
index 0000000..3d6da9b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/BindingBase.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.binding;
+
+/**
+ * The binding class keeps track of a binding between a ui component and an item of BindableData
+ * It allows each side to ensure that when it communicates with the other they are still bound
+ * together.
+ * NOTE: Ensure that the UI component uses the same binding instance for it's whole lifetime
+ *  (DO NOT CREATE A NEW BINDING EACH TIME A NEW PIECE OF DATA IS BOUND)...
+ *
+ * The ui component owns the binding instance.
+ * It can use it [isBound(data)] to see if the binding still binds to the right piece of data
+ *
+ * Upon binding the data is informed of a unique binding key generated in this class and can use
+ * that to ensure that it is still issuing callbacks to the right piece of ui.
+ */
+public abstract class BindingBase<T extends BindableData> {
+    /**
+     * Creates a new exclusively owned binding for the owner object.
+     */
+    public static <T extends BindableData> Binding<T> createBinding(final Object owner) {
+        return new Binding<T>(owner);
+    }
+
+    /**
+     * Creates a new read-only binding referencing the source binding object.
+     * TODO: We may want to refcount the Binding references, so that when the binding owner
+     * calls unbind() when there's still outstanding references we can catch it.
+     */
+    public static <T extends BindableData> ImmutableBindingRef<T> createBindingReference(
+            final BindingBase<T> srcBinding) {
+        return new ImmutableBindingRef<T>(srcBinding);
+    }
+
+    /**
+     * Creates a detachable binding for the owner object. Use this if your owner object is a UI
+     * component that may undergo a "detached from window" -> "re-attached to window" transition.
+     */
+    public static <T extends BindableData> DetachableBinding<T> createDetachableBinding(
+            final Object owner) {
+        return new DetachableBinding<T>(owner);
+    }
+
+    public abstract T getData();
+
+    /**
+     * Check if binding connects to the specified data instance
+     */
+    public abstract boolean isBound();
+
+    /**
+     * Check if binding connects to the specified data instance
+     */
+    public abstract boolean isBound(final T data);
+
+    /**
+     * Throw if binding connects to the specified data instance
+     */
+    public abstract void ensureBound();
+
+    /**
+     * Throw if binding connects to the specified data instance
+     */
+    public abstract void ensureBound(final T data);
+
+    /**
+     * Return the binding id for this binding (will be null if not bound)
+     */
+    public abstract String getBindingId();
+}
diff --git a/src/com/android/messaging/datamodel/binding/DetachableBinding.java b/src/com/android/messaging/datamodel/binding/DetachableBinding.java
new file mode 100644
index 0000000..a414c3b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/DetachableBinding.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.binding;
+
+import com.android.messaging.util.Assert;
+
+/**
+ * An extension on {@link Binding} that allows for temporary data detachment from the UI component.
+ * This is used when, instead of destruction or data rebinding, the owning UI undergoes a
+ * "detached from window" -> "re-attached to window" transition, in which case we want to
+ * temporarily unbind the data and remember it so that it can be rebound when the UI is re-attached
+ * to window later.
+ */
+public class DetachableBinding<T extends BindableData> extends Binding<T> {
+    private T mDetachedData;
+
+    DetachableBinding(Object owner) {
+        super(owner);
+    }
+
+    @Override
+    public void bind(T data) {
+        super.bind(data);
+        // Rebinding before re-attaching. Pre-emptively throw away the detached data because
+        // it's now stale.
+        mDetachedData = null;
+    }
+
+    public void detach() {
+        Assert.isNull(mDetachedData);
+        Assert.isTrue(isBound());
+        mDetachedData = getData();
+        unbind();
+    }
+
+    public void reAttachIfPossible() {
+        if (mDetachedData != null) {
+            Assert.isFalse(isBound());
+            bind(mDetachedData);
+            mDetachedData = null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/binding/ImmutableBindingRef.java b/src/com/android/messaging/datamodel/binding/ImmutableBindingRef.java
new file mode 100644
index 0000000..9a0a3d6
--- /dev/null
+++ b/src/com/android/messaging/datamodel/binding/ImmutableBindingRef.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.binding;
+
+import com.android.messaging.util.Assert;
+
+/**
+ * A immutable wrapper around a Binding object. Callers can only access readonly methods like
+ * getData(), isBound() and ensureBound() but not bind() and unbind(). This is used for MVC pattern
+ * where both the View and the Controller needs access to a centrally bound Model object. The View
+ * is the one that owns the bind/unbind logic of the Binding, whereas controller only serves as a
+ * consumer.
+ */
+public class ImmutableBindingRef<T extends BindableData> extends BindingBase<T> {
+    /**
+     * The referenced, read-only binding object.
+     */
+    private final BindingBase<T> mBinding;
+
+    /**
+     * Hidden ctor.
+     */
+    ImmutableBindingRef(final BindingBase<T> binding) {
+        mBinding = resolveBinding(binding);
+    }
+
+    @Override
+    public T getData() {
+        return mBinding.getData();
+    }
+
+    @Override
+    public boolean isBound() {
+        return mBinding.isBound();
+    }
+
+    @Override
+    public boolean isBound(final T data) {
+        return mBinding.isBound(data);
+    }
+
+    @Override
+    public void ensureBound() {
+        mBinding.ensureBound();
+    }
+
+    @Override
+    public void ensureBound(final T data) {
+        mBinding.ensureBound(data);
+    }
+
+    @Override
+    public String getBindingId() {
+        return mBinding.getBindingId();
+    }
+
+    /**
+     * Resolve the source binding to the real BindingImpl it's referencing. This avoids the
+     * redundancy of multiple wrapper calls when creating a binding reference from an existing
+     * binding reference.
+     */
+    private BindingBase<T> resolveBinding(final BindingBase<T> binding) {
+        BindingBase<T> resolvedBinding = binding;
+        while (resolvedBinding instanceof ImmutableBindingRef<?>) {
+            resolvedBinding = ((ImmutableBindingRef<T>) resolvedBinding).mBinding;
+        }
+        Assert.isTrue(resolvedBinding instanceof Binding<?>);
+        return resolvedBinding;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/BlockedParticipantsData.java b/src/com/android/messaging/datamodel/data/BlockedParticipantsData.java
new file mode 100644
index 0000000..4e94ee1
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/BlockedParticipantsData.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.util.Assert;
+
+/**
+ * Services data needs for BlockedParticipantsFragment
+ */
+public class BlockedParticipantsData extends BindableData implements
+        LoaderManager.LoaderCallbacks<Cursor> {
+    public interface BlockedParticipantsDataListener {
+        public void onBlockedParticipantsCursorUpdated(final Cursor cursor);
+    }
+    private static final String BINDING_ID = "bindingId";
+    private static final int BLOCKED_PARTICIPANTS_LOADER = 1;
+    private final Context mContext;
+    private LoaderManager mLoaderManager;
+    private BlockedParticipantsDataListener mListener;
+
+    public BlockedParticipantsData(final Context context,
+            final BlockedParticipantsDataListener listener) {
+        mContext = context;
+        mListener = listener;
+    }
+
+    @Override
+    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+        Assert.isTrue(id == BLOCKED_PARTICIPANTS_LOADER);
+        final String bindingId = args.getString(BINDING_ID);
+        // Check if data still bound to the requesting ui element
+        if (isBound(bindingId)) {
+            final Uri uri = MessagingContentProvider.PARTICIPANTS_URI;
+            return new BoundCursorLoader(bindingId, mContext, uri,
+                    ParticipantData.ParticipantsQuery.PROJECTION,
+                    ParticipantColumns.BLOCKED + "=1", null, null);
+        }
+        return null;
+    }
+
+    @Override
+    public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
+        Assert.isTrue(loader.getId() == BLOCKED_PARTICIPANTS_LOADER);
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        Assert.isTrue(isBound(cursorLoader.getBindingId()));
+        mListener.onBlockedParticipantsCursorUpdated(cursor);
+    }
+
+    @Override
+    public void onLoaderReset(final Loader<Cursor> loader) {
+        Assert.isTrue(loader.getId() == BLOCKED_PARTICIPANTS_LOADER);
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        Assert.isTrue(isBound(cursorLoader.getBindingId()));
+        mListener.onBlockedParticipantsCursorUpdated(null);
+    }
+
+    public void init(final LoaderManager loaderManager,
+            final BindingBase<BlockedParticipantsData> binding) {
+        final Bundle args = new Bundle();
+        args.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_LOADER, args, this);
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(BLOCKED_PARTICIPANTS_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    public ParticipantListItemData createParticipantListItemData(Cursor cursor) {
+        return new ParticipantListItemData(ParticipantData.getFromCursor(cursor));
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ContactListItemData.java b/src/com/android/messaging/datamodel/data/ContactListItemData.java
new file mode 100644
index 0000000..b9c7e85
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ContactListItemData.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract.DisplayNameSources;
+
+import com.android.ex.chips.RecipientEntry;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactRecipientEntryUtils;
+import com.android.messaging.util.ContactUtil;
+
+/**
+ * Data model object used to power ContactListItemViews, which may be displayed either in
+ * our contact list, or in the chips UI search drop down presented by ContactDropdownLayouter.
+ */
+public class ContactListItemData {
+    // Keeps the contact data in the form of RecipientEntry that RecipientEditTextView can
+    // directly use.
+    private RecipientEntry mRecipientEntry;
+
+    private CharSequence mStyledName;
+    private CharSequence mStyledDestination;
+
+    // If this contact is the first in the list for its first letter, then this will be the
+    // first letter, otherwise this is null.
+    private String mAlphabetHeader;
+
+    // Is the contact the only item in the list (happens when the user clicks on an
+    // existing chip for which we show full contact detail for the selected contact).
+    private boolean mSingleRecipient;
+
+    // Is the contact in managed profile.
+    private boolean mIsWorkContact;
+
+    /**
+     * Bind to a contact cursor in the contact list.
+     */
+    public void bind(final Cursor cursor, final String alphabetHeader) {
+        final long dataId = cursor.getLong(ContactUtil.INDEX_DATA_ID);
+        final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+        final String lookupKey = cursor.getString(ContactUtil.INDEX_LOOKUP_KEY);
+        final String displayName = cursor.getString(ContactUtil.INDEX_DISPLAY_NAME);
+        final String photoThumbnailUri = cursor.getString(ContactUtil.INDEX_PHOTO_URI);
+        final String destination = cursor.getString(ContactUtil.INDEX_PHONE_EMAIL);
+        final int destinationType = cursor.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE);
+        final String destinationLabel = cursor.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL);
+        mStyledName = null;
+        mStyledDestination = null;
+        mAlphabetHeader = alphabetHeader;
+        mSingleRecipient = false;
+
+        // Check whether this contact is first level (i.e. whether it's the first entry of this
+        // contact in the contact list).
+        boolean isFirstLevel = true;
+        if (!cursor.isFirst() && cursor.moveToPrevious()) {
+            final long contactIdPrevious = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+            if (contactId == contactIdPrevious) {
+                isFirstLevel = false;
+            }
+            cursor.moveToNext();
+        }
+
+        mRecipientEntry = ContactUtil.createRecipientEntry(displayName,
+                DisplayNameSources.STRUCTURED_NAME, destination, destinationType, destinationLabel,
+                contactId, lookupKey, dataId, photoThumbnailUri, isFirstLevel);
+
+        mIsWorkContact = ContactUtil.isEnterpriseContactId(contactId);
+    }
+
+    /**
+     * Bind to a RecipientEntry produced by the chips text view in the search drop down, plus
+     * optional styled name & destination for showing bold search match.
+     */
+    public void bind(final RecipientEntry entry, final CharSequence styledName,
+                     final CharSequence styledDestination, final boolean singleRecipient,
+                     final boolean isWorkContact) {
+        Assert.isTrue(entry.isValid());
+        mRecipientEntry = entry;
+        mStyledName = styledName;
+        mStyledDestination = styledDestination;
+        mAlphabetHeader = null;
+        mSingleRecipient = singleRecipient;
+        mIsWorkContact = isWorkContact;
+    }
+
+    public CharSequence getDisplayName() {
+        final CharSequence displayName = mStyledName != null ? mStyledName :
+            ContactRecipientEntryUtils.getDisplayNameForContactList(mRecipientEntry);
+        return displayName == null ? "" : displayName;
+    }
+
+    public Uri getPhotoThumbnailUri() {
+        return mRecipientEntry.getPhotoThumbnailUri() == null ? null :
+            mRecipientEntry.getPhotoThumbnailUri();
+    }
+
+    public CharSequence getDestination() {
+        final CharSequence destination = mStyledDestination != null ?
+                mStyledDestination : ContactRecipientEntryUtils.formatDestination(mRecipientEntry);
+        return destination == null ? "" : destination;
+    }
+
+    public int getDestinationType() {
+        return mRecipientEntry.getDestinationType();
+    }
+
+    public String getDestinationLabel() {
+        return mRecipientEntry.getDestinationLabel();
+    }
+
+    public long getContactId() {
+        return mRecipientEntry.getContactId();
+    }
+
+    public String getLookupKey() {
+        return mRecipientEntry.getLookupKey();
+    }
+
+    /**
+     * Returns if this item is "first-level," i.e. whether it's the first entry of the contact
+     * that it represents in the list. For example, if John Smith has 3 different phone numbers,
+     * then the first number is considered first-level, while the other two are considered
+     * second-level.
+     */
+    public boolean getIsFirstLevel() {
+        // Treat the item as first level if it's a top-level recipient entry, or if it's the only
+        // item in the list.
+        return mRecipientEntry.isFirstLevel() || mSingleRecipient;
+    }
+
+    /**
+     * Returns if this item is simple, i.e. it has only avatar and a display name with phone number
+     * embedded so we can hide everything else.
+     */
+    public boolean getIsSimpleContactItem() {
+        return ContactRecipientEntryUtils.isAvatarAndNumberOnlyContact(mRecipientEntry) ||
+                ContactRecipientEntryUtils.isSendToDestinationContact(mRecipientEntry);
+    }
+
+    public String getAlphabetHeader() {
+        return mAlphabetHeader;
+    }
+
+    /**
+     * Returns a RecipientEntry instance readily usable by the RecipientEditTextView.
+     */
+    public RecipientEntry getRecipientEntry() {
+        return mRecipientEntry;
+    }
+
+    /**
+     * @return whether the contact is in managed profile.
+     */
+    public boolean getIsWorkContact() {
+        return mIsWorkContact;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ContactPickerData.java b/src/com/android/messaging/datamodel/data/ContactPickerData.java
new file mode 100644
index 0000000..fd6fca0
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ContactPickerData.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.FrequentContactsCursorBuilder;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Class to access phone contacts.
+ * The caller is responsible for ensuring that the app has READ_CONTACTS permission (see
+ * {@link ContactUtil#hasReadContactsPermission()}) before instantiating this class.
+ */
+public class ContactPickerData extends BindableData implements
+        LoaderManager.LoaderCallbacks<Cursor> {
+    public interface ContactPickerDataListener {
+        void onAllContactsCursorUpdated(Cursor data);
+        void onFrequentContactsCursorUpdated(Cursor data);
+        void onContactCustomColorLoaded(ContactPickerData data);
+    }
+
+    private static final String BINDING_ID = "bindingId";
+    private final Context mContext;
+    private LoaderManager mLoaderManager;
+    private ContactPickerDataListener mListener;
+    private final FrequentContactsCursorBuilder mFrequentContactsCursorBuilder;
+
+    public ContactPickerData(final Context context, final ContactPickerDataListener listener) {
+        mListener = listener;
+        mContext = context;
+        mFrequentContactsCursorBuilder = new FrequentContactsCursorBuilder();
+    }
+
+    private static final int ALL_CONTACTS_LOADER = 1;
+    private static final int FREQUENT_CONTACTS_LOADER = 2;
+    private static final int PARTICIPANT_LOADER = 3;
+
+    @Override
+    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+        final String bindingId = args.getString(BINDING_ID);
+        // Check if data still bound to the requesting ui element
+        if (isBound(bindingId)) {
+            switch (id) {
+                case ALL_CONTACTS_LOADER:
+                    return ContactUtil.getPhones(mContext)
+                            .createBoundCursorLoader(bindingId);
+                case FREQUENT_CONTACTS_LOADER:
+                    return ContactUtil.getFrequentContacts(mContext)
+                            .createBoundCursorLoader(bindingId);
+                case PARTICIPANT_LOADER:
+                    return new BoundCursorLoader(bindingId, mContext,
+                            MessagingContentProvider.PARTICIPANTS_URI,
+                            ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
+                default:
+                    Assert.fail("Unknown loader id for contact picker!");
+                    break;
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding the contacts list");
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        if (isBound(cursorLoader.getBindingId())) {
+            switch (loader.getId()) {
+                case ALL_CONTACTS_LOADER:
+                    mListener.onAllContactsCursorUpdated(data);
+                    mFrequentContactsCursorBuilder.setAllContacts(data);
+                    break;
+                case FREQUENT_CONTACTS_LOADER:
+                    mFrequentContactsCursorBuilder.setFrequents(data);
+                    break;
+                case PARTICIPANT_LOADER:
+                    mListener.onContactCustomColorLoaded(this);
+                    break;
+                default:
+                    Assert.fail("Unknown loader id for contact picker!");
+                    break;
+            }
+
+            if (loader.getId() != PARTICIPANT_LOADER) {
+                // The frequent contacts cursor to be used in the UI depends on results from both
+                // all contacts and frequent contacts loader, and we don't know which will finish
+                // first. Therefore, try to build the cursor and notify the listener if it's
+                // successfully built.
+                final Cursor frequentContactsCursor = mFrequentContactsCursorBuilder.build();
+                if (frequentContactsCursor != null) {
+                    mListener.onFrequentContactsCursorUpdated(frequentContactsCursor);
+                }
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding the contacts list");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoaderReset(final Loader<Cursor> loader) {
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        if (isBound(cursorLoader.getBindingId())) {
+            switch (loader.getId()) {
+                case ALL_CONTACTS_LOADER:
+                    mListener.onAllContactsCursorUpdated(null);
+                    mFrequentContactsCursorBuilder.setAllContacts(null);
+                    break;
+                case FREQUENT_CONTACTS_LOADER:
+                    mListener.onFrequentContactsCursorUpdated(null);
+                    mFrequentContactsCursorBuilder.setFrequents(null);
+                    break;
+                case PARTICIPANT_LOADER:
+                    mListener.onContactCustomColorLoaded(this);
+                    break;
+                default:
+                    Assert.fail("Unknown loader id for contact picker!");
+                    break;
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding the contacts list");
+        }
+    }
+
+    public void init(final LoaderManager loaderManager,
+                     final BindingBase<ContactPickerData> binding) {
+        final Bundle args = new Bundle();
+        args.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(ALL_CONTACTS_LOADER, args, this);
+        mLoaderManager.initLoader(FREQUENT_CONTACTS_LOADER, args, this);
+        mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+
+
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(ALL_CONTACTS_LOADER);
+            mLoaderManager.destroyLoader(FREQUENT_CONTACTS_LOADER);
+            mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
+            mLoaderManager = null;
+        }
+        mFrequentContactsCursorBuilder.resetBuilder();
+    }
+
+    public static boolean isTooManyParticipants(final int participantCount) {
+        // When creating a conversation, the conversation will be created using the system's
+        // default SIM, so use the default MmsConfig's recipient limit.
+        return (participantCount > MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
+                .getRecipientLimit());
+    }
+
+    public static boolean getCanAddMoreParticipants(final int participantCount) {
+        // When creating a conversation, the conversation will be created using the system's
+        // default SIM, so use the default MmsConfig's recipient limit.
+        return (participantCount < MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
+                .getRecipientLimit());
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationData.java b/src/com/android/messaging/datamodel/data/ConversationData.java
new file mode 100644
index 0000000..704e46f
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationData.java
@@ -0,0 +1,849 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.database.sqlite.SQLiteFullException;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.android.common.contacts.DataUsageStatUpdater;
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.DeleteConversationAction;
+import com.android.messaging.datamodel.action.DeleteMessageAction;
+import com.android.messaging.datamodel.action.InsertNewMessageAction;
+import com.android.messaging.datamodel.action.RedownloadMmsAction;
+import com.android.messaging.datamodel.action.ResendMessageAction;
+import com.android.messaging.datamodel.action.UpdateConversationArchiveStatusAction;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.widget.WidgetConversationProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ConversationData extends BindableData {
+
+    private static final String TAG = "bugle_datamodel";
+    private static final String BINDING_ID = "bindingId";
+    private static final long LAST_MESSAGE_TIMESTAMP_NaN = -1;
+    private static final int MESSAGE_COUNT_NaN = -1;
+
+    /**
+     * Takes a conversation id and a list of message ids and computes the positions
+     * for each message.
+     */
+    public List<Integer> getPositions(final String conversationId, final List<Long> ids) {
+        final ArrayList<Integer> result = new ArrayList<Integer>();
+
+        if (ids.isEmpty()) {
+            return result;
+        }
+
+        final Cursor c = new ConversationData.ReversedCursor(
+                DataModel.get().getDatabase().rawQuery(
+                        ConversationMessageData.getConversationMessageIdsQuerySql(),
+                        new String [] { conversationId }));
+        if (c != null) {
+            try {
+                final Set<Long> idsSet = new HashSet<Long>(ids);
+                if (c.moveToLast()) {
+                    do {
+                        final long messageId = c.getLong(0);
+                        if (idsSet.contains(messageId)) {
+                            result.add(c.getPosition());
+                        }
+                    } while (c.moveToPrevious());
+                }
+            } finally {
+                c.close();
+            }
+        }
+        Collections.sort(result);
+        return result;
+    }
+
+    public interface ConversationDataListener {
+        public void onConversationMessagesCursorUpdated(ConversationData data, Cursor cursor,
+                @Nullable ConversationMessageData newestMessage, boolean isSync);
+        public void onConversationMetadataUpdated(ConversationData data);
+        public void closeConversation(String conversationId);
+        public void onConversationParticipantDataLoaded(ConversationData data);
+        public void onSubscriptionListDataLoaded(ConversationData data);
+    }
+
+    private static class ReversedCursor extends CursorWrapper {
+        final int mCount;
+
+        public ReversedCursor(final Cursor cursor) {
+            super(cursor);
+            mCount = cursor.getCount();
+        }
+
+        @Override
+        public boolean moveToPosition(final int position) {
+            return super.moveToPosition(mCount - position - 1);
+        }
+
+        @Override
+        public int getPosition() {
+            return mCount - super.getPosition() - 1;
+        }
+
+        @Override
+        public boolean isAfterLast() {
+            return super.isBeforeFirst();
+        }
+
+        @Override
+        public boolean isBeforeFirst() {
+            return super.isAfterLast();
+        }
+
+        @Override
+        public boolean isFirst() {
+            return super.isLast();
+        }
+
+        @Override
+        public boolean isLast() {
+            return super.isFirst();
+        }
+
+        @Override
+        public boolean move(final int offset) {
+            return super.move(-offset);
+        }
+
+        @Override
+        public boolean moveToFirst() {
+            return super.moveToLast();
+        }
+
+        @Override
+        public boolean moveToLast() {
+            return super.moveToFirst();
+        }
+
+        @Override
+        public boolean moveToNext() {
+            return super.moveToPrevious();
+        }
+
+        @Override
+        public boolean moveToPrevious() {
+            return super.moveToNext();
+        }
+    }
+
+    /**
+     * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
+     */
+    private class MetadataLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+            Assert.equals(CONVERSATION_META_DATA_LOADER, id);
+            Loader<Cursor> loader = null;
+
+            final String bindingId = args.getString(BINDING_ID);
+            // Check if data still bound to the requesting ui element
+            if (isBound(bindingId)) {
+                final Uri uri =
+                        MessagingContentProvider.buildConversationMetadataUri(mConversationId);
+                loader = new BoundCursorLoader(bindingId, mContext, uri,
+                        ConversationListItemData.PROJECTION, null, null, null);
+            } else {
+                LogUtil.w(TAG, "Creating messages loader after unbinding mConversationId = " +
+                        mConversationId);
+            }
+            return loader;
+        }
+
+        @Override
+        public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                if (data.moveToNext()) {
+                    Assert.isTrue(data.getCount() == 1);
+                    mConversationMetadata.bind(data);
+                    mListeners.onConversationMetadataUpdated(ConversationData.this);
+                } else {
+                    // Close the conversation, no meta data means conversation was deleted
+                    LogUtil.w(TAG, "Meta data loader returned nothing for mConversationId = " +
+                            mConversationId);
+                    mListeners.closeConversation(mConversationId);
+                    // Notify the widget the conversation is deleted so it can go into its
+                    // configure state.
+                    WidgetConversationProvider.notifyConversationDeleted(
+                            Factory.get().getApplicationContext(),
+                            mConversationId);
+                }
+            } else {
+                LogUtil.w(TAG, "Meta data loader finished after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+
+        @Override
+        public void onLoaderReset(final Loader<Cursor> generic) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                // Clear the conversation meta data
+                mConversationMetadata = new ConversationListItemData();
+                mListeners.onConversationMetadataUpdated(ConversationData.this);
+            } else {
+                LogUtil.w(TAG, "Meta data loader reset after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+    }
+
+    /**
+     * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
+     */
+    private class MessagesLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+            Assert.equals(CONVERSATION_MESSAGES_LOADER, id);
+            Loader<Cursor> loader = null;
+
+            final String bindingId = args.getString(BINDING_ID);
+            // Check if data still bound to the requesting ui element
+            if (isBound(bindingId)) {
+                final Uri uri =
+                        MessagingContentProvider.buildConversationMessagesUri(mConversationId);
+                loader = new BoundCursorLoader(bindingId, mContext, uri,
+                        ConversationMessageData.getProjection(), null, null, null);
+                mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
+                mMessageCount = MESSAGE_COUNT_NaN;
+            } else {
+                LogUtil.w(TAG, "Creating messages loader after unbinding mConversationId = " +
+                        mConversationId);
+            }
+            return loader;
+        }
+
+        @Override
+        public void onLoadFinished(final Loader<Cursor> generic, final Cursor rawData) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                // Check if we have a new message, or if we had a message sync.
+                ConversationMessageData newMessage = null;
+                boolean isSync = false;
+                Cursor data = null;
+                if (rawData != null) {
+                    // Note that the cursor is sorted DESC so here we reverse it.
+                    // This is a performance issue (improvement) for large cursors.
+                    data = new ReversedCursor(rawData);
+
+                    final int messageCountOld = mMessageCount;
+                    mMessageCount = data.getCount();
+                    final ConversationMessageData lastMessage = getLastMessage(data);
+                    if (lastMessage != null) {
+                        final long lastMessageTimestampOld = mLastMessageTimestamp;
+                        mLastMessageTimestamp = lastMessage.getReceivedTimeStamp();
+                        final String lastMessageIdOld = mLastMessageId;
+                        mLastMessageId = lastMessage.getMessageId();
+                        if (TextUtils.equals(lastMessageIdOld, mLastMessageId) &&
+                                messageCountOld < mMessageCount) {
+                            // Last message stays the same (no incoming message) but message
+                            // count increased, which means there has been a message sync.
+                            isSync = true;
+                        } else if (messageCountOld != MESSAGE_COUNT_NaN && // Ignore initial load
+                                mLastMessageTimestamp != LAST_MESSAGE_TIMESTAMP_NaN &&
+                                mLastMessageTimestamp > lastMessageTimestampOld) {
+                            newMessage = lastMessage;
+                        }
+                    } else {
+                        mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
+                    }
+                } else {
+                    mMessageCount = MESSAGE_COUNT_NaN;
+                }
+
+                mListeners.onConversationMessagesCursorUpdated(ConversationData.this, data,
+                        newMessage, isSync);
+            } else {
+                LogUtil.w(TAG, "Messages loader finished after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+
+        @Override
+        public void onLoaderReset(final Loader<Cursor> generic) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                mListeners.onConversationMessagesCursorUpdated(ConversationData.this, null, null,
+                        false);
+                mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
+                mMessageCount = MESSAGE_COUNT_NaN;
+            } else {
+                LogUtil.w(TAG, "Messages loader reset after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+
+        private ConversationMessageData getLastMessage(final Cursor cursor) {
+            if (cursor != null && cursor.getCount() > 0) {
+                final int position = cursor.getPosition();
+                if (cursor.moveToLast()) {
+                    final ConversationMessageData messageData = new ConversationMessageData();
+                    messageData.bind(cursor);
+                    cursor.move(position);
+                    return messageData;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
+     */
+    private class ParticipantLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+            Assert.equals(PARTICIPANT_LOADER, id);
+            Loader<Cursor> loader = null;
+
+            final String bindingId = args.getString(BINDING_ID);
+            // Check if data still bound to the requesting ui element
+            if (isBound(bindingId)) {
+                final Uri uri =
+                        MessagingContentProvider.buildConversationParticipantsUri(mConversationId);
+                loader = new BoundCursorLoader(bindingId, mContext, uri,
+                        ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
+            } else {
+                LogUtil.w(TAG, "Creating participant loader after unbinding mConversationId = " +
+                        mConversationId);
+            }
+            return loader;
+        }
+
+        @Override
+        public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                mParticipantData.bind(data);
+                mListeners.onConversationParticipantDataLoaded(ConversationData.this);
+            } else {
+                LogUtil.w(TAG, "Participant loader finished after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+
+        @Override
+        public void onLoaderReset(final Loader<Cursor> generic) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                mParticipantData.bind(null);
+            } else {
+                LogUtil.w(TAG, "Participant loader reset after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+    }
+
+    /**
+     * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
+     */
+    private class SelfParticipantLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+            Assert.equals(SELF_PARTICIPANT_LOADER, id);
+            Loader<Cursor> loader = null;
+
+            final String bindingId = args.getString(BINDING_ID);
+            // Check if data still bound to the requesting ui element
+            if (isBound(bindingId)) {
+                loader = new BoundCursorLoader(bindingId, mContext,
+                        MessagingContentProvider.PARTICIPANTS_URI,
+                        ParticipantData.ParticipantsQuery.PROJECTION,
+                        ParticipantColumns.SUB_ID + " <> ?",
+                        new String[] { String.valueOf(ParticipantData.OTHER_THAN_SELF_SUB_ID) },
+                        null);
+            } else {
+                LogUtil.w(TAG, "Creating self loader after unbinding mConversationId = " +
+                        mConversationId);
+            }
+            return loader;
+        }
+
+        @Override
+        public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                mSelfParticipantsData.bind(data);
+                mSubscriptionListData.bind(mSelfParticipantsData.getSelfParticipants(true));
+                mListeners.onSubscriptionListDataLoaded(ConversationData.this);
+            } else {
+                LogUtil.w(TAG, "Self loader finished after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+
+        @Override
+        public void onLoaderReset(final Loader<Cursor> generic) {
+            final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+            // Check if data still bound to the requesting ui element
+            if (isBound(loader.getBindingId())) {
+                mSelfParticipantsData.bind(null);
+            } else {
+                LogUtil.w(TAG, "Self loader reset after unbinding mConversationId = " +
+                        mConversationId);
+            }
+        }
+    }
+
+    private final ConversationDataEventDispatcher mListeners;
+    private final MetadataLoaderCallbacks mMetadataLoaderCallbacks;
+    private final MessagesLoaderCallbacks mMessagesLoaderCallbacks;
+    private final ParticipantLoaderCallbacks mParticipantsLoaderCallbacks;
+    private final SelfParticipantLoaderCallbacks mSelfParticipantLoaderCallbacks;
+    private final Context mContext;
+    private final String mConversationId;
+    private final ConversationParticipantsData mParticipantData;
+    private final SelfParticipantsData mSelfParticipantsData;
+    private ConversationListItemData mConversationMetadata;
+    private final SubscriptionListData mSubscriptionListData;
+    private LoaderManager mLoaderManager;
+    private long mLastMessageTimestamp = LAST_MESSAGE_TIMESTAMP_NaN;
+    private int mMessageCount = MESSAGE_COUNT_NaN;
+    private String mLastMessageId;
+
+    public ConversationData(final Context context, final ConversationDataListener listener,
+            final String conversationId) {
+        Assert.isTrue(conversationId != null);
+        mContext = context;
+        mConversationId = conversationId;
+        mMetadataLoaderCallbacks = new MetadataLoaderCallbacks();
+        mMessagesLoaderCallbacks = new MessagesLoaderCallbacks();
+        mParticipantsLoaderCallbacks = new ParticipantLoaderCallbacks();
+        mSelfParticipantLoaderCallbacks = new SelfParticipantLoaderCallbacks();
+        mParticipantData = new ConversationParticipantsData();
+        mConversationMetadata = new ConversationListItemData();
+        mSelfParticipantsData = new SelfParticipantsData();
+        mSubscriptionListData = new SubscriptionListData(context);
+
+        mListeners = new ConversationDataEventDispatcher();
+        mListeners.add(listener);
+    }
+
+    @RunsOnMainThread
+    public void addConversationDataListener(final ConversationDataListener listener) {
+        Assert.isMainThread();
+        mListeners.add(listener);
+    }
+
+    public String getConversationName() {
+        return mConversationMetadata.getName();
+    }
+
+    public boolean getIsArchived() {
+        return mConversationMetadata.getIsArchived();
+    }
+
+    public String getIcon() {
+        return mConversationMetadata.getIcon();
+    }
+
+    public String getConversationId() {
+        return mConversationId;
+    }
+
+    public void setFocus() {
+        DataModel.get().setFocusedConversation(mConversationId);
+        // As we are loading the conversation assume the user has read the messages...
+        // Do this late though so that it doesn't get in the way of other actions
+        BugleNotifications.markMessagesAsRead(mConversationId);
+    }
+
+    public void unsetFocus() {
+        DataModel.get().setFocusedConversation(null);
+    }
+
+    public boolean isFocused() {
+        return isBound() && DataModel.get().isFocusedConversation(mConversationId);
+    }
+
+    private static final int CONVERSATION_META_DATA_LOADER = 1;
+    private static final int CONVERSATION_MESSAGES_LOADER = 2;
+    private static final int PARTICIPANT_LOADER = 3;
+    private static final int SELF_PARTICIPANT_LOADER = 4;
+
+    public void init(final LoaderManager loaderManager,
+            final BindingBase<ConversationData> binding) {
+        // Remember the binding id so that loader callbacks can check if data is still bound
+        // to same ui component
+        final Bundle args = new Bundle();
+        args.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(CONVERSATION_META_DATA_LOADER, args, mMetadataLoaderCallbacks);
+        mLoaderManager.initLoader(CONVERSATION_MESSAGES_LOADER, args, mMessagesLoaderCallbacks);
+        mLoaderManager.initLoader(PARTICIPANT_LOADER, args, mParticipantsLoaderCallbacks);
+        mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, mSelfParticipantLoaderCallbacks);
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListeners.clear();
+        // Make sure focus has moved away from this conversation
+        // TODO: May false trigger if destroy happens after "new" conversation is focused.
+        //        Assert.isTrue(!DataModel.get().isFocusedConversation(mConversationId));
+
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(CONVERSATION_META_DATA_LOADER);
+            mLoaderManager.destroyLoader(CONVERSATION_MESSAGES_LOADER);
+            mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
+            mLoaderManager.destroyLoader(SELF_PARTICIPANT_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    /**
+     * Gets the default self participant in the participant table (NOT the conversation's self).
+     * This is available as soon as self participant data is loaded.
+     */
+    public ParticipantData getDefaultSelfParticipant() {
+        return mSelfParticipantsData.getDefaultSelfParticipant();
+    }
+
+    public List<ParticipantData> getSelfParticipants(final boolean activeOnly) {
+        return mSelfParticipantsData.getSelfParticipants(activeOnly);
+    }
+
+    public int getSelfParticipantsCountExcludingDefault(final boolean activeOnly) {
+        return mSelfParticipantsData.getSelfParticipantsCountExcludingDefault(activeOnly);
+    }
+
+    public ParticipantData getSelfParticipantById(final String selfId) {
+        return mSelfParticipantsData.getSelfParticipantById(selfId);
+    }
+
+    /**
+     * For a 1:1 conversation return the other (not self) participant (else null)
+     */
+    public ParticipantData getOtherParticipant() {
+        return mParticipantData.getOtherParticipant();
+    }
+
+    /**
+     * Return true once the participants are loaded
+     */
+    public boolean getParticipantsLoaded() {
+        return mParticipantData.isLoaded();
+    }
+
+    public void sendMessage(final BindingBase<ConversationData> binding,
+            final MessageData message) {
+        Assert.isTrue(TextUtils.equals(mConversationId, message.getConversationId()));
+        Assert.isTrue(binding.getData() == this);
+
+        if (!OsUtil.isAtLeastL_MR1() || message.getSelfId() == null) {
+            InsertNewMessageAction.insertNewMessage(message);
+        } else {
+            final int systemDefaultSubId = PhoneUtils.getDefault().getDefaultSmsSubscriptionId();
+            if (systemDefaultSubId != ParticipantData.DEFAULT_SELF_SUB_ID &&
+                    mSelfParticipantsData.isDefaultSelf(message.getSelfId())) {
+                // Lock the sub selection to the system default SIM as soon as the user clicks on
+                // the send button to avoid races between this and when InsertNewMessageAction is
+                // actually executed on the data model thread, during which the user can potentially
+                // change the system default SIM in Settings.
+                InsertNewMessageAction.insertNewMessage(message, systemDefaultSubId);
+            } else {
+                InsertNewMessageAction.insertNewMessage(message);
+            }
+        }
+        // Update contacts so Frequents will reflect messaging activity.
+        if (!getParticipantsLoaded()) {
+            return;  // oh well, not critical
+        }
+        final ArrayList<String> phones = new ArrayList<>();
+        final ArrayList<String> emails = new ArrayList<>();
+        for (final ParticipantData participant : mParticipantData) {
+            if (!participant.isSelf()) {
+                if (participant.isEmail()) {
+                    emails.add(participant.getSendDestination());
+                } else {
+                    phones.add(participant.getSendDestination());
+                }
+            }
+        }
+
+        if (ContactUtil.hasReadContactsPermission()) {
+            SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                @Override
+                public void run() {
+                    final DataUsageStatUpdater updater = new DataUsageStatUpdater(
+                            Factory.get().getApplicationContext());
+                    try {
+                        if (!phones.isEmpty()) {
+                            updater.updateWithPhoneNumber(phones);
+                        }
+                        if (!emails.isEmpty()) {
+                            updater.updateWithAddress(emails);
+                        }
+                    } catch (final SQLiteFullException ex) {
+                        LogUtil.w(TAG, "Unable to update contact", ex);
+                    }
+                }
+            });
+        }
+    }
+
+    public void downloadMessage(final BindingBase<ConversationData> binding,
+            final String messageId) {
+        Assert.isTrue(binding.getData() == this);
+        Assert.notNull(messageId);
+        RedownloadMmsAction.redownloadMessage(messageId);
+    }
+
+    public void resendMessage(final BindingBase<ConversationData> binding, final String messageId) {
+        Assert.isTrue(binding.getData() == this);
+        Assert.notNull(messageId);
+        ResendMessageAction.resendMessage(messageId);
+    }
+
+    public void deleteMessage(final BindingBase<ConversationData> binding, final String messageId) {
+        Assert.isTrue(binding.getData() == this);
+        Assert.notNull(messageId);
+        DeleteMessageAction.deleteMessage(messageId);
+    }
+
+    public void deleteConversation(final Binding<ConversationData> binding) {
+        Assert.isTrue(binding.getData() == this);
+        // If possible use timestamp of last message shown to delete only messages user is aware of
+        if (mConversationMetadata == null) {
+            DeleteConversationAction.deleteConversation(mConversationId,
+                    System.currentTimeMillis());
+        } else {
+            mConversationMetadata.deleteConversation();
+        }
+    }
+
+    public void archiveConversation(final BindingBase<ConversationData> binding) {
+        Assert.isTrue(binding.getData() == this);
+        UpdateConversationArchiveStatusAction.archiveConversation(mConversationId);
+    }
+
+    public void unarchiveConversation(final BindingBase<ConversationData> binding) {
+        Assert.isTrue(binding.getData() == this);
+        UpdateConversationArchiveStatusAction.unarchiveConversation(mConversationId);
+    }
+
+    public ConversationParticipantsData getParticipants() {
+        return mParticipantData;
+    }
+
+    /**
+     * Returns a dialable phone number for the participant if we are in a 1-1 conversation.
+     * @return the participant phone number, or null if the phone number is not valid or if there
+     *         are more than one participant.
+     */
+    public String getParticipantPhoneNumber() {
+        final ParticipantData participant = this.getOtherParticipant();
+        if (participant != null) {
+            final String phoneNumber = participant.getSendDestination();
+            if (!TextUtils.isEmpty(phoneNumber) && MmsSmsUtils.isPhoneNumber(phoneNumber)) {
+                return phoneNumber;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create a message to be forwarded from an existing message.
+     */
+    public MessageData createForwardedMessage(final ConversationMessageData message) {
+        final MessageData forwardedMessage = new MessageData();
+
+        final String originalSubject =
+                MmsUtils.cleanseMmsSubject(mContext.getResources(), message.getMmsSubject());
+        if (!TextUtils.isEmpty(originalSubject)) {
+            forwardedMessage.setMmsSubject(
+                    mContext.getResources().getString(R.string.message_fwd, originalSubject));
+        }
+
+        for (final MessagePartData part : message.getParts()) {
+            MessagePartData forwardedPart;
+
+            // Depending on the part type, if it is text, we can directly create a text part;
+            // if it is attachment, then we need to create a pending attachment data out of it, so
+            // that we may persist the attachment locally in the scratch folder when the user picks
+            // a conversation to forward to.
+            if (part.isText()) {
+                forwardedPart = MessagePartData.createTextMessagePart(part.getText());
+            } else {
+                final PendingAttachmentData pendingAttachmentData = PendingAttachmentData
+                        .createPendingAttachmentData(part.getContentType(), part.getContentUri());
+                forwardedPart = pendingAttachmentData;
+            }
+            forwardedMessage.addPart(forwardedPart);
+        }
+        return forwardedMessage;
+    }
+
+    public int getNumberOfParticipantsExcludingSelf() {
+        return mParticipantData.getNumberOfParticipantsExcludingSelf();
+    }
+
+    /**
+     * Returns {@link com.android.messaging.datamodel.data.SubscriptionListData
+     * .SubscriptionListEntry} for a given self participant so UI can display SIM-related info
+     * (icon, name etc.) for multi-SIM.
+     */
+    public SubscriptionListEntry getSubscriptionEntryForSelfParticipant(
+            final String selfParticipantId, final boolean excludeDefault) {
+        return getSubscriptionEntryForSelfParticipant(selfParticipantId, excludeDefault,
+                mSubscriptionListData, mSelfParticipantsData);
+    }
+
+    /**
+     * Returns {@link com.android.messaging.datamodel.data.SubscriptionListData
+     * .SubscriptionListEntry} for a given self participant so UI can display SIM-related info
+     * (icon, name etc.) for multi-SIM.
+     */
+    public static SubscriptionListEntry getSubscriptionEntryForSelfParticipant(
+            final String selfParticipantId, final boolean excludeDefault,
+            final SubscriptionListData subscriptionListData,
+            final SelfParticipantsData selfParticipantsData) {
+        // SIM indicators are shown in the UI only if:
+        // 1. Framework has MSIM support AND
+        // 2. The device has had multiple *active* subscriptions. AND
+        // 3. The message's subscription is active.
+        if (OsUtil.isAtLeastL_MR1() &&
+                selfParticipantsData.getSelfParticipantsCountExcludingDefault(true) > 1) {
+            return subscriptionListData.getActiveSubscriptionEntryBySelfId(selfParticipantId,
+                    excludeDefault);
+        }
+        return null;
+    }
+
+    public SubscriptionListData getSubscriptionListData() {
+        return mSubscriptionListData;
+    }
+
+    /**
+     * A placeholder implementation of {@link ConversationDataListener} so that subclasses may opt
+     * to implement some, but not all, of the interface methods.
+     */
+    public static class SimpleConversationDataListener implements ConversationDataListener {
+
+        @Override
+        public void onConversationMessagesCursorUpdated(final ConversationData data, final Cursor cursor,
+                @Nullable
+                        final
+                ConversationMessageData newestMessage, final boolean isSync) {}
+
+        @Override
+        public void onConversationMetadataUpdated(final ConversationData data) {}
+
+        @Override
+        public void closeConversation(final String conversationId) {}
+
+        @Override
+        public void onConversationParticipantDataLoaded(final ConversationData data) {}
+
+        @Override
+        public void onSubscriptionListDataLoaded(final ConversationData data) {}
+
+    }
+
+    private class ConversationDataEventDispatcher
+            extends ArrayList<ConversationDataListener>
+            implements ConversationDataListener {
+
+        @Override
+        public void onConversationMessagesCursorUpdated(final ConversationData data, final Cursor cursor,
+                @Nullable
+                        final ConversationMessageData newestMessage, final boolean isSync) {
+            for (final ConversationDataListener listener : this) {
+                listener.onConversationMessagesCursorUpdated(data, cursor, newestMessage, isSync);
+            }
+        }
+
+        @Override
+        public void onConversationMetadataUpdated(final ConversationData data) {
+            for (final ConversationDataListener listener : this) {
+                listener.onConversationMetadataUpdated(data);
+            }
+        }
+
+        @Override
+        public void closeConversation(final String conversationId) {
+            for (final ConversationDataListener listener : this) {
+                listener.closeConversation(conversationId);
+            }
+        }
+
+        @Override
+        public void onConversationParticipantDataLoaded(final ConversationData data) {
+            for (final ConversationDataListener listener : this) {
+                listener.onConversationParticipantDataLoaded(data);
+            }
+        }
+
+        @Override
+        public void onSubscriptionListDataLoaded(final ConversationData data) {
+            for (final ConversationDataListener listener : this) {
+                listener.onSubscriptionListDataLoaded(data);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationListData.java b/src/com/android/messaging/datamodel/data/ConversationListData.java
new file mode 100644
index 0000000..3d27ecd
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationListData.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ConversationListItemData.ConversationListViewColumns;
+import com.android.messaging.receiver.SmsReceiver;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.HashSet;
+
+public class ConversationListData extends BindableData
+        implements LoaderManager.LoaderCallbacks<Cursor> {
+
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final String BINDING_ID = "bindingId";
+    public static final String SORT_ORDER =
+            ConversationListViewColumns.SORT_TIMESTAMP + " DESC";
+
+    private static final String WHERE_ARCHIVED =
+            "(" + ConversationListViewColumns.ARCHIVE_STATUS + " = 1)";
+    public static final String WHERE_NOT_ARCHIVED =
+            "(" + ConversationListViewColumns.ARCHIVE_STATUS + " = 0)";
+
+    public interface ConversationListDataListener {
+        public void onConversationListCursorUpdated(ConversationListData data, Cursor cursor);
+        public void setBlockedParticipantsAvailable(boolean blockedAvailable);
+    }
+
+    private ConversationListDataListener mListener;
+    private final Context mContext;
+    private final boolean mArchivedMode;
+    private LoaderManager mLoaderManager;
+
+    public ConversationListData(final Context context, final ConversationListDataListener listener,
+            final boolean archivedMode) {
+        mListener = listener;
+        mContext = context;
+        mArchivedMode = archivedMode;
+    }
+
+    private static final int CONVERSATION_LIST_LOADER = 1;
+    private static final int BLOCKED_PARTICIPANTS_AVAILABLE_LOADER = 2;
+
+    private static final String[] BLOCKED_PARTICIPANTS_PROJECTION = new String[] {
+            ParticipantColumns._ID,
+            ParticipantColumns.NORMALIZED_DESTINATION,
+    };
+    private static final int INDEX_BLOCKED_PARTICIPANTS_ID = 0;
+    private static final int INDEX_BLOCKED_PARTICIPANTS_NORMALIZED_DESTINATION = 1;
+
+    // all blocked participants
+    private final HashSet<String> mBlockedParticipants = new HashSet<String>();
+
+    @Override
+    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+        final String bindingId = args.getString(BINDING_ID);
+        Loader<Cursor> loader = null;
+        // Check if data still bound to the requesting ui element
+        if (isBound(bindingId)) {
+            switch (id) {
+                case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
+                    loader = new BoundCursorLoader(bindingId, mContext,
+                            MessagingContentProvider.PARTICIPANTS_URI,
+                            BLOCKED_PARTICIPANTS_PROJECTION,
+                            ParticipantColumns.BLOCKED + "=1", null, null);
+                    break;
+                case CONVERSATION_LIST_LOADER:
+                    loader = new BoundCursorLoader(bindingId, mContext,
+                            MessagingContentProvider.CONVERSATIONS_URI,
+                            ConversationListItemData.PROJECTION,
+                            mArchivedMode ? WHERE_ARCHIVED : WHERE_NOT_ARCHIVED,
+                            null,       // selection args
+                            SORT_ORDER);
+                    break;
+                default:
+                    Assert.fail("Unknown loader id");
+                    break;
+            }
+        } else {
+            LogUtil.w(TAG, "Creating loader after unbinding list");
+        }
+        return loader;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
+        final BoundCursorLoader loader = (BoundCursorLoader) generic;
+        if (isBound(loader.getBindingId())) {
+            switch (loader.getId()) {
+                case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
+                    mBlockedParticipants.clear();
+                    for (int i = 0; i < data.getCount(); i++) {
+                        data.moveToPosition(i);
+                        mBlockedParticipants.add(data.getString(
+                                INDEX_BLOCKED_PARTICIPANTS_NORMALIZED_DESTINATION));
+                    }
+                    mListener.setBlockedParticipantsAvailable(data != null && data.getCount() > 0);
+                    break;
+                case CONVERSATION_LIST_LOADER:
+                    mListener.onConversationListCursorUpdated(this, data);
+                    break;
+                default:
+                    Assert.fail("Unknown loader id");
+                    break;
+            }
+        } else {
+            LogUtil.w(TAG, "Loader finished after unbinding list");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoaderReset(final Loader<Cursor> generic) {
+        final BoundCursorLoader loader = (BoundCursorLoader) generic;
+        if (isBound(loader.getBindingId())) {
+            switch (loader.getId()) {
+                case BLOCKED_PARTICIPANTS_AVAILABLE_LOADER:
+                    mListener.setBlockedParticipantsAvailable(false);
+                    break;
+                case CONVERSATION_LIST_LOADER:
+                    mListener.onConversationListCursorUpdated(this, null);
+                    break;
+                default:
+                    Assert.fail("Unknown loader id");
+                    break;
+            }
+        } else {
+            LogUtil.w(TAG, "Loader reset after unbinding list");
+        }
+    }
+
+    private Bundle mArgs;
+
+    public void init(final LoaderManager loaderManager,
+            final BindingBase<ConversationListData> binding) {
+        mArgs = new Bundle();
+        mArgs.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(CONVERSATION_LIST_LOADER, mArgs, this);
+        mLoaderManager.initLoader(BLOCKED_PARTICIPANTS_AVAILABLE_LOADER, mArgs, this);
+    }
+
+    public void handleMessagesSeen() {
+        BugleNotifications.markAllMessagesAsSeen();
+
+        SmsReceiver.cancelSecondaryUserNotification();
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(CONVERSATION_LIST_LOADER);
+            mLoaderManager.destroyLoader(BLOCKED_PARTICIPANTS_AVAILABLE_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    public boolean getHasFirstSyncCompleted() {
+        final SyncManager syncManager = DataModel.get().getSyncManager();
+        return syncManager.getHasFirstSyncCompleted();
+    }
+
+    public void setScrolledToNewestConversation(boolean scrolledToNewestConversation) {
+        DataModel.get().setConversationListScrolledToNewestConversation(
+                scrolledToNewestConversation);
+        if (scrolledToNewestConversation) {
+            handleMessagesSeen();
+        }
+    }
+
+    public HashSet<String> getBlockedParticipants() {
+        return mBlockedParticipants;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationListItemData.java b/src/com/android/messaging/datamodel/data/ConversationListItemData.java
new file mode 100644
index 0000000..f627a09
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationListItemData.java
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.action.DeleteConversationAction;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.Dates;
+import com.google.common.base.Joiner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class wrapping the conversation list view used to display each item in conversation list
+ */
+public class ConversationListItemData {
+    private String mConversationId;
+    private String mName;
+    private String mIcon;
+    private boolean mIsRead;
+    private long mTimestamp;
+    private String mSnippetText;
+    private Uri mPreviewUri;
+    private String mPreviewContentType;
+    private long mParticipantContactId;
+    private String mParticipantLookupKey;
+    private String mOtherParticipantNormalizedDestination;
+    private String mSelfId;
+    private int mParticipantCount;
+    private boolean mNotificationEnabled;
+    private String mNotificationSoundUri;
+    private boolean mNotificationVibrate;
+    private boolean mIncludeEmailAddress;
+    private int mMessageStatus;
+    private int mMessageRawTelephonyStatus;
+    private boolean mShowDraft;
+    private Uri mDraftPreviewUri;
+    private String mDraftPreviewContentType;
+    private String mDraftSnippetText;
+    private boolean mIsArchived;
+    private String mSubject;
+    private String mDraftSubject;
+    private String mSnippetSenderFirstName;
+    private String mSnippetSenderDisplayDestination;
+    private boolean mIsEnterprise;
+
+    public ConversationListItemData() {
+    }
+
+    public void bind(final Cursor cursor) {
+        bind(cursor, false);
+    }
+
+    public void bind(final Cursor cursor, final boolean ignoreDraft) {
+        mConversationId = cursor.getString(INDEX_ID);
+        mName = cursor.getString(INDEX_CONVERSATION_NAME);
+        mIcon = cursor.getString(INDEX_CONVERSATION_ICON);
+        mSnippetText = cursor.getString(INDEX_SNIPPET_TEXT);
+        mTimestamp = cursor.getLong(INDEX_SORT_TIMESTAMP);
+        mIsRead = cursor.getInt(INDEX_READ) == 1;
+        final String previewUriString = cursor.getString(INDEX_PREVIEW_URI);
+        mPreviewUri = TextUtils.isEmpty(previewUriString) ? null : Uri.parse(previewUriString);
+        mPreviewContentType = cursor.getString(INDEX_PREVIEW_CONTENT_TYPE);
+        mParticipantContactId = cursor.getLong(INDEX_PARTICIPANT_CONTACT_ID);
+        mParticipantLookupKey = cursor.getString(INDEX_PARTICIPANT_LOOKUP_KEY);
+        mOtherParticipantNormalizedDestination = cursor.getString(
+                INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION);
+        mSelfId = cursor.getString(INDEX_SELF_ID);
+        mParticipantCount = cursor.getInt(INDEX_PARTICIPANT_COUNT);
+        mNotificationEnabled = cursor.getInt(INDEX_NOTIFICATION_ENABLED) == 1;
+        mNotificationSoundUri = cursor.getString(INDEX_NOTIFICATION_SOUND_URI);
+        mNotificationVibrate = cursor.getInt(INDEX_NOTIFICATION_VIBRATION) == 1;
+        mIncludeEmailAddress = cursor.getInt(INDEX_INCLUDE_EMAIL_ADDRESS) == 1;
+        mMessageStatus = cursor.getInt(INDEX_MESSAGE_STATUS);
+        mMessageRawTelephonyStatus = cursor.getInt(INDEX_MESSAGE_RAW_TELEPHONY_STATUS);
+        if (!ignoreDraft) {
+            mShowDraft = cursor.getInt(INDEX_SHOW_DRAFT) == 1;
+            final String draftPreviewUriString = cursor.getString(INDEX_DRAFT_PREVIEW_URI);
+            mDraftPreviewUri = TextUtils.isEmpty(draftPreviewUriString) ?
+                    null : Uri.parse(draftPreviewUriString);
+            mDraftPreviewContentType = cursor.getString(INDEX_DRAFT_PREVIEW_CONTENT_TYPE);
+            mDraftSnippetText = cursor.getString(INDEX_DRAFT_SNIPPET_TEXT);
+            mDraftSubject = cursor.getString(INDEX_DRAFT_SUBJECT_TEXT);
+        } else {
+            mShowDraft = false;
+            mDraftPreviewUri = null;
+            mDraftPreviewContentType = null;
+            mDraftSnippetText = null;
+            mDraftSubject = null;
+        }
+
+        mIsArchived = cursor.getInt(INDEX_ARCHIVE_STATUS) == 1;
+        mSubject = cursor.getString(INDEX_SUBJECT_TEXT);
+        mSnippetSenderFirstName = cursor.getString(INDEX_SNIPPET_SENDER_FIRST_NAME);
+        mSnippetSenderDisplayDestination =
+                cursor.getString(INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION);
+        mIsEnterprise = cursor.getInt(INDEX_IS_ENTERPRISE) == 1;
+    }
+
+    public String getConversationId() {
+        return mConversationId;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public String getIcon() {
+        return mIcon;
+    }
+
+    public boolean getIsRead() {
+        return mIsRead;
+    }
+
+    public String getFormattedTimestamp() {
+        return Dates.getConversationTimeString(mTimestamp).toString();
+    }
+
+    public long getTimestamp() {
+        return mTimestamp;
+    }
+
+    public String getSnippetText() {
+        return mSnippetText;
+    }
+
+    public Uri getPreviewUri() {
+        return mPreviewUri;
+    }
+
+    public String getPreviewContentType() {
+        return mPreviewContentType;
+    }
+
+    /**
+      * @see ConversationColumns#PARTICIPANT_CONTACT_ID
+      * @return the contact id of the participant if it is a 1:1 conversation, -1 for group.
+      */
+    public long getParticipantContactId() {
+        return mParticipantContactId;
+    }
+
+    /**
+     * @see ConversationColumns#IS_ENTERPRISE
+     * @return whether the conversation is enterprise.
+     */
+    public boolean isEnterprise() {
+        return mIsEnterprise;
+    }
+
+    public String getParticipantLookupKey() {
+        return mParticipantLookupKey;
+    }
+
+    public String getOtherParticipantNormalizedDestination() {
+        return mOtherParticipantNormalizedDestination;
+    }
+
+    public String getSelfId() {
+        return mSelfId;
+    }
+
+    public int getParticipantCount() {
+        return mParticipantCount;
+    }
+
+    public boolean getIsGroup() {
+        // Participant count excludes self
+        return (mParticipantCount > 1);
+    }
+
+    public boolean getIncludeEmailAddress() {
+        return mIncludeEmailAddress;
+    }
+
+    public boolean getNotificationEnabled() {
+        return mNotificationEnabled;
+    }
+
+    public String getNotificationSoundUri() {
+        return mNotificationSoundUri;
+    }
+
+    public boolean getNotifiationVibrate() {
+        return mNotificationVibrate;
+    }
+
+    public final boolean getIsFailedStatus() {
+        return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED ||
+                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER ||
+                mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
+                mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE);
+    }
+
+    public final boolean getIsSendRequested() {
+        return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND ||
+                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY ||
+                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_SENDING ||
+                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_RESENDING);
+    }
+
+    public boolean getIsMessageTypeOutgoing() {
+        return !MessageData.getIsIncoming(mMessageStatus);
+    }
+
+    public int getMessageRawTelephonyStatus() {
+        return mMessageRawTelephonyStatus;
+    }
+
+    public int getMessageStatus() {
+        return mMessageStatus;
+    }
+
+    public boolean getShowDraft() {
+        return mShowDraft;
+    }
+
+    public String getDraftSnippetText() {
+        return mDraftSnippetText;
+    }
+
+    public Uri getDraftPreviewUri() {
+        return mDraftPreviewUri;
+    }
+
+    public String getDraftPreviewContentType() {
+        return mDraftPreviewContentType;
+    }
+
+    public boolean getIsArchived() {
+        return mIsArchived;
+    }
+
+    public String getSubject() {
+        return mSubject;
+    }
+
+    public String getDraftSubject() {
+        return mDraftSubject;
+    }
+
+    public String getSnippetSenderName() {
+        if (!TextUtils.isEmpty(mSnippetSenderFirstName)) {
+            return mSnippetSenderFirstName;
+        }
+        return mSnippetSenderDisplayDestination;
+    }
+
+    public void deleteConversation() {
+        DeleteConversationAction.deleteConversation(mConversationId, mTimestamp);
+    }
+
+    /**
+     * Get the name of the view for this data item
+     */
+    public static final String getConversationListView() {
+        return CONVERSATION_LIST_VIEW;
+    }
+
+    public static final String getConversationListViewSql() {
+        return CONVERSATION_LIST_VIEW_SQL;
+    }
+
+    private static final String CONVERSATION_LIST_VIEW = "conversation_list_view";
+
+    private static final String CONVERSATION_LIST_VIEW_PROJECTION =
+            DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns._ID
+            + " as " + ConversationListViewColumns._ID + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NAME
+            + " as " + ConversationListViewColumns.NAME + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.CURRENT_SELF_ID
+            + " as " + ConversationListViewColumns.CURRENT_SELF_ID + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ARCHIVE_STATUS
+            + " as " + ConversationListViewColumns.ARCHIVE_STATUS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.READ
+            + " as " + ConversationListViewColumns.READ + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ICON
+            + " as " + ConversationListViewColumns.ICON + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_CONTACT_ID
+            + " as " + ConversationListViewColumns.PARTICIPANT_CONTACT_ID + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_LOOKUP_KEY
+            + " as " + ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.'
+                    + ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION
+            + " as " + ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SORT_TIMESTAMP
+            + " as " + ConversationListViewColumns.SORT_TIMESTAMP + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SHOW_DRAFT
+            + " as " + ConversationListViewColumns.SHOW_DRAFT + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SNIPPET_TEXT
+            + " as " + ConversationListViewColumns.DRAFT_SNIPPET_TEXT + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_PREVIEW_URI
+            + " as " + ConversationListViewColumns.DRAFT_PREVIEW_URI + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SUBJECT_TEXT
+            + " as " + ConversationListViewColumns.DRAFT_SUBJECT_TEXT + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.'
+                    + ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE
+            + " as " + ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_URI
+            + " as " + ConversationListViewColumns.PREVIEW_URI + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_CONTENT_TYPE
+            + " as " + ConversationListViewColumns.PREVIEW_CONTENT_TYPE + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_COUNT
+            + " as " + ConversationListViewColumns.PARTICIPANT_COUNT + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_ENABLED
+            + " as " + ConversationListViewColumns.NOTIFICATION_ENABLED + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_SOUND_URI
+            + " as " + ConversationListViewColumns.NOTIFICATION_SOUND_URI + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_VIBRATION
+            + " as " + ConversationListViewColumns.NOTIFICATION_VIBRATION + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' +
+                    ConversationColumns.INCLUDE_EMAIL_ADDRESS
+            + " as " + ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS
+            + " as " + ConversationListViewColumns.MESSAGE_STATUS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RAW_TELEPHONY_STATUS
+            + " as " + ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID
+            + " as " + ConversationListViewColumns.MESSAGE_ID + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FIRST_NAME
+            + " as " + ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION
+            + " as " + ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.IS_ENTERPRISE
+            + " as " + ConversationListViewColumns.IS_ENTERPRISE;
+
+    private static final String JOIN_PARTICIPANTS =
+            " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE + " ON ("
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID
+            + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + DatabaseHelper.ParticipantColumns._ID
+            + ") ";
+
+    // View that makes latest message read flag available with rest of conversation data.
+    private static final String CONVERSATION_LIST_VIEW_SQL = "CREATE VIEW " +
+            CONVERSATION_LIST_VIEW + " AS SELECT "
+            + CONVERSATION_LIST_VIEW_PROJECTION + ", "
+            // Snippet not part of the base projection shared with search view
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SNIPPET_TEXT
+            + " as " + ConversationListViewColumns.SNIPPET_TEXT + ", "
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SUBJECT_TEXT
+            + " as " + ConversationListViewColumns.SUBJECT_TEXT + " "
+            + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE
+            + " LEFT JOIN " + DatabaseHelper.MESSAGES_TABLE + " ON ("
+            + DatabaseHelper.CONVERSATIONS_TABLE + '.' +  ConversationColumns.LATEST_MESSAGE_ID
+            + '=' + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID + ") "
+            + JOIN_PARTICIPANTS
+            + "ORDER BY " + DatabaseHelper.CONVERSATIONS_TABLE + '.'
+            + ConversationColumns.SORT_TIMESTAMP + " DESC";
+
+    public static class ConversationListViewColumns implements BaseColumns {
+        public static final String _ID = ConversationColumns._ID;
+        static final String NAME = ConversationColumns.NAME;
+        static final String ARCHIVE_STATUS = ConversationColumns.ARCHIVE_STATUS;
+        static final String READ = MessageColumns.READ;
+        static final String SORT_TIMESTAMP = ConversationColumns.SORT_TIMESTAMP;
+        static final String PREVIEW_URI = ConversationColumns.PREVIEW_URI;
+        static final String PREVIEW_CONTENT_TYPE = ConversationColumns.PREVIEW_CONTENT_TYPE;
+        static final String SNIPPET_TEXT = ConversationColumns.SNIPPET_TEXT;
+        static final String SUBJECT_TEXT = ConversationColumns.SUBJECT_TEXT;
+        static final String ICON = ConversationColumns.ICON;
+        static final String SHOW_DRAFT = ConversationColumns.SHOW_DRAFT;
+        static final String DRAFT_SUBJECT_TEXT = ConversationColumns.DRAFT_SUBJECT_TEXT;
+        static final String DRAFT_PREVIEW_URI = ConversationColumns.DRAFT_PREVIEW_URI;
+        static final String DRAFT_PREVIEW_CONTENT_TYPE =
+                ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE;
+        static final String DRAFT_SNIPPET_TEXT = ConversationColumns.DRAFT_SNIPPET_TEXT;
+        static final String PARTICIPANT_CONTACT_ID = ConversationColumns.PARTICIPANT_CONTACT_ID;
+        static final String PARTICIPANT_LOOKUP_KEY = ConversationColumns.PARTICIPANT_LOOKUP_KEY;
+        static final String OTHER_PARTICIPANT_NORMALIZED_DESTINATION =
+                ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION;
+        static final String CURRENT_SELF_ID = ConversationColumns.CURRENT_SELF_ID;
+        static final String PARTICIPANT_COUNT = ConversationColumns.PARTICIPANT_COUNT;
+        static final String NOTIFICATION_ENABLED = ConversationColumns.NOTIFICATION_ENABLED;
+        static final String NOTIFICATION_SOUND_URI = ConversationColumns.NOTIFICATION_SOUND_URI;
+        static final String NOTIFICATION_VIBRATION = ConversationColumns.NOTIFICATION_VIBRATION;
+        static final String INCLUDE_EMAIL_ADDRESS =
+                ConversationColumns.INCLUDE_EMAIL_ADDRESS;
+        static final String MESSAGE_STATUS = MessageColumns.STATUS;
+        static final String MESSAGE_RAW_TELEPHONY_STATUS = MessageColumns.RAW_TELEPHONY_STATUS;
+        static final String MESSAGE_ID = "message_id";
+        static final String SNIPPET_SENDER_FIRST_NAME = "snippet_sender_first_name";
+        static final String SNIPPET_SENDER_DISPLAY_DESTINATION =
+                "snippet_sender_display_destination";
+        static final String IS_ENTERPRISE = ConversationColumns.IS_ENTERPRISE;
+    }
+
+    public static final String[] PROJECTION = {
+        ConversationListViewColumns._ID,
+        ConversationListViewColumns.NAME,
+        ConversationListViewColumns.ICON,
+        ConversationListViewColumns.SNIPPET_TEXT,
+        ConversationListViewColumns.SORT_TIMESTAMP,
+        ConversationListViewColumns.READ,
+        ConversationListViewColumns.PREVIEW_URI,
+        ConversationListViewColumns.PREVIEW_CONTENT_TYPE,
+        ConversationListViewColumns.PARTICIPANT_CONTACT_ID,
+        ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY,
+        ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION,
+        ConversationListViewColumns.PARTICIPANT_COUNT,
+        ConversationListViewColumns.CURRENT_SELF_ID,
+        ConversationListViewColumns.NOTIFICATION_ENABLED,
+        ConversationListViewColumns.NOTIFICATION_SOUND_URI,
+        ConversationListViewColumns.NOTIFICATION_VIBRATION,
+        ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS,
+        ConversationListViewColumns.MESSAGE_STATUS,
+        ConversationListViewColumns.SHOW_DRAFT,
+        ConversationListViewColumns.DRAFT_PREVIEW_URI,
+        ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE,
+        ConversationListViewColumns.DRAFT_SNIPPET_TEXT,
+        ConversationListViewColumns.ARCHIVE_STATUS,
+        ConversationListViewColumns.MESSAGE_ID,
+        ConversationListViewColumns.SUBJECT_TEXT,
+        ConversationListViewColumns.DRAFT_SUBJECT_TEXT,
+        ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS,
+        ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME,
+        ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION,
+        ConversationListViewColumns.IS_ENTERPRISE,
+    };
+
+    private static final int INDEX_ID = 0;
+    private static final int INDEX_CONVERSATION_NAME = 1;
+    private static final int INDEX_CONVERSATION_ICON = 2;
+    private static final int INDEX_SNIPPET_TEXT = 3;
+    private static final int INDEX_SORT_TIMESTAMP = 4;
+    private static final int INDEX_READ = 5;
+    private static final int INDEX_PREVIEW_URI = 6;
+    private static final int INDEX_PREVIEW_CONTENT_TYPE = 7;
+    private static final int INDEX_PARTICIPANT_CONTACT_ID = 8;
+    private static final int INDEX_PARTICIPANT_LOOKUP_KEY = 9;
+    private static final int INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION = 10;
+    private static final int INDEX_PARTICIPANT_COUNT = 11;
+    private static final int INDEX_SELF_ID = 12;
+    private static final int INDEX_NOTIFICATION_ENABLED = 13;
+    private static final int INDEX_NOTIFICATION_SOUND_URI = 14;
+    private static final int INDEX_NOTIFICATION_VIBRATION = 15;
+    private static final int INDEX_INCLUDE_EMAIL_ADDRESS = 16;
+    private static final int INDEX_MESSAGE_STATUS = 17;
+    private static final int INDEX_SHOW_DRAFT = 18;
+    private static final int INDEX_DRAFT_PREVIEW_URI = 19;
+    private static final int INDEX_DRAFT_PREVIEW_CONTENT_TYPE = 20;
+    private static final int INDEX_DRAFT_SNIPPET_TEXT = 21;
+    private static final int INDEX_ARCHIVE_STATUS = 22;
+    private static final int INDEX_MESSAGE_ID = 23;
+    private static final int INDEX_SUBJECT_TEXT = 24;
+    private static final int INDEX_DRAFT_SUBJECT_TEXT = 25;
+    private static final int INDEX_MESSAGE_RAW_TELEPHONY_STATUS = 26;
+    private static final int INDEX_SNIPPET_SENDER_FIRST_NAME = 27;
+    private static final int INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION = 28;
+    private static final int INDEX_IS_ENTERPRISE = 29;
+
+    private static final String DIVIDER_TEXT = ", ";
+
+    public static boolean hasAnyEnterpriseContact(
+             final List<ParticipantData> participants) {
+         for (final ParticipantData participant : participants) {
+             if (ContactUtil.isEnterpriseContactId(participant.getContactId())) {
+                 return true;
+             }
+         }
+         return false;
+     }
+
+    /**
+     * Get a conversation from the local DB based on the conversation id.
+     *
+     * @param dbWrapper       The database
+     * @param conversationId  The conversation Id to read
+     * @return The existing conversation or null
+     */
+    public static ConversationListItemData getExistingConversation(final DatabaseWrapper dbWrapper,
+            final String conversationId) {
+        ConversationListItemData conversation = null;
+
+        // Look for an existing conversation in the db with this conversation id
+        Cursor cursor = null;
+        try {
+            // TODO: Should we be able to read a row from just the conversation table?
+            cursor = dbWrapper.query(getConversationListView(),
+                    PROJECTION,
+                    ConversationColumns._ID + "=?",
+                    new String[] { conversationId },
+                    null, null, null);
+            Assert.inRange(cursor.getCount(), 0, 1);
+            if (cursor.moveToFirst()) {
+                conversation = new ConversationListItemData();
+                conversation.bind(cursor);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return conversation;
+    }
+
+    public static String generateConversationName(final List<ParticipantData>
+            participants) {
+        if (participants.size() == 1) {
+            // Prefer full name over first name for 1:1 conversation
+            return participants.get(0).getDisplayName(true);
+        }
+
+        final ArrayList<String> participantNames = new ArrayList<String>();
+        for (final ParticipantData participant : participants) {
+            // Prefer first name over full name for group conversation
+            participantNames.add(participant.getDisplayName(false));
+        }
+
+        final Joiner joiner = Joiner.on(DIVIDER_TEXT).skipNulls();
+        return joiner.join(participantNames);
+    }
+
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationMessageBubbleData.java b/src/com/android/messaging/datamodel/data/ConversationMessageBubbleData.java
new file mode 100644
index 0000000..f329f46
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationMessageBubbleData.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.text.TextUtils;
+
+/**
+ * Holds data for conversation message bubble which keeps track of whether it's been bound to
+ * a new message.
+ */
+public class ConversationMessageBubbleData {
+    private String mMessageId;
+
+    /**
+     * Binds to ConversationMessageData instance.
+     * @return true if we are binding to a different message, false if we are binding to the
+     *         same message (e.g. in order to update the status text)
+     */
+    public boolean bind(final ConversationMessageData data) {
+        final boolean changed = !TextUtils.equals(mMessageId, data.getMessageId());
+        mMessageId = data.getMessageId();
+        return changed;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationMessageData.java b/src/com/android/messaging/datamodel/data/ConversationMessageData.java
new file mode 100644
index 0000000..2a85277
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationMessageData.java
@@ -0,0 +1,919 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Predicate;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Class representing a message within a conversation sequence. The message parts
+ * are available via the getParts() method.
+ *
+ * TODO: See if we can delegate to MessageData for the logic that this class duplicates
+ * (e.g. getIsMms).
+ */
+public class ConversationMessageData {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private String mMessageId;
+    private String mConversationId;
+    private String mParticipantId;
+    private int mPartsCount;
+    private List<MessagePartData> mParts;
+    private long mSentTimestamp;
+    private long mReceivedTimestamp;
+    private boolean mSeen;
+    private boolean mRead;
+    private int mProtocol;
+    private int mStatus;
+    private String mSmsMessageUri;
+    private int mSmsPriority;
+    private int mSmsMessageSize;
+    private String mMmsSubject;
+    private long mMmsExpiry;
+    private int mRawTelephonyStatus;
+    private String mSenderFullName;
+    private String mSenderFirstName;
+    private String mSenderDisplayDestination;
+    private String mSenderNormalizedDestination;
+    private String mSenderProfilePhotoUri;
+    private long mSenderContactId;
+    private String mSenderContactLookupKey;
+    private String mSelfParticipantId;
+
+    /** Are we similar enough to the previous/next messages that we can cluster them? */
+    private boolean mCanClusterWithPreviousMessage;
+    private boolean mCanClusterWithNextMessage;
+
+    public ConversationMessageData() {
+    }
+
+    public void bind(final Cursor cursor) {
+        mMessageId = cursor.getString(INDEX_MESSAGE_ID);
+        mConversationId = cursor.getString(INDEX_CONVERSATION_ID);
+        mParticipantId = cursor.getString(INDEX_PARTICIPANT_ID);
+        mPartsCount = cursor.getInt(INDEX_PARTS_COUNT);
+
+        mParts = makeParts(
+                cursor.getString(INDEX_PARTS_IDS),
+                cursor.getString(INDEX_PARTS_CONTENT_TYPES),
+                cursor.getString(INDEX_PARTS_CONTENT_URIS),
+                cursor.getString(INDEX_PARTS_WIDTHS),
+                cursor.getString(INDEX_PARTS_HEIGHTS),
+                cursor.getString(INDEX_PARTS_TEXTS),
+                mPartsCount,
+                mMessageId);
+
+        mSentTimestamp = cursor.getLong(INDEX_SENT_TIMESTAMP);
+        mReceivedTimestamp = cursor.getLong(INDEX_RECEIVED_TIMESTAMP);
+        mSeen = (cursor.getInt(INDEX_SEEN) != 0);
+        mRead = (cursor.getInt(INDEX_READ) != 0);
+        mProtocol = cursor.getInt(INDEX_PROTOCOL);
+        mStatus = cursor.getInt(INDEX_STATUS);
+        mSmsMessageUri = cursor.getString(INDEX_SMS_MESSAGE_URI);
+        mSmsPriority = cursor.getInt(INDEX_SMS_PRIORITY);
+        mSmsMessageSize = cursor.getInt(INDEX_SMS_MESSAGE_SIZE);
+        mMmsSubject = cursor.getString(INDEX_MMS_SUBJECT);
+        mMmsExpiry = cursor.getLong(INDEX_MMS_EXPIRY);
+        mRawTelephonyStatus = cursor.getInt(INDEX_RAW_TELEPHONY_STATUS);
+        mSenderFullName = cursor.getString(INDEX_SENDER_FULL_NAME);
+        mSenderFirstName = cursor.getString(INDEX_SENDER_FIRST_NAME);
+        mSenderDisplayDestination = cursor.getString(INDEX_SENDER_DISPLAY_DESTINATION);
+        mSenderNormalizedDestination = cursor.getString(INDEX_SENDER_NORMALIZED_DESTINATION);
+        mSenderProfilePhotoUri = cursor.getString(INDEX_SENDER_PROFILE_PHOTO_URI);
+        mSenderContactId = cursor.getLong(INDEX_SENDER_CONTACT_ID);
+        mSenderContactLookupKey = cursor.getString(INDEX_SENDER_CONTACT_LOOKUP_KEY);
+        mSelfParticipantId = cursor.getString(INDEX_SELF_PARTICIPIANT_ID);
+
+        if (!cursor.isFirst() && cursor.moveToPrevious()) {
+            mCanClusterWithPreviousMessage = canClusterWithMessage(cursor);
+            cursor.moveToNext();
+        } else {
+            mCanClusterWithPreviousMessage = false;
+        }
+        if (!cursor.isLast() && cursor.moveToNext()) {
+            mCanClusterWithNextMessage = canClusterWithMessage(cursor);
+            cursor.moveToPrevious();
+        } else {
+            mCanClusterWithNextMessage = false;
+        }
+    }
+
+    private boolean canClusterWithMessage(final Cursor cursor) {
+        final String otherParticipantId = cursor.getString(INDEX_PARTICIPANT_ID);
+        if (!TextUtils.equals(getParticipantId(), otherParticipantId)) {
+            return false;
+        }
+        final int otherStatus = cursor.getInt(INDEX_STATUS);
+        final boolean otherIsIncoming = (otherStatus >= MessageData.BUGLE_STATUS_FIRST_INCOMING);
+        if (getIsIncoming() != otherIsIncoming) {
+            return false;
+        }
+        final long otherReceivedTimestamp = cursor.getLong(INDEX_RECEIVED_TIMESTAMP);
+        final long timestampDeltaMillis = Math.abs(mReceivedTimestamp - otherReceivedTimestamp);
+        if (timestampDeltaMillis > DateUtils.MINUTE_IN_MILLIS) {
+            return false;
+        }
+        final String otherSelfId = cursor.getString(INDEX_SELF_PARTICIPIANT_ID);
+        if (!TextUtils.equals(getSelfParticipantId(), otherSelfId)) {
+            return false;
+        }
+        return true;
+    }
+
+    private static final Character QUOTE_CHAR = '\'';
+    private static final char DIVIDER = '|';
+
+    // statics to avoid unnecessary object allocation
+    private static final StringBuilder sUnquoteStringBuilder = new StringBuilder();
+    private static final ArrayList<String> sUnquoteResults = new ArrayList<String>();
+
+    // this lock is used to guard access to the above statics
+    private static final Object sUnquoteLock = new Object();
+
+    private static void addResult(final ArrayList<String> results, final StringBuilder value) {
+        if (value.length() > 0) {
+            results.add(value.toString());
+        } else {
+            results.add(EMPTY_STRING);
+        }
+    }
+
+    @VisibleForTesting
+    static String[] splitUnquotedString(final String inputString) {
+        if (TextUtils.isEmpty(inputString)) {
+            return new String[0];
+        }
+
+        return inputString.split("\\" + DIVIDER);
+    }
+
+    /**
+     * Takes a group-concated and quoted string and decomposes it into its constituent
+     * parts.  A quoted string starts and ends with a single quote.  Actual single quotes
+     * within the string are escaped using a second single quote.  So, for example, an
+     * input string with 3 constituent parts might look like this:
+     *
+     * 'now is the time'|'I can''t do it'|'foo'
+     *
+     * This would be returned as an array of 3 strings as follows:
+     * now is the time
+     * I can't do it
+     * foo
+     *
+     * This is achieved by walking through the inputString, character by character,
+     * ignoring the outer quotes and the divider and replacing any pair of consecutive
+     * single quotes with a single single quote.
+     *
+     * @param inputString
+     * @return array of constituent strings
+     */
+    @VisibleForTesting
+    static String[] splitQuotedString(final String inputString) {
+        if (TextUtils.isEmpty(inputString)) {
+            return new String[0];
+        }
+
+        // this method can be called from multiple threads but it uses a static
+        // string builder
+        synchronized (sUnquoteLock) {
+            final int length = inputString.length();
+            final ArrayList<String> results = sUnquoteResults;
+            results.clear();
+
+            int characterPos = -1;
+            while (++characterPos < length) {
+                final char mustBeQuote = inputString.charAt(characterPos);
+                Assert.isTrue(QUOTE_CHAR == mustBeQuote);
+                while (++characterPos < length) {
+                    final char currentChar = inputString.charAt(characterPos);
+                    if (currentChar == QUOTE_CHAR) {
+                        final char peekAhead = characterPos < length - 1
+                                ? inputString.charAt(characterPos + 1) : 0;
+
+                        if (peekAhead == QUOTE_CHAR) {
+                            characterPos += 1;  // skip the second quote
+                        } else {
+                            addResult(results, sUnquoteStringBuilder);
+                            sUnquoteStringBuilder.setLength(0);
+
+                            Assert.isTrue((peekAhead == DIVIDER) || (peekAhead == (char) 0));
+                            characterPos += 1;  // skip the divider
+                            break;
+                        }
+                    }
+                    sUnquoteStringBuilder.append(currentChar);
+                }
+            }
+            return results.toArray(new String[results.size()]);
+        }
+    }
+
+    static MessagePartData makePartData(
+            final String partId,
+            final String contentType,
+            final String contentUriString,
+            final String contentWidth,
+            final String contentHeight,
+            final String text,
+            final String messageId) {
+        if (ContentType.isTextType(contentType)) {
+            final MessagePartData textPart = MessagePartData.createTextMessagePart(text);
+            textPart.updatePartId(partId);
+            textPart.updateMessageId(messageId);
+            return textPart;
+        } else {
+            final Uri contentUri = Uri.parse(contentUriString);
+            final int width = Integer.parseInt(contentWidth);
+            final int height = Integer.parseInt(contentHeight);
+            final MessagePartData attachmentPart = MessagePartData.createMediaMessagePart(
+                    contentType, contentUri, width, height);
+            attachmentPart.updatePartId(partId);
+            attachmentPart.updateMessageId(messageId);
+            return attachmentPart;
+        }
+    }
+
+    @VisibleForTesting
+    static List<MessagePartData> makeParts(
+            final String rawIds,
+            final String rawContentTypes,
+            final String rawContentUris,
+            final String rawWidths,
+            final String rawHeights,
+            final String rawTexts,
+            final int partsCount,
+            final String messageId) {
+        final List<MessagePartData> parts = new LinkedList<MessagePartData>();
+        if (partsCount == 1) {
+            parts.add(makePartData(
+                    rawIds,
+                    rawContentTypes,
+                    rawContentUris,
+                    rawWidths,
+                    rawHeights,
+                    rawTexts,
+                    messageId));
+        } else {
+            unpackMessageParts(
+                    parts,
+                    splitUnquotedString(rawIds),
+                    splitQuotedString(rawContentTypes),
+                    splitQuotedString(rawContentUris),
+                    splitUnquotedString(rawWidths),
+                    splitUnquotedString(rawHeights),
+                    splitQuotedString(rawTexts),
+                    partsCount,
+                    messageId);
+        }
+        return parts;
+    }
+
+    @VisibleForTesting
+    static void unpackMessageParts(
+            final List<MessagePartData> parts,
+            final String[] ids,
+            final String[] contentTypes,
+            final String[] contentUris,
+            final String[] contentWidths,
+            final String[] contentHeights,
+            final String[] texts,
+            final int partsCount,
+            final String messageId) {
+
+        Assert.equals(partsCount, ids.length);
+        Assert.equals(partsCount, contentTypes.length);
+        Assert.equals(partsCount, contentUris.length);
+        Assert.equals(partsCount, contentWidths.length);
+        Assert.equals(partsCount, contentHeights.length);
+        Assert.equals(partsCount, texts.length);
+
+        for (int i = 0; i < partsCount; i++) {
+            parts.add(makePartData(
+                    ids[i],
+                    contentTypes[i],
+                    contentUris[i],
+                    contentWidths[i],
+                    contentHeights[i],
+                    texts[i],
+                    messageId));
+        }
+
+        if (parts.size() != partsCount) {
+            LogUtil.wtf(TAG, "Only unpacked " + parts.size() + " parts from message (id="
+                    + messageId + "), expected " + partsCount + " parts");
+        }
+    }
+
+    public final String getMessageId() {
+        return mMessageId;
+    }
+
+    public final String getConversationId() {
+        return mConversationId;
+    }
+
+    public final String getParticipantId() {
+        return mParticipantId;
+    }
+
+    public List<MessagePartData> getParts() {
+        return mParts;
+    }
+
+    public boolean hasText() {
+        for (final MessagePartData part : mParts) {
+            if (part.isText()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get a concatenation of all text parts
+     *
+     * @return the text that is a concatenation of all text parts
+     */
+    public String getText() {
+        // This is optimized for single text part case, which is the majority
+
+        // For single text part, we just return the part without creating the StringBuilder
+        String firstTextPart = null;
+        boolean foundText = false;
+        // For multiple text parts, we need the StringBuilder and the separator for concatenation
+        StringBuilder sb = null;
+        String separator = null;
+        for (final MessagePartData part : mParts) {
+            if (part.isText()) {
+                if (!foundText) {
+                    // First text part
+                    firstTextPart = part.getText();
+                    foundText = true;
+                } else {
+                    // Second and beyond
+                    if (sb == null) {
+                        // Need the StringBuilder and the separator starting from 2nd text part
+                        sb = new StringBuilder();
+                        if (!TextUtils.isEmpty(firstTextPart)) {
+                              sb.append(firstTextPart);
+                        }
+                        separator = BugleGservices.get().getString(
+                                BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR,
+                                BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR_DEFAULT);
+                    }
+                    final String partText = part.getText();
+                    if (!TextUtils.isEmpty(partText)) {
+                        if (!TextUtils.isEmpty(separator) && sb.length() > 0) {
+                            sb.append(separator);
+                        }
+                        sb.append(partText);
+                    }
+                }
+            }
+        }
+        if (sb == null) {
+            // Only one text part
+            return firstTextPart;
+        } else {
+            // More than one
+            return sb.toString();
+        }
+    }
+
+    public boolean hasAttachments() {
+        for (final MessagePartData part : mParts) {
+            if (part.isAttachment()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<MessagePartData> getAttachments() {
+        return getAttachments(null);
+    }
+
+    public List<MessagePartData> getAttachments(final Predicate<MessagePartData> filter) {
+        if (mParts.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<MessagePartData> attachmentParts = new LinkedList<>();
+        for (final MessagePartData part : mParts) {
+            if (part.isAttachment()) {
+                if (filter == null || filter.apply(part)) {
+                    attachmentParts.add(part);
+                }
+            }
+        }
+        return attachmentParts;
+    }
+
+    public final long getSentTimeStamp() {
+        return mSentTimestamp;
+    }
+
+    public final long getReceivedTimeStamp() {
+        return mReceivedTimestamp;
+    }
+
+    public final String getFormattedReceivedTimeStamp() {
+        return Dates.getMessageTimeString(mReceivedTimestamp).toString();
+    }
+
+    public final boolean getIsSeen() {
+        return mSeen;
+    }
+
+    public final boolean getIsRead() {
+        return mRead;
+    }
+
+    public final boolean getIsMms() {
+        return (mProtocol == MessageData.PROTOCOL_MMS ||
+                mProtocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION);
+    }
+
+    public final boolean getIsMmsNotification() {
+        return (mProtocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION);
+    }
+
+    public final boolean getIsSms() {
+        return mProtocol == (MessageData.PROTOCOL_SMS);
+    }
+
+    final int getProtocol() {
+        return mProtocol;
+    }
+
+    public final int getStatus() {
+        return mStatus;
+    }
+
+    public final String getSmsMessageUri() {
+        return mSmsMessageUri;
+    }
+
+    public final int getSmsPriority() {
+        return mSmsPriority;
+    }
+
+    public final int getSmsMessageSize() {
+        return mSmsMessageSize;
+    }
+
+    public final String getMmsSubject() {
+        return mMmsSubject;
+    }
+
+    public final long getMmsExpiry() {
+        return mMmsExpiry;
+    }
+
+    public final int getRawTelephonyStatus() {
+        return mRawTelephonyStatus;
+    }
+
+    public final String getSelfParticipantId() {
+        return mSelfParticipantId;
+    }
+
+    public boolean getIsIncoming() {
+        return (mStatus >= MessageData.BUGLE_STATUS_FIRST_INCOMING);
+    }
+
+    public boolean hasIncomingErrorStatus() {
+        return (mStatus == MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE ||
+                mStatus == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED);
+    }
+
+    public boolean getIsSendComplete() {
+        return (mStatus == MessageData.BUGLE_STATUS_OUTGOING_COMPLETE
+                || mStatus == MessageData.BUGLE_STATUS_OUTGOING_DELIVERED);
+    }
+
+    public String getSenderFullName() {
+        return mSenderFullName;
+    }
+
+    public String getSenderFirstName() {
+        return mSenderFirstName;
+    }
+
+    public String getSenderDisplayDestination() {
+        return mSenderDisplayDestination;
+    }
+
+    public String getSenderNormalizedDestination() {
+        return mSenderNormalizedDestination;
+    }
+
+    public Uri getSenderProfilePhotoUri() {
+        return mSenderProfilePhotoUri == null ? null : Uri.parse(mSenderProfilePhotoUri);
+    }
+
+    public long getSenderContactId() {
+        return mSenderContactId;
+    }
+
+    public String getSenderDisplayName() {
+        if (!TextUtils.isEmpty(mSenderFullName)) {
+            return mSenderFullName;
+        }
+        if (!TextUtils.isEmpty(mSenderFirstName)) {
+            return mSenderFirstName;
+        }
+        return mSenderDisplayDestination;
+    }
+
+    public String getSenderContactLookupKey() {
+        return mSenderContactLookupKey;
+    }
+
+    public boolean getShowDownloadMessage() {
+        return MessageData.getShowDownloadMessage(mStatus);
+    }
+
+    public boolean getShowResendMessage() {
+        return MessageData.getShowResendMessage(mStatus);
+    }
+
+    public boolean getCanForwardMessage() {
+        // Even for outgoing messages, we only allow forwarding if the message has finished sending
+        // as media often has issues when send isn't complete
+        return (mStatus == MessageData.BUGLE_STATUS_OUTGOING_COMPLETE
+                || mStatus == MessageData.BUGLE_STATUS_OUTGOING_DELIVERED
+                || mStatus == MessageData.BUGLE_STATUS_INCOMING_COMPLETE);
+    }
+
+    public boolean getCanCopyMessageToClipboard() {
+        return (hasText() &&
+                (!getIsIncoming() || mStatus == MessageData.BUGLE_STATUS_INCOMING_COMPLETE));
+    }
+
+    public boolean getOneClickResendMessage() {
+        return MessageData.getOneClickResendMessage(mStatus, mRawTelephonyStatus);
+    }
+
+    /**
+     * Get sender's lookup uri.
+     * This method doesn't support corp contacts.
+     *
+     * @return Lookup uri of sender's contact
+     */
+    public Uri getSenderContactLookupUri() {
+        if (mSenderContactId > ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED
+                && !TextUtils.isEmpty(mSenderContactLookupKey)) {
+            return ContactsContract.Contacts.getLookupUri(mSenderContactId,
+                    mSenderContactLookupKey);
+        }
+        return null;
+    }
+
+    public boolean getCanClusterWithPreviousMessage() {
+        return mCanClusterWithPreviousMessage;
+    }
+
+    public boolean getCanClusterWithNextMessage() {
+        return mCanClusterWithNextMessage;
+    }
+
+    @Override
+    public String toString() {
+        return MessageData.toString(mMessageId, mParts);
+    }
+
+    // Data definitions
+
+    public static final String getConversationMessagesQuerySql() {
+        return CONVERSATION_MESSAGES_QUERY_SQL
+                + " AND "
+                // Inject the conversation id
+                + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?)"
+                + CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY;
+    }
+
+    static final String getConversationMessageIdsQuerySql() {
+        return CONVERSATION_MESSAGES_IDS_QUERY_SQL
+                + " AND "
+                // Inject the conversation id
+                + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?)"
+                + CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY;
+    }
+
+    public static final String getNotificationQuerySql() {
+        return CONVERSATION_MESSAGES_QUERY_SQL
+                + " AND "
+                + "(" + DatabaseHelper.MessageColumns.STATUS + " in ("
+                + MessageData.BUGLE_STATUS_INCOMING_COMPLETE + ", "
+                + MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD + ")"
+                + " AND "
+                + DatabaseHelper.MessageColumns.SEEN + " = 0)"
+                + ")"
+                + NOTIFICATION_QUERY_SQL_GROUP_BY;
+    }
+
+    public static final String getWearableQuerySql() {
+        return CONVERSATION_MESSAGES_QUERY_SQL
+                + " AND "
+                + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.CONVERSATION_ID + "=?"
+                + " AND "
+                + DatabaseHelper.MessageColumns.STATUS + " IN ("
+                + MessageData.BUGLE_STATUS_OUTGOING_DELIVERED + ", "
+                + MessageData.BUGLE_STATUS_OUTGOING_COMPLETE + ", "
+                + MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND + ", "
+                + MessageData.BUGLE_STATUS_OUTGOING_SENDING + ", "
+                + MessageData.BUGLE_STATUS_OUTGOING_RESENDING + ", "
+                + MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY + ", "
+                + MessageData.BUGLE_STATUS_INCOMING_COMPLETE + ", "
+                + MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD + ")"
+                + ")"
+                + NOTIFICATION_QUERY_SQL_GROUP_BY;
+    }
+
+    /*
+     * Generate a sqlite snippet to call the quote function on the columnName argument.
+     * The columnName doesn't strictly have to be a column name (e.g. it could be an
+     * expression).
+     */
+    private static String quote(final String columnName) {
+        return "quote(" + columnName + ")";
+    }
+
+    private static String makeGroupConcatString(final String column) {
+        return "group_concat(" + column + ", '" + DIVIDER + "')";
+    }
+
+    private static String makeIfNullString(final String column) {
+        return "ifnull(" + column + "," + "''" + ")";
+    }
+
+    private static String makePartsTableColumnString(final String column) {
+        return DatabaseHelper.PARTS_TABLE + '.' + column;
+    }
+
+    private static String makeCaseWhenString(final String column,
+                                             final boolean quote,
+                                             final String asColumn) {
+        final String fullColumn = makeIfNullString(makePartsTableColumnString(column));
+        final String groupConcatTerm = quote
+                ? makeGroupConcatString(quote(fullColumn))
+                : makeGroupConcatString(fullColumn);
+        return "CASE WHEN (" + CONVERSATION_MESSAGE_VIEW_PARTS_COUNT + ">1) THEN " + groupConcatTerm
+                + " ELSE " + makePartsTableColumnString(column) + " END AS " + asColumn;
+    }
+
+    private static final String CONVERSATION_MESSAGE_VIEW_PARTS_COUNT =
+            "count(" + DatabaseHelper.PARTS_TABLE + '.' + PartColumns._ID + ")";
+
+    private static final String EMPTY_STRING = "";
+
+    private static final String CONVERSATION_MESSAGES_QUERY_PROJECTION_SQL =
+            DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID
+            + " as " + ConversationMessageViewColumns._ID + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.CONVERSATION_ID
+            + " as " + ConversationMessageViewColumns.CONVERSATION_ID + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID
+            + " as " + ConversationMessageViewColumns.PARTICIPANT_ID + ", "
+
+            + makeCaseWhenString(PartColumns._ID, false,
+                    ConversationMessageViewColumns.PARTS_IDS) + ", "
+            + makeCaseWhenString(PartColumns.CONTENT_TYPE, true,
+                    ConversationMessageViewColumns.PARTS_CONTENT_TYPES) + ", "
+            + makeCaseWhenString(PartColumns.CONTENT_URI, true,
+                    ConversationMessageViewColumns.PARTS_CONTENT_URIS) + ", "
+            + makeCaseWhenString(PartColumns.WIDTH, false,
+                    ConversationMessageViewColumns.PARTS_WIDTHS) + ", "
+            + makeCaseWhenString(PartColumns.HEIGHT, false,
+                    ConversationMessageViewColumns.PARTS_HEIGHTS) + ", "
+            + makeCaseWhenString(PartColumns.TEXT, true,
+                    ConversationMessageViewColumns.PARTS_TEXTS) + ", "
+
+            + CONVERSATION_MESSAGE_VIEW_PARTS_COUNT
+            + " as " + ConversationMessageViewColumns.PARTS_COUNT + ", "
+
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENT_TIMESTAMP
+            + " as " + ConversationMessageViewColumns.SENT_TIMESTAMP + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP
+            + " as " + ConversationMessageViewColumns.RECEIVED_TIMESTAMP + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SEEN
+            + " as " + ConversationMessageViewColumns.SEEN + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.READ
+            + " as " + ConversationMessageViewColumns.READ + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.PROTOCOL
+            + " as " + ConversationMessageViewColumns.PROTOCOL + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS
+            + " as " + ConversationMessageViewColumns.STATUS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_MESSAGE_URI
+            + " as " + ConversationMessageViewColumns.SMS_MESSAGE_URI + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_PRIORITY
+            + " as " + ConversationMessageViewColumns.SMS_PRIORITY + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SMS_MESSAGE_SIZE
+            + " as " + ConversationMessageViewColumns.SMS_MESSAGE_SIZE + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.MMS_SUBJECT
+            + " as " + ConversationMessageViewColumns.MMS_SUBJECT + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.MMS_EXPIRY
+            + " as " + ConversationMessageViewColumns.MMS_EXPIRY + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RAW_TELEPHONY_STATUS
+            + " as " + ConversationMessageViewColumns.RAW_TELEPHONY_STATUS + ", "
+            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SELF_PARTICIPANT_ID
+            + " as " + ConversationMessageViewColumns.SELF_PARTICIPANT_ID + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FULL_NAME
+            + " as " + ConversationMessageViewColumns.SENDER_FULL_NAME + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FIRST_NAME
+            + " as " + ConversationMessageViewColumns.SENDER_FIRST_NAME + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION
+            + " as " + ConversationMessageViewColumns.SENDER_DISPLAY_DESTINATION + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.NORMALIZED_DESTINATION
+            + " as " + ConversationMessageViewColumns.SENDER_NORMALIZED_DESTINATION + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.PROFILE_PHOTO_URI
+            + " as " + ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.CONTACT_ID
+            + " as " + ConversationMessageViewColumns.SENDER_CONTACT_ID + ", "
+            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.LOOKUP_KEY
+            + " as " + ConversationMessageViewColumns.SENDER_CONTACT_LOOKUP_KEY + " ";
+
+    private static final String CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL =
+            " FROM " + DatabaseHelper.MESSAGES_TABLE
+            + " LEFT JOIN " + DatabaseHelper.PARTS_TABLE
+            + " ON (" + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns._ID
+            + "=" + DatabaseHelper.PARTS_TABLE + "." + PartColumns.MESSAGE_ID + ") "
+            + " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE
+            + " ON (" + DatabaseHelper.MESSAGES_TABLE + '.' +  MessageColumns.SENDER_PARTICIPANT_ID
+            + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns._ID + ")"
+            // Exclude draft messages from main view
+            + " WHERE (" + DatabaseHelper.MESSAGES_TABLE + "." + MessageColumns.STATUS
+            + " <> " + MessageData.BUGLE_STATUS_OUTGOING_DRAFT;
+
+    // This query is mostly static, except for the injection of conversation id. This is for
+    // performance reasons, to ensure that the query uses indices and does not trigger full scans
+    // of the messages table. See b/17160946 for more details.
+    private static final String CONVERSATION_MESSAGES_QUERY_SQL = "SELECT "
+            + CONVERSATION_MESSAGES_QUERY_PROJECTION_SQL
+            + CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL;
+
+    private static final String CONVERSATION_MESSAGE_IDS_PROJECTION_SQL =
+            DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID
+                    + " as " + ConversationMessageViewColumns._ID + " ";
+
+    private static final String CONVERSATION_MESSAGES_IDS_QUERY_SQL = "SELECT "
+            + CONVERSATION_MESSAGE_IDS_PROJECTION_SQL
+            + CONVERSATION_MESSAGES_QUERY_FROM_WHERE_SQL;
+
+    // Note that we sort DESC and ConversationData reverses the cursor.  This is a performance
+    // issue (improvement) for large cursors.
+    private static final String CONVERSATION_MESSAGES_QUERY_SQL_GROUP_BY =
+            " GROUP BY " + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.MESSAGE_ID
+          + " ORDER BY "
+          + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP + " DESC";
+
+    private static final String NOTIFICATION_QUERY_SQL_GROUP_BY =
+            " GROUP BY " + DatabaseHelper.PARTS_TABLE + '.' + PartColumns.MESSAGE_ID
+          + " ORDER BY "
+          + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RECEIVED_TIMESTAMP + " DESC";
+
+    interface ConversationMessageViewColumns extends BaseColumns {
+        static final String _ID = MessageColumns._ID;
+        static final String CONVERSATION_ID = MessageColumns.CONVERSATION_ID;
+        static final String PARTICIPANT_ID = MessageColumns.SENDER_PARTICIPANT_ID;
+        static final String PARTS_COUNT = "parts_count";
+        static final String SENT_TIMESTAMP = MessageColumns.SENT_TIMESTAMP;
+        static final String RECEIVED_TIMESTAMP = MessageColumns.RECEIVED_TIMESTAMP;
+        static final String SEEN = MessageColumns.SEEN;
+        static final String READ = MessageColumns.READ;
+        static final String PROTOCOL = MessageColumns.PROTOCOL;
+        static final String STATUS = MessageColumns.STATUS;
+        static final String SMS_MESSAGE_URI = MessageColumns.SMS_MESSAGE_URI;
+        static final String SMS_PRIORITY = MessageColumns.SMS_PRIORITY;
+        static final String SMS_MESSAGE_SIZE = MessageColumns.SMS_MESSAGE_SIZE;
+        static final String MMS_SUBJECT = MessageColumns.MMS_SUBJECT;
+        static final String MMS_EXPIRY = MessageColumns.MMS_EXPIRY;
+        static final String RAW_TELEPHONY_STATUS = MessageColumns.RAW_TELEPHONY_STATUS;
+        static final String SELF_PARTICIPANT_ID = MessageColumns.SELF_PARTICIPANT_ID;
+        static final String SENDER_FULL_NAME = ParticipantColumns.FULL_NAME;
+        static final String SENDER_FIRST_NAME = ParticipantColumns.FIRST_NAME;
+        static final String SENDER_DISPLAY_DESTINATION = ParticipantColumns.DISPLAY_DESTINATION;
+        static final String SENDER_NORMALIZED_DESTINATION =
+                ParticipantColumns.NORMALIZED_DESTINATION;
+        static final String SENDER_PROFILE_PHOTO_URI = ParticipantColumns.PROFILE_PHOTO_URI;
+        static final String SENDER_CONTACT_ID = ParticipantColumns.CONTACT_ID;
+        static final String SENDER_CONTACT_LOOKUP_KEY = ParticipantColumns.LOOKUP_KEY;
+        static final String PARTS_IDS = "parts_ids";
+        static final String PARTS_CONTENT_TYPES = "parts_content_types";
+        static final String PARTS_CONTENT_URIS = "parts_content_uris";
+        static final String PARTS_WIDTHS = "parts_widths";
+        static final String PARTS_HEIGHTS = "parts_heights";
+        static final String PARTS_TEXTS = "parts_texts";
+    }
+
+    private static int sIndexIncrementer = 0;
+
+    private static final int INDEX_MESSAGE_ID                    = sIndexIncrementer++;
+    private static final int INDEX_CONVERSATION_ID               = sIndexIncrementer++;
+    private static final int INDEX_PARTICIPANT_ID                = sIndexIncrementer++;
+
+    private static final int INDEX_PARTS_IDS                     = sIndexIncrementer++;
+    private static final int INDEX_PARTS_CONTENT_TYPES           = sIndexIncrementer++;
+    private static final int INDEX_PARTS_CONTENT_URIS            = sIndexIncrementer++;
+    private static final int INDEX_PARTS_WIDTHS                  = sIndexIncrementer++;
+    private static final int INDEX_PARTS_HEIGHTS                 = sIndexIncrementer++;
+    private static final int INDEX_PARTS_TEXTS                   = sIndexIncrementer++;
+
+    private static final int INDEX_PARTS_COUNT                   = sIndexIncrementer++;
+
+    private static final int INDEX_SENT_TIMESTAMP                = sIndexIncrementer++;
+    private static final int INDEX_RECEIVED_TIMESTAMP            = sIndexIncrementer++;
+    private static final int INDEX_SEEN                          = sIndexIncrementer++;
+    private static final int INDEX_READ                          = sIndexIncrementer++;
+    private static final int INDEX_PROTOCOL                      = sIndexIncrementer++;
+    private static final int INDEX_STATUS                        = sIndexIncrementer++;
+    private static final int INDEX_SMS_MESSAGE_URI               = sIndexIncrementer++;
+    private static final int INDEX_SMS_PRIORITY                  = sIndexIncrementer++;
+    private static final int INDEX_SMS_MESSAGE_SIZE              = sIndexIncrementer++;
+    private static final int INDEX_MMS_SUBJECT                   = sIndexIncrementer++;
+    private static final int INDEX_MMS_EXPIRY                    = sIndexIncrementer++;
+    private static final int INDEX_RAW_TELEPHONY_STATUS          = sIndexIncrementer++;
+    private static final int INDEX_SELF_PARTICIPIANT_ID          = sIndexIncrementer++;
+    private static final int INDEX_SENDER_FULL_NAME              = sIndexIncrementer++;
+    private static final int INDEX_SENDER_FIRST_NAME             = sIndexIncrementer++;
+    private static final int INDEX_SENDER_DISPLAY_DESTINATION    = sIndexIncrementer++;
+    private static final int INDEX_SENDER_NORMALIZED_DESTINATION = sIndexIncrementer++;
+    private static final int INDEX_SENDER_PROFILE_PHOTO_URI      = sIndexIncrementer++;
+    private static final int INDEX_SENDER_CONTACT_ID             = sIndexIncrementer++;
+    private static final int INDEX_SENDER_CONTACT_LOOKUP_KEY     = sIndexIncrementer++;
+
+
+    private static String[] sProjection = {
+        ConversationMessageViewColumns._ID,
+        ConversationMessageViewColumns.CONVERSATION_ID,
+        ConversationMessageViewColumns.PARTICIPANT_ID,
+
+        ConversationMessageViewColumns.PARTS_IDS,
+        ConversationMessageViewColumns.PARTS_CONTENT_TYPES,
+        ConversationMessageViewColumns.PARTS_CONTENT_URIS,
+        ConversationMessageViewColumns.PARTS_WIDTHS,
+        ConversationMessageViewColumns.PARTS_HEIGHTS,
+        ConversationMessageViewColumns.PARTS_TEXTS,
+
+        ConversationMessageViewColumns.PARTS_COUNT,
+        ConversationMessageViewColumns.SENT_TIMESTAMP,
+        ConversationMessageViewColumns.RECEIVED_TIMESTAMP,
+        ConversationMessageViewColumns.SEEN,
+        ConversationMessageViewColumns.READ,
+        ConversationMessageViewColumns.PROTOCOL,
+        ConversationMessageViewColumns.STATUS,
+        ConversationMessageViewColumns.SMS_MESSAGE_URI,
+        ConversationMessageViewColumns.SMS_PRIORITY,
+        ConversationMessageViewColumns.SMS_MESSAGE_SIZE,
+        ConversationMessageViewColumns.MMS_SUBJECT,
+        ConversationMessageViewColumns.MMS_EXPIRY,
+        ConversationMessageViewColumns.RAW_TELEPHONY_STATUS,
+        ConversationMessageViewColumns.SELF_PARTICIPANT_ID,
+        ConversationMessageViewColumns.SENDER_FULL_NAME,
+        ConversationMessageViewColumns.SENDER_FIRST_NAME,
+        ConversationMessageViewColumns.SENDER_DISPLAY_DESTINATION,
+        ConversationMessageViewColumns.SENDER_NORMALIZED_DESTINATION,
+        ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
+        ConversationMessageViewColumns.SENDER_CONTACT_ID,
+        ConversationMessageViewColumns.SENDER_CONTACT_LOOKUP_KEY,
+    };
+
+    public static String[] getProjection() {
+        return sProjection;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ConversationParticipantsData.java b/src/com/android/messaging/datamodel/data/ConversationParticipantsData.java
new file mode 100644
index 0000000..962cb74
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ConversationParticipantsData.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import androidx.collection.SimpleArrayMap;
+
+import com.android.messaging.util.Assert;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A class that contains the list of all participants potentially involved in a conversation.
+ * Includes both the participant records for each participant referenced in conversation
+ * participants table (i.e. "other" phone numbers) plus all participants representing self
+ * (i.e. one per sim recorded in the subscription manager db).
+ */
+public class ConversationParticipantsData implements Iterable<ParticipantData> {
+    // A map from a participant id to a participant
+    private final SimpleArrayMap<String, ParticipantData> mConversationParticipantsMap;
+    private int mParticipantCountExcludingSelf = 0;
+
+    public ConversationParticipantsData() {
+        mConversationParticipantsMap = new SimpleArrayMap<String, ParticipantData>();
+    }
+
+    public void bind(final Cursor cursor) {
+        mConversationParticipantsMap.clear();
+        mParticipantCountExcludingSelf = 0;
+        if (cursor != null) {
+            while (cursor.moveToNext()) {
+                final ParticipantData newParticipant = ParticipantData.getFromCursor(cursor);
+                if (!newParticipant.isSelf()) {
+                    mParticipantCountExcludingSelf++;
+                }
+                mConversationParticipantsMap.put(newParticipant.getId(), newParticipant);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    ParticipantData getParticipantById(final String participantId) {
+        return mConversationParticipantsMap.get(participantId);
+    }
+
+    ArrayList<ParticipantData> getParticipantListExcludingSelf() {
+        final ArrayList<ParticipantData> retList =
+                new ArrayList<ParticipantData>(mConversationParticipantsMap.size());
+        for (int i = 0; i < mConversationParticipantsMap.size(); i++) {
+            final ParticipantData participant = mConversationParticipantsMap.valueAt(i);
+            if (!participant.isSelf()) {
+                retList.add(participant);
+            }
+        }
+        return retList;
+    }
+
+    /**
+     * For a 1:1 conversation return the other (not self) participant
+     */
+    public ParticipantData getOtherParticipant() {
+        if (mParticipantCountExcludingSelf == 1) {
+            for (int i = 0; i < mConversationParticipantsMap.size(); i++) {
+                final ParticipantData participant = mConversationParticipantsMap.valueAt(i);
+                if (!participant.isSelf()) {
+                    return participant;
+                }
+            }
+            Assert.fail("Could not find other participant");
+        }
+        return null;
+    }
+
+    public int getNumberOfParticipantsExcludingSelf() {
+        return mParticipantCountExcludingSelf;
+    }
+
+    public boolean isLoaded() {
+        return !mConversationParticipantsMap.isEmpty();
+    }
+
+    @Override
+    public Iterator<ParticipantData> iterator() {
+        return new Iterator<ParticipantData>() {
+            private int mCurrentIndex = -1;
+
+            @Override
+            public boolean hasNext() {
+                return mCurrentIndex < mConversationParticipantsMap.size() - 1;
+            }
+
+            @Override
+            public ParticipantData next() {
+                mCurrentIndex++;
+                if (mCurrentIndex >= mConversationParticipantsMap.size()) {
+                    throw new NoSuchElementException();
+                }
+                return mConversationParticipantsMap.valueAt(mCurrentIndex);
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/DraftMessageData.java b/src/com/android/messaging/datamodel/data/DraftMessageData.java
new file mode 100644
index 0000000..f63c27f
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/DraftMessageData.java
@@ -0,0 +1,867 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.MessageTextStats;
+import com.android.messaging.datamodel.action.ReadDraftDataAction;
+import com.android.messaging.datamodel.action.ReadDraftDataAction.ReadDraftDataActionListener;
+import com.android.messaging.datamodel.action.ReadDraftDataAction.ReadDraftDataActionMonitor;
+import com.android.messaging.datamodel.action.WriteDraftMessageAction;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class DraftMessageData extends BindableData implements ReadDraftDataActionListener {
+
+    /**
+     * Interface for DraftMessageData listeners
+     */
+    public interface DraftMessageDataListener {
+        @RunsOnMainThread
+        void onDraftChanged(DraftMessageData data, int changeFlags);
+
+        @RunsOnMainThread
+        void onDraftAttachmentLimitReached(DraftMessageData data);
+
+        @RunsOnMainThread
+        void onDraftAttachmentLoadFailed();
+    }
+
+    /**
+     * Interface for providing subscription-related data to DraftMessageData
+     */
+    public interface DraftMessageSubscriptionDataProvider {
+        int getConversationSelfSubId();
+    }
+
+    // Flags sent to onDraftChanged to help the receiver limit the amount of work done
+    public static int ATTACHMENTS_CHANGED  =     0x0001;
+    public static int MESSAGE_TEXT_CHANGED =     0x0002;
+    public static int MESSAGE_SUBJECT_CHANGED =  0x0004;
+    // Whether the self participant data has been loaded
+    public static int SELF_CHANGED =             0x0008;
+    public static int ALL_CHANGED =              0x00FF;
+    // ALL_CHANGED intentionally doesn't include WIDGET_CHANGED. ConversationFragment needs to
+    // be notified if the draft it is looking at is changed externally (by a desktop widget) so it
+    // can reload the draft.
+    public static int WIDGET_CHANGED  =          0x0100;
+
+    private final String mConversationId;
+    private ReadDraftDataActionMonitor mMonitor;
+    private final DraftMessageDataEventDispatcher mListeners;
+    private DraftMessageSubscriptionDataProvider mSubscriptionDataProvider;
+
+    private boolean mIncludeEmailAddress;
+    private boolean mIsGroupConversation;
+    private String mMessageText;
+    private String mMessageSubject;
+    private String mSelfId;
+    private MessageTextStats mMessageTextStats;
+    private boolean mSending;
+
+    /** Keeps track of completed attachments in the message draft. This data is persisted to db */
+    private final List<MessagePartData> mAttachments;
+
+    /** A read-only wrapper on mAttachments surfaced to the UI layer for rendering */
+    private final List<MessagePartData> mReadOnlyAttachments;
+
+    /** Keeps track of pending attachments that are being loaded. The pending attachments are
+     * transient, because they are not persisted to the database and are dropped once we go
+     * to the background (after the UI calls saveToStorage) */
+    private final List<PendingAttachmentData> mPendingAttachments;
+
+    /** A read-only wrapper on mPendingAttachments surfaced to the UI layer for rendering */
+    private final List<PendingAttachmentData> mReadOnlyPendingAttachments;
+
+    /** Is the current draft a cached copy of what's been saved to the database. If so, we
+     * may skip loading from database if we are still bound */
+    private boolean mIsDraftCachedCopy;
+
+    /** Whether we are currently asynchronously validating the draft before sending. */
+    private CheckDraftForSendTask mCheckDraftForSendTask;
+
+    public DraftMessageData(final String conversationId) {
+        mConversationId = conversationId;
+        mAttachments = new ArrayList<MessagePartData>();
+        mReadOnlyAttachments = Collections.unmodifiableList(mAttachments);
+        mPendingAttachments = new ArrayList<PendingAttachmentData>();
+        mReadOnlyPendingAttachments = Collections.unmodifiableList(mPendingAttachments);
+        mListeners = new DraftMessageDataEventDispatcher();
+        mMessageTextStats = new MessageTextStats();
+    }
+
+    public void addListener(final DraftMessageDataListener listener) {
+        mListeners.add(listener);
+    }
+
+    public void setSubscriptionDataProvider(final DraftMessageSubscriptionDataProvider provider) {
+        mSubscriptionDataProvider = provider;
+    }
+
+    public void updateFromMessageData(final MessageData message, final String bindingId) {
+        // New attachments have arrived - only update if the user hasn't already edited
+        Assert.notNull(bindingId);
+        // The draft is now synced with actual MessageData and no longer a cached copy.
+        mIsDraftCachedCopy = false;
+        // Do not use the loaded draft if the user began composing a message before the draft loaded
+        // During config changes (orientation), the text fields preserve their data, so allow them
+        // to be the same and still consider the draft unchanged by the user
+        if (isDraftEmpty() || (TextUtils.equals(mMessageText, message.getMessageText()) &&
+                TextUtils.equals(mMessageSubject, message.getMmsSubject()) &&
+                mAttachments.isEmpty())) {
+            // No need to clear as just checked it was empty or a subset
+            setMessageText(message.getMessageText(), false /* notify */);
+            setMessageSubject(message.getMmsSubject(), false /* notify */);
+            for (final MessagePartData part : message.getParts()) {
+                if (part.isAttachment() && getAttachmentCount() >= getAttachmentLimit()) {
+                    dispatchAttachmentLimitReached();
+                    break;
+                }
+
+                if (part instanceof PendingAttachmentData) {
+                    // This is a pending attachment data from share intent (e.g. an shared image
+                    // that we need to persist locally).
+                    final PendingAttachmentData data = (PendingAttachmentData) part;
+                    Assert.equals(PendingAttachmentData.STATE_PENDING, data.getCurrentState());
+                    addOnePendingAttachmentNoNotify(data, bindingId);
+                } else if (part.isAttachment()) {
+                    addOneAttachmentNoNotify(part);
+                }
+            }
+            dispatchChanged(ALL_CHANGED);
+        } else {
+            // The user has started a new message so we throw out the draft message data if there
+            // is one but we also loaded the self metadata and need to let our listeners know.
+            dispatchChanged(SELF_CHANGED);
+        }
+    }
+
+    /**
+     * Create a MessageData object containing a copy of all the parts in this DraftMessageData.
+     *
+     * @param clearLocalCopy whether we should clear out the in-memory copy of the parts. If we
+     *        are simply pausing/resuming and not sending the message, then we can keep
+     * @return the MessageData for the draft, null if self id is not set
+     */
+    public MessageData createMessageWithCurrentAttachments(final boolean clearLocalCopy) {
+        MessageData message = null;
+        if (getIsMms()) {
+            message = MessageData.createDraftMmsMessage(mConversationId, mSelfId,
+                    mMessageText, mMessageSubject);
+            for (final MessagePartData attachment : mAttachments) {
+                message.addPart(attachment);
+            }
+        } else {
+            message = MessageData.createDraftSmsMessage(mConversationId, mSelfId,
+                    mMessageText);
+        }
+
+        if (clearLocalCopy) {
+            // The message now owns all the attachments and the text...
+            clearLocalDraftCopy();
+            dispatchChanged(ALL_CHANGED);
+        } else {
+            // The draft message becomes a cached copy for UI.
+            mIsDraftCachedCopy = true;
+        }
+        return message;
+    }
+
+    private void clearLocalDraftCopy() {
+        mIsDraftCachedCopy = false;
+        mAttachments.clear();
+        setMessageText("");
+        setMessageSubject("");
+    }
+
+    public String getConversationId() {
+        return mConversationId;
+    }
+
+    public String getMessageText() {
+        return mMessageText;
+    }
+
+    public String getMessageSubject() {
+        return mMessageSubject;
+    }
+
+    public boolean getIsMms() {
+        final int selfSubId = getSelfSubId();
+        return MmsSmsUtils.getRequireMmsForEmailAddress(mIncludeEmailAddress, selfSubId) ||
+                (mIsGroupConversation && MmsUtils.groupMmsEnabled(selfSubId)) ||
+                mMessageTextStats.getMessageLengthRequiresMms() || !mAttachments.isEmpty() ||
+                !TextUtils.isEmpty(mMessageSubject);
+    }
+
+    public boolean getIsGroupMmsConversation() {
+        return getIsMms() && mIsGroupConversation;
+    }
+
+    public String getSelfId() {
+        return mSelfId;
+    }
+
+    public int getNumMessagesToBeSent() {
+        return mMessageTextStats.getNumMessagesToBeSent();
+    }
+
+    public int getCodePointsRemainingInCurrentMessage() {
+        return mMessageTextStats.getCodePointsRemainingInCurrentMessage();
+    }
+
+    public int getSelfSubId() {
+        return mSubscriptionDataProvider == null ? ParticipantData.DEFAULT_SELF_SUB_ID :
+                mSubscriptionDataProvider.getConversationSelfSubId();
+    }
+
+    private void setMessageText(final String messageText, final boolean notify) {
+        mMessageText = messageText;
+        mMessageTextStats.updateMessageTextStats(getSelfSubId(), mMessageText);
+        if (notify) {
+            dispatchChanged(MESSAGE_TEXT_CHANGED);
+        }
+    }
+
+    private void setMessageSubject(final String subject, final boolean notify) {
+        mMessageSubject = subject;
+        if (notify) {
+            dispatchChanged(MESSAGE_SUBJECT_CHANGED);
+        }
+    }
+
+    public void setMessageText(final String messageText) {
+        setMessageText(messageText, false);
+    }
+
+    public void setMessageSubject(final String subject) {
+        setMessageSubject(subject, false);
+    }
+
+    public void addAttachments(final Collection<? extends MessagePartData> attachments) {
+        // If the incoming attachments contains a single-only attachment, we need to clear
+        // the existing attachments.
+        for (final MessagePartData data : attachments) {
+            if (data.isSinglePartOnly()) {
+                // clear any existing attachments because the attachment we're adding can only
+                // exist by itself.
+                destroyAttachments();
+                break;
+            }
+        }
+        // If the existing attachments contain a single-only attachment, we need to clear the
+        // existing attachments to make room for the incoming attachment.
+        for (final MessagePartData data : mAttachments) {
+            if (data.isSinglePartOnly()) {
+                // clear any existing attachments because the single attachment can only exist
+                // by itself
+                destroyAttachments();
+                break;
+            }
+        }
+        // If any of the pending attachments contain a single-only attachment, we need to clear the
+        // existing attachments to make room for the incoming attachment.
+        for (final MessagePartData data : mPendingAttachments) {
+            if (data.isSinglePartOnly()) {
+                // clear any existing attachments because the single attachment can only exist
+                // by itself
+                destroyAttachments();
+                break;
+            }
+        }
+
+        boolean reachedLimit = false;
+        for (final MessagePartData data : attachments) {
+            // Don't break out of loop even if limit has been reached so we can destroy all
+            // of the over-limit attachments.
+            reachedLimit |= addOneAttachmentNoNotify(data);
+        }
+        if (reachedLimit) {
+            dispatchAttachmentLimitReached();
+        }
+        dispatchChanged(ATTACHMENTS_CHANGED);
+    }
+
+    public boolean containsAttachment(final Uri contentUri) {
+        for (final MessagePartData existingAttachment : mAttachments) {
+            if (existingAttachment.getContentUri().equals(contentUri)) {
+                return true;
+            }
+        }
+
+        for (final PendingAttachmentData pendingAttachment : mPendingAttachments) {
+            if (pendingAttachment.getContentUri().equals(contentUri)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Try to add one attachment to the attachment list, while guarding against duplicates and
+     * going over the limit.
+     * @return true if the attachment limit was reached, false otherwise
+     */
+    private boolean addOneAttachmentNoNotify(final MessagePartData attachment) {
+        Assert.isTrue(attachment.isAttachment());
+        // Check duplication.
+        for (final MessagePartData existingAttachment : mAttachments) {
+            if (existingAttachment.getContentUri().equals(attachment.getContentUri())) {
+                // Destroy existing attachment and replace with new attachment instead of destroying
+                // new one so that mSelectedImages in GalleryGridView could be maintained correctly.
+                mAttachments.remove(existingAttachment);
+                existingAttachment.destroyAsync();
+                addAttachment(attachment, null /*pendingAttachment*/);
+                return false;
+            }
+        }
+
+        final boolean reachedLimit = getAttachmentCount() >= getAttachmentLimit();
+        if (reachedLimit) {
+            // Never go over the limit.
+            attachment.destroyAsync();
+            return true;
+        } else {
+            addAttachment(attachment, null /*pendingAttachment*/);
+            return false;
+        }
+    }
+
+    private void addAttachment(final MessagePartData attachment,
+            final PendingAttachmentData pendingAttachment) {
+        if (attachment != null && attachment.isSinglePartOnly()) {
+            // clear any existing attachments because the attachment we're adding can only
+            // exist by itself.
+            destroyAttachments();
+        }
+        if (pendingAttachment != null && pendingAttachment.isSinglePartOnly()) {
+            // clear any existing attachments because the attachment we're adding can only
+            // exist by itself.
+            destroyAttachments();
+        }
+        // If the existing attachments contain a single-only attachment, we need to clear the
+        // existing attachments to make room for the incoming attachment.
+        for (final MessagePartData data : mAttachments) {
+            if (data.isSinglePartOnly()) {
+                // clear any existing attachments because the single attachment can only exist
+                // by itself
+                destroyAttachments();
+                break;
+            }
+        }
+        // If any of the pending attachments contain a single-only attachment, we need to clear the
+        // existing attachments to make room for the incoming attachment.
+        for (final MessagePartData data : mPendingAttachments) {
+            if (data.isSinglePartOnly()) {
+                // clear any existing attachments because the single attachment can only exist
+                // by itself
+                destroyAttachments();
+                break;
+            }
+        }
+        if (attachment != null) {
+            mAttachments.add(attachment);
+        } else if (pendingAttachment != null) {
+            mPendingAttachments.add(pendingAttachment);
+        }
+    }
+
+    public void addPendingAttachment(final PendingAttachmentData pendingAttachment,
+            final BindingBase<DraftMessageData> binding) {
+        final boolean reachedLimit = addOnePendingAttachmentNoNotify(pendingAttachment,
+                binding.getBindingId());
+        if (reachedLimit) {
+            dispatchAttachmentLimitReached();
+        }
+        dispatchChanged(ATTACHMENTS_CHANGED);
+    }
+
+    /**
+     * Try to add one pending attachment, while guarding against duplicates and
+     * going over the limit.
+     * @return true if the attachment limit was reached, false otherwise
+     */
+    private boolean addOnePendingAttachmentNoNotify(final PendingAttachmentData pendingAttachment,
+            final String bindingId) {
+        final boolean reachedLimit = getAttachmentCount() >= getAttachmentLimit();
+        if (reachedLimit || containsAttachment(pendingAttachment.getContentUri())) {
+            // Never go over the limit. Never add duplicated attachments.
+            pendingAttachment.destroyAsync();
+            return reachedLimit;
+        } else {
+            Assert.isTrue(!mPendingAttachments.contains(pendingAttachment));
+            Assert.equals(PendingAttachmentData.STATE_PENDING, pendingAttachment.getCurrentState());
+            addAttachment(null /*attachment*/, pendingAttachment);
+
+            pendingAttachment.loadAttachmentForDraft(this, bindingId);
+            return false;
+        }
+    }
+
+    public void setSelfId(final String selfId, final boolean notify) {
+        LogUtil.d(LogUtil.BUGLE_TAG, "DraftMessageData: set selfId=" + selfId
+                + " for conversationId=" + mConversationId);
+        mSelfId = selfId;
+        if (notify) {
+            dispatchChanged(SELF_CHANGED);
+        }
+    }
+
+    public boolean hasAttachments() {
+        return !mAttachments.isEmpty();
+    }
+
+    public boolean hasPendingAttachments() {
+        return !mPendingAttachments.isEmpty();
+    }
+
+    private int getAttachmentCount() {
+        return mAttachments.size() + mPendingAttachments.size();
+    }
+
+    private int getVideoAttachmentCount() {
+        int count = 0;
+        for (MessagePartData part : mAttachments) {
+            if (part.isVideo()) {
+                count++;
+            }
+        }
+        for (MessagePartData part : mPendingAttachments) {
+            if (part.isVideo()) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private int getAttachmentLimit() {
+        return BugleGservices.get().getInt(
+                BugleGservicesKeys.MMS_ATTACHMENT_LIMIT,
+                BugleGservicesKeys.MMS_ATTACHMENT_LIMIT_DEFAULT);
+    }
+
+    public void removeAttachment(final MessagePartData attachment) {
+        for (final MessagePartData existingAttachment : mAttachments) {
+            if (existingAttachment.getContentUri().equals(attachment.getContentUri())) {
+                mAttachments.remove(existingAttachment);
+                existingAttachment.destroyAsync();
+                dispatchChanged(ATTACHMENTS_CHANGED);
+                break;
+            }
+        }
+    }
+
+    public void removeExistingAttachments(final Set<MessagePartData> attachmentsToRemove) {
+        boolean removed = false;
+        final Iterator<MessagePartData> iterator = mAttachments.iterator();
+        while (iterator.hasNext()) {
+            final MessagePartData existingAttachment = iterator.next();
+            if (attachmentsToRemove.contains(existingAttachment)) {
+                iterator.remove();
+                existingAttachment.destroyAsync();
+                removed = true;
+            }
+        }
+
+        if (removed) {
+            dispatchChanged(ATTACHMENTS_CHANGED);
+        }
+    }
+
+    public void removePendingAttachment(final PendingAttachmentData pendingAttachment) {
+        for (final PendingAttachmentData existingAttachment : mPendingAttachments) {
+            if (existingAttachment.getContentUri().equals(pendingAttachment.getContentUri())) {
+                mPendingAttachments.remove(pendingAttachment);
+                pendingAttachment.destroyAsync();
+                dispatchChanged(ATTACHMENTS_CHANGED);
+                break;
+            }
+        }
+    }
+
+    public void updatePendingAttachment(final MessagePartData updatedAttachment,
+            final PendingAttachmentData pendingAttachment) {
+        for (final PendingAttachmentData existingAttachment : mPendingAttachments) {
+            if (existingAttachment.getContentUri().equals(pendingAttachment.getContentUri())) {
+                mPendingAttachments.remove(pendingAttachment);
+                if (pendingAttachment.isSinglePartOnly()) {
+                    updatedAttachment.setSinglePartOnly(true);
+                }
+                mAttachments.add(updatedAttachment);
+                dispatchChanged(ATTACHMENTS_CHANGED);
+                return;
+            }
+        }
+
+        // If we are here, this means the pending attachment has been dropped before the task
+        // to load it was completed. In this case destroy the temporarily staged file since it
+        // is no longer needed.
+        updatedAttachment.destroyAsync();
+    }
+
+    /**
+     * Remove the attachments from the draft and notify any listeners.
+     * @param flags typically this will be ATTACHMENTS_CHANGED. When attachments are cleared in a
+     * widget, flags will also contain WIDGET_CHANGED.
+     */
+    public void clearAttachments(final int flags) {
+        destroyAttachments();
+        dispatchChanged(flags);
+    }
+
+    public List<MessagePartData> getReadOnlyAttachments() {
+        return mReadOnlyAttachments;
+    }
+
+    public List<PendingAttachmentData> getReadOnlyPendingAttachments() {
+        return mReadOnlyPendingAttachments;
+    }
+
+    public boolean loadFromStorage(final BindingBase<DraftMessageData> binding,
+            final MessageData optionalIncomingDraft, boolean clearLocalDraft) {
+        LogUtil.d(LogUtil.BUGLE_TAG, "DraftMessageData: "
+                + (optionalIncomingDraft == null ? "loading" : "setting")
+                + " for conversationId=" + mConversationId);
+        if (clearLocalDraft) {
+            clearLocalDraftCopy();
+        }
+        final boolean isDraftCachedCopy = mIsDraftCachedCopy;
+        mIsDraftCachedCopy = false;
+        // Before reading message from db ensure the caller is bound to us (and knows the id)
+        if (mMonitor == null && !isDraftCachedCopy && isBound(binding.getBindingId())) {
+            mMonitor = ReadDraftDataAction.readDraftData(mConversationId,
+                    optionalIncomingDraft, binding.getBindingId(), this);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Saves the current draft to db. This will save the draft and drop any pending attachments
+     * we have. The UI typically goes into the background when this is called, and instead of
+     * trying to persist the state of the pending attachments (the app may be killed, the activity
+     * may be destroyed), we simply drop the pending attachments for consistency.
+     */
+    public void saveToStorage(final BindingBase<DraftMessageData> binding) {
+        saveToStorageInternal(binding);
+        dropPendingAttachments();
+    }
+
+    private void saveToStorageInternal(final BindingBase<DraftMessageData> binding) {
+        // Create MessageData to store to db, but don't clear the in-memory copy so UI will
+        // continue to display it.
+        // If self id is null then we'll not attempt to change the conversation's self id.
+        final MessageData message = createMessageWithCurrentAttachments(false /* clearLocalCopy */);
+        // Before writing message to db ensure the caller is bound to us (and knows the id)
+        if (isBound(binding.getBindingId())){
+            WriteDraftMessageAction.writeDraftMessage(mConversationId, message);
+        }
+    }
+
+    /**
+     * Called when we are ready to send the message. This will assemble/return the MessageData for
+     * sending and clear the local draft data, both from memory and from DB. This will also bind
+     * the message data with a self Id through which the message will be sent.
+     *
+     * @param binding the binding object from our consumer. We need to make sure we are still bound
+     *        to that binding before saving to storage.
+     */
+    public MessageData prepareMessageForSending(final BindingBase<DraftMessageData> binding) {
+        // We can't send the message while there's still stuff pending.
+        Assert.isTrue(!hasPendingAttachments());
+        mSending = true;
+        // Assembles the message to send and empty working draft data.
+        // If self id is null then message is sent with conversation's self id.
+        final MessageData messageToSend =
+                createMessageWithCurrentAttachments(true /* clearLocalCopy */);
+        // Note sending message will empty the draft data in DB.
+        mSending = false;
+        return messageToSend;
+    }
+
+    public boolean isSending() {
+        return mSending;
+    }
+
+    @Override // ReadDraftMessageActionListener.onReadDraftMessageSucceeded
+    public void onReadDraftDataSucceeded(final ReadDraftDataAction action, final Object data,
+            final MessageData message, final ConversationListItemData conversation) {
+        final String bindingId = (String) data;
+
+        // Before passing draft message on to ui ensure the data is bound to the same bindingid
+        if (isBound(bindingId)) {
+            mSelfId = message.getSelfId();
+            mIsGroupConversation = conversation.getIsGroup();
+            mIncludeEmailAddress = conversation.getIncludeEmailAddress();
+            updateFromMessageData(message, bindingId);
+            LogUtil.d(LogUtil.BUGLE_TAG, "DraftMessageData: draft loaded. "
+                    + "conversationId=" + mConversationId + " selfId=" + mSelfId);
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "DraftMessageData: draft loaded but not bound. "
+                    + "conversationId=" + mConversationId);
+        }
+        mMonitor = null;
+    }
+
+    @Override // ReadDraftMessageActionListener.onReadDraftDataFailed
+    public void onReadDraftDataFailed(final ReadDraftDataAction action, final Object data) {
+        LogUtil.w(LogUtil.BUGLE_TAG, "DraftMessageData: draft not loaded. "
+                + "conversationId=" + mConversationId);
+        // The draft is now synced with actual MessageData and no longer a cached copy.
+        mIsDraftCachedCopy = false;
+        // Just clear the monitor - no update to draft data
+        mMonitor = null;
+    }
+
+    /**
+     * Check if Bugle is default sms app
+     * @return
+     */
+    public boolean getIsDefaultSmsApp() {
+        return PhoneUtils.getDefault().isDefaultSmsApp();
+    }
+
+    @Override //BindableData.unregisterListeners
+    protected void unregisterListeners() {
+        if (mMonitor != null) {
+            mMonitor.unregister();
+        }
+        mMonitor = null;
+        mListeners.clear();
+    }
+
+    private void destroyAttachments() {
+        for (final MessagePartData attachment : mAttachments) {
+            attachment.destroyAsync();
+        }
+        mAttachments.clear();
+        mPendingAttachments.clear();
+    }
+
+    private void dispatchChanged(final int changeFlags) {
+        // No change is expected to be made to the draft if it is in cached copy state.
+        if (mIsDraftCachedCopy) {
+            return;
+        }
+        // Any change in the draft will cancel any pending draft checking task, since the
+        // size/status of the draft may have changed.
+        if (mCheckDraftForSendTask != null) {
+            mCheckDraftForSendTask.cancel(true /* mayInterruptIfRunning */);
+            mCheckDraftForSendTask = null;
+        }
+        mListeners.onDraftChanged(this, changeFlags);
+    }
+
+    private void dispatchAttachmentLimitReached() {
+        mListeners.onDraftAttachmentLimitReached(this);
+    }
+
+    /**
+     * Drop any pending attachments that haven't finished. This is called after the UI goes to
+     * the background and we persist the draft data to the database.
+     */
+    private void dropPendingAttachments() {
+        mPendingAttachments.clear();
+    }
+
+    private boolean isDraftEmpty() {
+        return TextUtils.isEmpty(mMessageText) && mAttachments.isEmpty() &&
+                TextUtils.isEmpty(mMessageSubject);
+    }
+
+    public boolean isCheckingDraft() {
+        return mCheckDraftForSendTask != null && !mCheckDraftForSendTask.isCancelled();
+    }
+
+    public void checkDraftForAction(final boolean checkMessageSize, final int selfSubId,
+            final CheckDraftTaskCallback callback, final Binding<DraftMessageData> binding) {
+        new CheckDraftForSendTask(checkMessageSize, selfSubId, callback, binding)
+            .executeOnThreadPool((Void) null);
+    }
+
+    /**
+     * Allows us to have multiple data listeners for DraftMessageData
+     */
+    private class DraftMessageDataEventDispatcher
+        extends ArrayList<DraftMessageDataListener>
+        implements DraftMessageDataListener {
+
+        @Override
+        @RunsOnMainThread
+        public void onDraftChanged(DraftMessageData data, int changeFlags) {
+            Assert.isMainThread();
+            for (final DraftMessageDataListener listener : this) {
+                listener.onDraftChanged(data, changeFlags);
+            }
+        }
+
+        @Override
+        @RunsOnMainThread
+        public void onDraftAttachmentLimitReached(DraftMessageData data) {
+            Assert.isMainThread();
+            for (final DraftMessageDataListener listener : this) {
+                listener.onDraftAttachmentLimitReached(data);
+            }
+        }
+
+        @Override
+        @RunsOnMainThread
+        public void onDraftAttachmentLoadFailed() {
+            Assert.isMainThread();
+            for (final DraftMessageDataListener listener : this) {
+                listener.onDraftAttachmentLoadFailed();
+            }
+        }
+    }
+
+    public interface CheckDraftTaskCallback {
+        void onDraftChecked(DraftMessageData data, int result);
+    }
+
+    public class CheckDraftForSendTask extends SafeAsyncTask<Void, Void, Integer> {
+        public static final int RESULT_PASSED = 0;
+        public static final int RESULT_HAS_PENDING_ATTACHMENTS = 1;
+        public static final int RESULT_NO_SELF_PHONE_NUMBER_IN_GROUP_MMS = 2;
+        public static final int RESULT_MESSAGE_OVER_LIMIT = 3;
+        public static final int RESULT_VIDEO_ATTACHMENT_LIMIT_EXCEEDED = 4;
+        public static final int RESULT_SIM_NOT_READY = 5;
+        private final boolean mCheckMessageSize;
+        private final int mSelfSubId;
+        private final CheckDraftTaskCallback mCallback;
+        private final String mBindingId;
+        private final List<MessagePartData> mAttachmentsCopy;
+        private int mPreExecuteResult = RESULT_PASSED;
+
+        public CheckDraftForSendTask(final boolean checkMessageSize, final int selfSubId,
+                final CheckDraftTaskCallback callback, final Binding<DraftMessageData> binding) {
+            mCheckMessageSize = checkMessageSize;
+            mSelfSubId = selfSubId;
+            mCallback = callback;
+            mBindingId = binding.getBindingId();
+            // Obtain an immutable copy of the attachment list so we can operate on it in the
+            // background thread.
+            mAttachmentsCopy = new ArrayList<MessagePartData>(mAttachments);
+
+            mCheckDraftForSendTask = this;
+        }
+
+        @Override
+        protected void onPreExecute() {
+            // Perform checking work that can happen on the main thread.
+            if (hasPendingAttachments()) {
+                mPreExecuteResult = RESULT_HAS_PENDING_ATTACHMENTS;
+                return;
+            }
+            if (getIsGroupMmsConversation()) {
+                try {
+                    if (TextUtils.isEmpty(PhoneUtils.get(mSelfSubId).getSelfRawNumber(true))) {
+                        mPreExecuteResult = RESULT_NO_SELF_PHONE_NUMBER_IN_GROUP_MMS;
+                        return;
+                    }
+                } catch (IllegalStateException e) {
+                    // This happens when there is no active subscription, e.g. on Nova
+                    // when the phone switches carrier.
+                    mPreExecuteResult = RESULT_SIM_NOT_READY;
+                    return;
+                }
+            }
+            if (getVideoAttachmentCount() > MmsUtils.MAX_VIDEO_ATTACHMENT_COUNT) {
+                mPreExecuteResult = RESULT_VIDEO_ATTACHMENT_LIMIT_EXCEEDED;
+                return;
+            }
+        }
+
+        @Override
+        protected Integer doInBackgroundTimed(Void... params) {
+            if (mPreExecuteResult != RESULT_PASSED) {
+                return mPreExecuteResult;
+            }
+
+            if (mCheckMessageSize && getIsMessageOverLimit()) {
+                return RESULT_MESSAGE_OVER_LIMIT;
+            }
+            return RESULT_PASSED;
+        }
+
+        @Override
+        protected void onPostExecute(Integer result) {
+            mCheckDraftForSendTask = null;
+            // Only call back if we are bound to the original binding.
+            if (isBound(mBindingId) && !isCancelled()) {
+                mCallback.onDraftChecked(DraftMessageData.this, result);
+            } else {
+                if (!isBound(mBindingId)) {
+                    LogUtil.w(LogUtil.BUGLE_TAG, "Message can't be sent: draft not bound");
+                }
+                if (isCancelled()) {
+                    LogUtil.w(LogUtil.BUGLE_TAG, "Message can't be sent: draft is cancelled");
+                }
+            }
+        }
+
+        @Override
+        protected void onCancelled() {
+            mCheckDraftForSendTask = null;
+        }
+
+        /**
+         * 1. Check if the draft message contains too many attachments to send
+         * 2. Computes the minimum size that this message could be compressed/downsampled/encoded
+         * before sending and check if it meets the carrier max size for sending.
+         * @see MessagePartData#getMinimumSizeInBytesForSending()
+         */
+        @DoesNotRunOnMainThread
+        private boolean getIsMessageOverLimit() {
+            Assert.isNotMainThread();
+            if (mAttachmentsCopy.size() > getAttachmentLimit()) {
+                return true;
+            }
+
+            // Aggregate the size from all the attachments.
+            long totalSize = 0;
+            for (final MessagePartData attachment : mAttachmentsCopy) {
+                totalSize += attachment.getMinimumSizeInBytesForSending();
+            }
+            return totalSize > MmsConfig.get(mSelfSubId).getMaxMessageSize();
+        }
+    }
+
+    public void onPendingAttachmentLoadFailed(PendingAttachmentData data) {
+        mListeners.onDraftAttachmentLoadFailed();
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/GalleryGridItemData.java b/src/com/android/messaging/datamodel/data/GalleryGridItemData.java
new file mode 100644
index 0000000..941d38d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/GalleryGridItemData.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.MediaStore.MediaColumns;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.media.FileImageRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.datamodel.media.VideoThumbnailRequestDescriptor;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * Provides data for GalleryGridItemView
+ */
+public class GalleryGridItemData {
+    public static final String[] MEDIA_PROJECTION = new String[] {
+        MediaColumns._ID,
+        MediaColumns.DATA,
+        MediaColumns.WIDTH,
+        MediaColumns.HEIGHT,
+        MediaColumns.MIME_TYPE,
+        MediaColumns.DATE_MODIFIED,
+        MediaColumns.DISPLAY_NAME};
+
+    public static final String[] SPECIAL_ITEM_COLUMNS = new String[] {
+        BaseColumns._ID
+    };
+
+    private static final int INDEX_ID = 0;
+
+    // For local media gallery.
+    private static final int INDEX_DATA_PATH = 1;
+    private static final int INDEX_WIDTH = 2;
+    private static final int INDEX_HEIGHT = 3;
+    private static final int INDEX_MIME_TYPE = 4;
+    private static final int INDEX_DATE_MODIFIED = 5;
+    private static final int INDEX_DISPLAY_NAME = 6;
+
+    /** A special item's id for picking a media from document picker */
+    public static final String ID_DOCUMENT_PICKER_ITEM = "-1";
+
+    private UriImageRequestDescriptor mImageData;
+    private String mContentType;
+    private boolean mIsDocumentPickerItem;
+    private long mDateSeconds;
+    private String mFileName;
+    private Uri mAudioUri;
+
+    public GalleryGridItemData() {
+    }
+
+    public void bind(final Cursor cursor, final int desiredWidth, final int desiredHeight) {
+        mIsDocumentPickerItem = TextUtils.equals(cursor.getString(INDEX_ID),
+                ID_DOCUMENT_PICKER_ITEM);
+        if (mIsDocumentPickerItem) {
+            mImageData = null;
+            mContentType = null;
+        } else {
+            mContentType = cursor.getString(INDEX_MIME_TYPE);
+            final String filePath = cursor.getString(INDEX_DATA_PATH);
+            final String dateModified = cursor.getString(INDEX_DATE_MODIFIED);
+            mDateSeconds = !TextUtils.isEmpty(dateModified) ? Long.parseLong(dateModified) : -1;
+            if (ContentType.isAudioType(mContentType)) {
+                mImageData = null;
+                mAudioUri = UriUtil.getUriForResourceFile(filePath);
+                mFileName = cursor.getString(INDEX_DISPLAY_NAME);
+            } else { // For image and video types
+                int sourceWidth = cursor.getInt(INDEX_WIDTH);
+                int sourceHeight = cursor.getInt(INDEX_HEIGHT);
+
+                // Guard against bad data
+                if (sourceWidth <= 0) {
+                    sourceWidth = ImageRequest.UNSPECIFIED_SIZE;
+                }
+                if (sourceHeight <= 0) {
+                    sourceHeight = ImageRequest.UNSPECIFIED_SIZE;
+                }
+
+                if (ContentType.isVideoType(mContentType)) {
+                    mImageData = new VideoThumbnailRequestDescriptor(
+                            cursor.getLong(INDEX_ID),
+                            desiredWidth,
+                            desiredHeight,
+                            sourceWidth,
+                            sourceHeight);
+                } else {
+                    mImageData = new FileImageRequestDescriptor(
+                            filePath,
+                            desiredWidth,
+                            desiredHeight,
+                            sourceWidth,
+                            sourceHeight,
+                            true /* canUseThumbnail */,
+                            true /* allowCompression */,
+                            true /* isStatic */);
+                }
+            }
+        }
+    }
+
+    public boolean isDocumentPickerItem() {
+        return mIsDocumentPickerItem;
+    }
+
+    public Uri getImageUri() {
+        return ContentType.isAudioType(mContentType) ? mAudioUri : mImageData.uri;
+    }
+
+    public UriImageRequestDescriptor getImageRequestDescriptor() {
+        return mImageData;
+    }
+
+    public MessagePartData constructMessagePartData(final Rect startRect) {
+        Assert.isTrue(!mIsDocumentPickerItem);
+        return ContentType.isAudioType(mContentType)
+                ? new MediaPickerMessagePartData(startRect, mContentType, mAudioUri, 0, 0)
+                : new MediaPickerMessagePartData(startRect, mContentType, mImageData.uri,
+                        mImageData.sourceWidth, mImageData.sourceHeight);
+    }
+
+    /**
+     * @return The date in seconds. This can be negative if we could not retreive date info
+     */
+    public long getDateSeconds() {
+        return mDateSeconds;
+    }
+
+    public String getContentType() {
+        return mContentType;
+    }
+
+    public String getFileName() {
+        return mFileName;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/LaunchConversationData.java b/src/com/android/messaging/datamodel/data/LaunchConversationData.java
new file mode 100644
index 0000000..7eea580
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/LaunchConversationData.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import com.android.messaging.datamodel.action.ActionMonitor;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.LogUtil;
+
+public class LaunchConversationData extends BindableData implements
+        GetOrCreateConversationActionListener {
+    public interface LaunchConversationDataListener {
+        void onGetOrCreateNewConversation(String conversationId);
+        void onGetOrCreateNewConversationFailed();
+    }
+
+    private LaunchConversationDataListener mListener;
+    private GetOrCreateConversationActionMonitor mMonitor;
+
+    public LaunchConversationData(final LaunchConversationDataListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+        if (mMonitor != null) {
+            mMonitor.unregister();
+        }
+        mMonitor = null;
+    }
+
+    public void getOrCreateConversation(final BindingBase<LaunchConversationData> binding,
+            final String[] recipients) {
+        final String bindingId = binding.getBindingId();
+
+        // Start a new conversation from the list of contacts.
+        if (isBound(bindingId) && mMonitor == null) {
+            mMonitor = GetOrCreateConversationAction.getOrCreateConversation(recipients,
+                    bindingId, this);
+        }
+    }
+
+    @Override
+    @RunsOnMainThread
+    public void onGetOrCreateConversationSucceeded(final ActionMonitor monitor,
+            final Object data, final String conversationId) {
+        Assert.isTrue(monitor == mMonitor);
+        Assert.isTrue(conversationId != null);
+
+        final String bindingId = (String) data;
+        if (isBound(bindingId) && mListener != null) {
+            mListener.onGetOrCreateNewConversation(conversationId);
+        }
+
+        mMonitor = null;
+    }
+
+    @Override
+    @RunsOnMainThread
+    public void onGetOrCreateConversationFailed(final ActionMonitor monitor,
+            final Object data) {
+        Assert.isTrue(monitor == mMonitor);
+        final String bindingId = (String) data;
+        if (isBound(bindingId) && mListener != null) {
+            mListener.onGetOrCreateNewConversationFailed();
+        }
+        LogUtil.e(LogUtil.BUGLE_TAG, "onGetOrCreateConversationFailed");
+        mMonitor = null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/MediaPickerData.java b/src/com/android/messaging/datamodel/data/MediaPickerData.java
new file mode 100644
index 0000000..5a2ef33
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/MediaPickerData.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.GalleryBoundCursorLoader;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Services data needs for MediaPicker.
+ */
+public class MediaPickerData extends BindableData {
+    public interface MediaPickerDataListener {
+        void onMediaPickerDataUpdated(MediaPickerData mediaPickerData, Object data, int loaderId);
+    }
+
+    private static final String BINDING_ID = "bindingId";
+    private final Context mContext;
+    private LoaderManager mLoaderManager;
+    private final GalleryLoaderCallbacks mGalleryLoaderCallbacks;
+    private MediaPickerDataListener mListener;
+
+    public MediaPickerData(final Context context) {
+        mContext = context;
+        mGalleryLoaderCallbacks = new GalleryLoaderCallbacks();
+    }
+
+    public static final int GALLERY_MEDIA_LOADER = 1;
+
+    /**
+     * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times.
+     */
+    private class GalleryLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
+        @Override
+        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+            final String bindingId = args.getString(BINDING_ID);
+            // Check if data still bound to the requesting ui element
+            if (isBound(bindingId)) {
+                switch (id) {
+                    case GALLERY_MEDIA_LOADER:
+                        return new GalleryBoundCursorLoader(bindingId, mContext);
+
+                    default:
+                        Assert.fail("Unknown loader id for gallery picker!");
+                        break;
+                }
+            } else {
+                LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding the media picker");
+            }
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
+            final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+            if (isBound(cursorLoader.getBindingId())) {
+                switch (loader.getId()) {
+                    case GALLERY_MEDIA_LOADER:
+                        mListener.onMediaPickerDataUpdated(MediaPickerData.this, data,
+                                GALLERY_MEDIA_LOADER);
+                        break;
+
+                    default:
+                        Assert.fail("Unknown loader id for gallery picker!");
+                        break;
+                }
+            } else {
+                LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding the media picker");
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onLoaderReset(final Loader<Cursor> loader) {
+            final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+            if (isBound(cursorLoader.getBindingId())) {
+                switch (loader.getId()) {
+                    case GALLERY_MEDIA_LOADER:
+                        mListener.onMediaPickerDataUpdated(MediaPickerData.this, null,
+                                GALLERY_MEDIA_LOADER);
+                        break;
+
+                    default:
+                        Assert.fail("Unknown loader id for media picker!");
+                        break;
+                }
+            } else {
+                LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding the media picker");
+            }
+        }
+    }
+
+
+
+    public void startLoader(final int loaderId, final BindingBase<MediaPickerData> binding,
+            @Nullable Bundle args, final MediaPickerDataListener listener) {
+        if (args == null) {
+            args = new Bundle();
+        }
+        args.putString(BINDING_ID, binding.getBindingId());
+        if (loaderId == GALLERY_MEDIA_LOADER) {
+            mLoaderManager.initLoader(loaderId, args, mGalleryLoaderCallbacks).forceLoad();
+        } else {
+            Assert.fail("Unsupported loader id for media picker!");
+        }
+        mListener = listener;
+    }
+
+    public void destroyLoader(final int loaderId) {
+        mLoaderManager.destroyLoader(loaderId);
+    }
+
+    public void init(final LoaderManager loaderManager) {
+        mLoaderManager = loaderManager;
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(GALLERY_MEDIA_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    /**
+     * Gets the last selected chooser index, or -1 if no selection has been saved.
+     */
+    public int getSelectedChooserIndex() {
+        return BuglePrefs.getApplicationPrefs().getInt(
+                BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX,
+                BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX_DEFAULT);
+    }
+
+    /**
+     * Saves the selected media chooser index.
+     * @param selectedIndex the selected media chooser index.
+     */
+    public void saveSelectedChooserIndex(final int selectedIndex) {
+        BuglePrefs.getApplicationPrefs().putInt(BuglePrefsKeys.SELECTED_MEDIA_PICKER_CHOOSER_INDEX,
+                selectedIndex);
+    }
+
+}
diff --git a/src/com/android/messaging/datamodel/data/MediaPickerMessagePartData.java b/src/com/android/messaging/datamodel/data/MediaPickerMessagePartData.java
new file mode 100644
index 0000000..7de9166
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/MediaPickerMessagePartData.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.graphics.Rect;
+import android.net.Uri;
+
+public class MediaPickerMessagePartData extends MessagePartData {
+    private final Rect mStartRect;
+
+    public MediaPickerMessagePartData(final Rect startRect, final String contentType,
+            final Uri contentUri, final int width, final int height) {
+        this(startRect, null /* messageText */, contentType, contentUri, width, height);
+    }
+
+   public MediaPickerMessagePartData(final Rect startRect, final String messageText,
+            final String contentType, final Uri contentUri, final int width, final int height) {
+        this(startRect, messageText, contentType, contentUri, width, height,
+                false /*onlySingleAttachment*/);
+    }
+
+    public MediaPickerMessagePartData(final Rect startRect, final String contentType,
+            final Uri contentUri, final int width, final int height,
+            final boolean onlySingleAttachment) {
+        this(startRect, null /* messageText */, contentType, contentUri, width, height,
+                onlySingleAttachment);
+    }
+
+    public MediaPickerMessagePartData(final Rect startRect, final String messageText,
+            final String contentType, final Uri contentUri, final int width, final int height,
+            final boolean onlySingleAttachment) {
+        super(messageText, contentType, contentUri, width, height, onlySingleAttachment);
+        mStartRect = startRect;
+    }
+
+    /**
+     * @return The starting rect to animate the attachment preview from in order to perform a smooth
+     * transition
+     */
+    public Rect getStartRect() {
+        return mStartRect;
+    }
+
+    /**
+     * Modify the start rect of the attachment.
+     */
+    public void setStartRect(final Rect startRect) {
+        mStartRect.set(startRect);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/MessageData.java b/src/com/android/messaging/datamodel/data/MessageData.java
new file mode 100644
index 0000000..b2cab48
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/MessageData.java
@@ -0,0 +1,928 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.OsUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MessageData implements Parcelable {
+    private static final String[] sProjection = {
+        MessageColumns._ID,
+        MessageColumns.CONVERSATION_ID,
+        MessageColumns.SENDER_PARTICIPANT_ID,
+        MessageColumns.SELF_PARTICIPANT_ID,
+        MessageColumns.SENT_TIMESTAMP,
+        MessageColumns.RECEIVED_TIMESTAMP,
+        MessageColumns.SEEN,
+        MessageColumns.READ,
+        MessageColumns.PROTOCOL,
+        MessageColumns.STATUS,
+        MessageColumns.SMS_MESSAGE_URI,
+        MessageColumns.SMS_PRIORITY,
+        MessageColumns.SMS_MESSAGE_SIZE,
+        MessageColumns.MMS_SUBJECT,
+        MessageColumns.MMS_TRANSACTION_ID,
+        MessageColumns.MMS_CONTENT_LOCATION,
+        MessageColumns.MMS_EXPIRY,
+        MessageColumns.RAW_TELEPHONY_STATUS,
+        MessageColumns.RETRY_START_TIMESTAMP,
+    };
+
+    private static final int INDEX_ID = 0;
+    private static final int INDEX_CONVERSATION_ID = 1;
+    private static final int INDEX_PARTICIPANT_ID = 2;
+    private static final int INDEX_SELF_ID = 3;
+    private static final int INDEX_SENT_TIMESTAMP = 4;
+    private static final int INDEX_RECEIVED_TIMESTAMP = 5;
+    private static final int INDEX_SEEN = 6;
+    private static final int INDEX_READ = 7;
+    private static final int INDEX_PROTOCOL = 8;
+    private static final int INDEX_BUGLE_STATUS = 9;
+    private static final int INDEX_SMS_MESSAGE_URI = 10;
+    private static final int INDEX_SMS_PRIORITY = 11;
+    private static final int INDEX_SMS_MESSAGE_SIZE = 12;
+    private static final int INDEX_MMS_SUBJECT = 13;
+    private static final int INDEX_MMS_TRANSACTION_ID = 14;
+    private static final int INDEX_MMS_CONTENT_LOCATION = 15;
+    private static final int INDEX_MMS_EXPIRY = 16;
+    private static final int INDEX_RAW_TELEPHONY_STATUS = 17;
+    private static final int INDEX_RETRY_START_TIMESTAMP = 18;
+
+    // SQL statement to insert a "complete" message row (columns based on the projection above).
+    private static final String INSERT_MESSAGE_SQL =
+            "INSERT INTO " + DatabaseHelper.MESSAGES_TABLE + " ( "
+                    + TextUtils.join(", ", Arrays.copyOfRange(sProjection, 1,
+                            INDEX_RETRY_START_TIMESTAMP + 1))
+                    + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+    private String mMessageId;
+    private String mConversationId;
+    private String mParticipantId;
+    private String mSelfId;
+    private long mSentTimestamp;
+    private long mReceivedTimestamp;
+    private boolean mSeen;
+    private boolean mRead;
+    private int mProtocol;
+    private Uri mSmsMessageUri;
+    private int mSmsPriority;
+    private long mSmsMessageSize;
+    private String mMmsSubject;
+    private String mMmsTransactionId;
+    private String mMmsContentLocation;
+    private long mMmsExpiry;
+    private int mRawStatus;
+    private int mStatus;
+    private final ArrayList<MessagePartData> mParts;
+    private long mRetryStartTimestamp;
+
+    // PROTOCOL Values
+    public static final int PROTOCOL_UNKNOWN = -1;              // Unknown type
+    public static final int PROTOCOL_SMS = 0;                   // SMS message
+    public static final int PROTOCOL_MMS = 1;                   // MMS message
+    public static final int PROTOCOL_MMS_PUSH_NOTIFICATION = 2; // MMS WAP push notification
+
+    // Bugle STATUS Values
+    public static final int BUGLE_STATUS_UNKNOWN = 0;
+
+    // Outgoing
+    public static final int BUGLE_STATUS_OUTGOING_COMPLETE                = 1;
+    public static final int BUGLE_STATUS_OUTGOING_DELIVERED               = 2;
+    // Transitions to either YET_TO_SEND or SEND_AFTER_PROCESSING depending attachments.
+    public static final int BUGLE_STATUS_OUTGOING_DRAFT                   = 3;
+    public static final int BUGLE_STATUS_OUTGOING_YET_TO_SEND             = 4;
+    public static final int BUGLE_STATUS_OUTGOING_SENDING                 = 5;
+    public static final int BUGLE_STATUS_OUTGOING_RESENDING               = 6;
+    public static final int BUGLE_STATUS_OUTGOING_AWAITING_RETRY          = 7;
+    public static final int BUGLE_STATUS_OUTGOING_FAILED                  = 8;
+    public static final int BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER = 9;
+
+    // Incoming
+    public static final int BUGLE_STATUS_INCOMING_COMPLETE                   = 100;
+    public static final int BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD     = 101;
+    public static final int BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD   = 102;
+    public static final int BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING         = 103;
+    public static final int BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD     = 104;
+    public static final int BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING           = 105;
+    public static final int BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED            = 106;
+    public static final int BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE   = 107;
+
+    public static final String getStatusDescription(int status) {
+        switch (status) {
+            case BUGLE_STATUS_UNKNOWN:
+                return "UNKNOWN";
+            case BUGLE_STATUS_OUTGOING_COMPLETE:
+                return "OUTGOING_COMPLETE";
+            case BUGLE_STATUS_OUTGOING_DELIVERED:
+                return "OUTGOING_DELIVERED";
+            case BUGLE_STATUS_OUTGOING_DRAFT:
+                return "OUTGOING_DRAFT";
+            case BUGLE_STATUS_OUTGOING_YET_TO_SEND:
+                return "OUTGOING_YET_TO_SEND";
+            case BUGLE_STATUS_OUTGOING_SENDING:
+                return "OUTGOING_SENDING";
+            case BUGLE_STATUS_OUTGOING_RESENDING:
+                return "OUTGOING_RESENDING";
+            case BUGLE_STATUS_OUTGOING_AWAITING_RETRY:
+                return "OUTGOING_AWAITING_RETRY";
+            case BUGLE_STATUS_OUTGOING_FAILED:
+                return "OUTGOING_FAILED";
+            case BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER:
+                return "OUTGOING_FAILED_EMERGENCY_NUMBER";
+            case BUGLE_STATUS_INCOMING_COMPLETE:
+                return "INCOMING_COMPLETE";
+            case BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD:
+                return "INCOMING_YET_TO_MANUAL_DOWNLOAD";
+            case BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                return "INCOMING_RETRYING_MANUAL_DOWNLOAD";
+            case BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
+                return "INCOMING_MANUAL_DOWNLOADING";
+            case BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+                return "INCOMING_RETRYING_AUTO_DOWNLOAD";
+            case BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
+                return "INCOMING_AUTO_DOWNLOADING";
+            case BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED:
+                return "INCOMING_DOWNLOAD_FAILED";
+            case BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE:
+                return "INCOMING_EXPIRED_OR_NOT_AVAILABLE";
+            default:
+                return String.valueOf(status) + " (check MessageData)";
+        }
+    }
+
+    // All incoming messages expect to have status >= BUGLE_STATUS_FIRST_INCOMING
+    public static final int BUGLE_STATUS_FIRST_INCOMING = BUGLE_STATUS_INCOMING_COMPLETE;
+
+    // Detailed MMS failures. Most of the values are defined in PduHeaders. However, a few are
+    // defined here instead. These are never returned in the MMS HTTP response, but are used
+    // internally. The values here must not conflict with any of the existing PduHeader values.
+    public static final int RAW_TELEPHONY_STATUS_UNDEFINED = MmsUtils.PDU_HEADER_VALUE_UNDEFINED;
+    public static final int RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG = 10000;
+
+    // Unknown result code for MMS sending/downloading. This is used as the default value
+    // for result code returned from platform MMS API.
+    public static final int UNKNOWN_RESULT_CODE = 0;
+
+    /**
+     * Create an "empty" message
+     */
+    public MessageData() {
+        mParts = new ArrayList<MessagePartData>();
+    }
+
+    public static String[] getProjection() {
+        return sProjection;
+    }
+
+    /**
+     * Create a draft message for a particular conversation based on supplied content
+     */
+    public static MessageData createDraftMessage(final String conversationId,
+            final String selfId, final MessageData content) {
+        final MessageData message = new MessageData();
+        message.mStatus = BUGLE_STATUS_OUTGOING_DRAFT;
+        message.mProtocol = PROTOCOL_UNKNOWN;
+        message.mConversationId = conversationId;
+        message.mParticipantId = selfId;
+        message.mReceivedTimestamp = System.currentTimeMillis();
+        if (content == null) {
+            message.mParts.add(MessagePartData.createTextMessagePart(""));
+        } else {
+            if (!TextUtils.isEmpty(content.mParticipantId)) {
+                message.mParticipantId = content.mParticipantId;
+            }
+            if (!TextUtils.isEmpty(content.mMmsSubject)) {
+                message.mMmsSubject = content.mMmsSubject;
+            }
+            for (final MessagePartData part : content.getParts()) {
+                message.mParts.add(part);
+            }
+        }
+        message.mSelfId = selfId;
+        return message;
+    }
+
+    /**
+     * Create a draft sms message for a particular conversation
+     */
+    public static MessageData createDraftSmsMessage(final String conversationId,
+            final String selfId, final String messageText) {
+        final MessageData message = new MessageData();
+        message.mStatus = BUGLE_STATUS_OUTGOING_DRAFT;
+        message.mProtocol = PROTOCOL_SMS;
+        message.mConversationId = conversationId;
+        message.mParticipantId = selfId;
+        message.mSelfId = selfId;
+        message.mParts.add(MessagePartData.createTextMessagePart(messageText));
+        message.mReceivedTimestamp = System.currentTimeMillis();
+        return message;
+    }
+
+    /**
+     * Create a draft mms message for a particular conversation
+     */
+    public static MessageData createDraftMmsMessage(final String conversationId,
+            final String selfId, final String messageText, final String subjectText) {
+        final MessageData message = new MessageData();
+        message.mStatus = BUGLE_STATUS_OUTGOING_DRAFT;
+        message.mProtocol = PROTOCOL_MMS;
+        message.mConversationId = conversationId;
+        message.mParticipantId = selfId;
+        message.mSelfId = selfId;
+        message.mMmsSubject = subjectText;
+        message.mReceivedTimestamp = System.currentTimeMillis();
+        if (!TextUtils.isEmpty(messageText)) {
+            message.mParts.add(MessagePartData.createTextMessagePart(messageText));
+        }
+        return message;
+    }
+
+    /**
+     * Create a message received from a particular number in a particular conversation
+     */
+    public static MessageData createReceivedSmsMessage(final Uri uri, final String conversationId,
+            final String participantId, final String selfId, final String messageText,
+            final String subject, final long sent, final long recieved,
+            final boolean seen, final boolean read) {
+        final MessageData message = new MessageData();
+        message.mSmsMessageUri = uri;
+        message.mConversationId = conversationId;
+        message.mParticipantId = participantId;
+        message.mSelfId = selfId;
+        message.mProtocol = PROTOCOL_SMS;
+        message.mStatus = BUGLE_STATUS_INCOMING_COMPLETE;
+        message.mMmsSubject = subject;
+        message.mReceivedTimestamp = recieved;
+        message.mSentTimestamp = sent;
+        message.mParts.add(MessagePartData.createTextMessagePart(messageText));
+        message.mSeen = seen;
+        message.mRead = read;
+        return message;
+    }
+
+    /**
+     * Create a message not yet associated with a particular conversation
+     */
+    public static MessageData createSharedMessage(final String messageText,
+            final String subjectText) {
+        final MessageData message = new MessageData();
+        message.mStatus = BUGLE_STATUS_OUTGOING_DRAFT;
+        message.mMmsSubject = subjectText;
+        if (!TextUtils.isEmpty(messageText)) {
+            message.mParts.add(MessagePartData.createTextMessagePart(messageText));
+        }
+        return message;
+    }
+
+    /**
+     * Create a message from Sms table fields
+     */
+    public static MessageData createSmsMessage(final String messageUri, final String participantId,
+            final String selfId, final String conversationId, final int bugleStatus,
+            final boolean seen, final boolean read, final long sent,
+            final long recieved, final String messageText) {
+        final MessageData message = new MessageData();
+        message.mParticipantId = participantId;
+        message.mSelfId = selfId;
+        message.mConversationId = conversationId;
+        message.mSentTimestamp = sent;
+        message.mReceivedTimestamp = recieved;
+        message.mSeen = seen;
+        message.mRead = read;
+        message.mProtocol = PROTOCOL_SMS;
+        message.mStatus = bugleStatus;
+        message.mSmsMessageUri = Uri.parse(messageUri);
+        message.mParts.add(MessagePartData.createTextMessagePart(messageText));
+        return message;
+    }
+
+    /**
+     * Create a message from Mms table fields
+     */
+    public static MessageData createMmsMessage(final String messageUri, final String participantId,
+            final String selfId, final String conversationId, final boolean isNotification,
+            final int bugleStatus, final String contentLocation, final String transactionId,
+            final int smsPriority, final String subject, final boolean seen, final boolean read,
+            final long size, final int rawStatus, final long expiry, final long sent,
+            final long received) {
+        final MessageData message = new MessageData();
+        message.mParticipantId = participantId;
+        message.mSelfId = selfId;
+        message.mConversationId = conversationId;
+        message.mSentTimestamp = sent;
+        message.mReceivedTimestamp = received;
+        message.mMmsContentLocation = contentLocation;
+        message.mMmsTransactionId = transactionId;
+        message.mSeen = seen;
+        message.mRead = read;
+        message.mStatus = bugleStatus;
+        message.mProtocol = (isNotification ? PROTOCOL_MMS_PUSH_NOTIFICATION : PROTOCOL_MMS);
+        message.mSmsMessageUri = Uri.parse(messageUri);
+        message.mSmsPriority = smsPriority;
+        message.mSmsMessageSize = size;
+        message.mMmsSubject = subject;
+        message.mMmsExpiry = expiry;
+        message.mRawStatus = rawStatus;
+        if (bugleStatus == BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD ||
+                bugleStatus == BUGLE_STATUS_OUTGOING_RESENDING) {
+            // Set the retry start timestamp if this message is already in process of retrying
+            // Either as autodownload is starting or sending already in progress (MMS update)
+            message.mRetryStartTimestamp = received;
+        }
+        return message;
+    }
+
+    public void addPart(final MessagePartData part) {
+        if (part instanceof PendingAttachmentData) {
+            // Pending attachments may only be added to shared message data that's not associated
+            // with any particular conversation, in order to store shared images.
+            Assert.isTrue(mConversationId == null);
+        }
+        mParts.add(part);
+    }
+
+    public Iterable<MessagePartData> getParts() {
+        return mParts;
+    }
+
+    public void bind(final Cursor cursor) {
+        mMessageId = cursor.getString(INDEX_ID);
+        mConversationId = cursor.getString(INDEX_CONVERSATION_ID);
+        mParticipantId = cursor.getString(INDEX_PARTICIPANT_ID);
+        mSelfId = cursor.getString(INDEX_SELF_ID);
+        mSentTimestamp = cursor.getLong(INDEX_SENT_TIMESTAMP);
+        mReceivedTimestamp = cursor.getLong(INDEX_RECEIVED_TIMESTAMP);
+        mSeen = (cursor.getInt(INDEX_SEEN) != 0);
+        mRead = (cursor.getInt(INDEX_READ) != 0);
+        mProtocol = cursor.getInt(INDEX_PROTOCOL);
+        mStatus = cursor.getInt(INDEX_BUGLE_STATUS);
+        final String smsMessageUri = cursor.getString(INDEX_SMS_MESSAGE_URI);
+        mSmsMessageUri = (smsMessageUri == null) ? null : Uri.parse(smsMessageUri);
+        mSmsPriority = cursor.getInt(INDEX_SMS_PRIORITY);
+        mSmsMessageSize = cursor.getLong(INDEX_SMS_MESSAGE_SIZE);
+        mMmsExpiry = cursor.getLong(INDEX_MMS_EXPIRY);
+        mRawStatus = cursor.getInt(INDEX_RAW_TELEPHONY_STATUS);
+        mMmsSubject = cursor.getString(INDEX_MMS_SUBJECT);
+        mMmsTransactionId = cursor.getString(INDEX_MMS_TRANSACTION_ID);
+        mMmsContentLocation = cursor.getString(INDEX_MMS_CONTENT_LOCATION);
+        mRetryStartTimestamp = cursor.getLong(INDEX_RETRY_START_TIMESTAMP);
+    }
+
+    /**
+     * Bind to the draft message data for a conversation. The conversation's self id is used as
+     * the draft's self id.
+     */
+    public void bindDraft(final Cursor cursor, final String conversationSelfId) {
+        bind(cursor);
+        mSelfId = conversationSelfId;
+    }
+
+    protected static String getParticipantId(final Cursor cursor) {
+        return cursor.getString(INDEX_PARTICIPANT_ID);
+    }
+
+    public void populate(final ContentValues values) {
+        values.put(MessageColumns.CONVERSATION_ID, mConversationId);
+        values.put(MessageColumns.SENDER_PARTICIPANT_ID, mParticipantId);
+        values.put(MessageColumns.SELF_PARTICIPANT_ID, mSelfId);
+        values.put(MessageColumns.SENT_TIMESTAMP, mSentTimestamp);
+        values.put(MessageColumns.RECEIVED_TIMESTAMP, mReceivedTimestamp);
+        values.put(MessageColumns.SEEN, mSeen ? 1 : 0);
+        values.put(MessageColumns.READ, mRead ? 1 : 0);
+        values.put(MessageColumns.PROTOCOL, mProtocol);
+        values.put(MessageColumns.STATUS, mStatus);
+        final String smsMessageUri = ((mSmsMessageUri == null) ? null : mSmsMessageUri.toString());
+        values.put(MessageColumns.SMS_MESSAGE_URI, smsMessageUri);
+        values.put(MessageColumns.SMS_PRIORITY, mSmsPriority);
+        values.put(MessageColumns.SMS_MESSAGE_SIZE, mSmsMessageSize);
+        values.put(MessageColumns.MMS_EXPIRY, mMmsExpiry);
+        values.put(MessageColumns.MMS_SUBJECT, mMmsSubject);
+        values.put(MessageColumns.MMS_TRANSACTION_ID, mMmsTransactionId);
+        values.put(MessageColumns.MMS_CONTENT_LOCATION, mMmsContentLocation);
+        values.put(MessageColumns.RAW_TELEPHONY_STATUS, mRawStatus);
+        values.put(MessageColumns.RETRY_START_TIMESTAMP, mRetryStartTimestamp);
+    }
+
+    /**
+     * Note this is not thread safe so callers need to make sure they own the wrapper + statements
+     * while they call this and use the returned value.
+     */
+    public SQLiteStatement getInsertStatement(final DatabaseWrapper db) {
+        final SQLiteStatement insert = db.getStatementInTransaction(
+                DatabaseWrapper.INDEX_INSERT_MESSAGE, INSERT_MESSAGE_SQL);
+        insert.clearBindings();
+        insert.bindString(INDEX_CONVERSATION_ID, mConversationId);
+        insert.bindString(INDEX_PARTICIPANT_ID, mParticipantId);
+        insert.bindString(INDEX_SELF_ID, mSelfId);
+        insert.bindLong(INDEX_SENT_TIMESTAMP, mSentTimestamp);
+        insert.bindLong(INDEX_RECEIVED_TIMESTAMP, mReceivedTimestamp);
+        insert.bindLong(INDEX_SEEN, mSeen ? 1 : 0);
+        insert.bindLong(INDEX_READ, mRead ? 1 : 0);
+        insert.bindLong(INDEX_PROTOCOL, mProtocol);
+        insert.bindLong(INDEX_BUGLE_STATUS, mStatus);
+        if (mSmsMessageUri != null) {
+            insert.bindString(INDEX_SMS_MESSAGE_URI, mSmsMessageUri.toString());
+        }
+        insert.bindLong(INDEX_SMS_PRIORITY, mSmsPriority);
+        insert.bindLong(INDEX_SMS_MESSAGE_SIZE, mSmsMessageSize);
+        insert.bindLong(INDEX_MMS_EXPIRY, mMmsExpiry);
+        if (mMmsSubject != null) {
+            insert.bindString(INDEX_MMS_SUBJECT, mMmsSubject);
+        }
+        if (mMmsTransactionId != null) {
+            insert.bindString(INDEX_MMS_TRANSACTION_ID, mMmsTransactionId);
+        }
+        if (mMmsContentLocation != null) {
+            insert.bindString(INDEX_MMS_CONTENT_LOCATION, mMmsContentLocation);
+        }
+        insert.bindLong(INDEX_RAW_TELEPHONY_STATUS, mRawStatus);
+        insert.bindLong(INDEX_RETRY_START_TIMESTAMP, mRetryStartTimestamp);
+        return insert;
+    }
+
+    public final String getMessageId() {
+        return mMessageId;
+    }
+
+    public final String getConversationId() {
+        return mConversationId;
+    }
+
+    public final String getParticipantId() {
+        return mParticipantId;
+    }
+
+    public final String getSelfId() {
+        return mSelfId;
+    }
+
+    public final long getSentTimeStamp() {
+        return mSentTimestamp;
+    }
+
+    public final long getReceivedTimeStamp() {
+        return mReceivedTimestamp;
+    }
+
+    public final String getFormattedReceivedTimeStamp() {
+        return Dates.getMessageTimeString(mReceivedTimestamp).toString();
+    }
+
+    public final int getProtocol() {
+        return mProtocol;
+    }
+
+    public final int getStatus() {
+        return mStatus;
+    }
+
+    public final Uri getSmsMessageUri() {
+        return mSmsMessageUri;
+    }
+
+    public final int getSmsPriority() {
+        return mSmsPriority;
+    }
+
+    public final long getSmsMessageSize() {
+        return mSmsMessageSize;
+    }
+
+    public final String getMmsSubject() {
+        return mMmsSubject;
+    }
+
+    public final void setMmsSubject(final String subject) {
+        mMmsSubject = subject;
+    }
+
+    public final String getMmsContentLocation() {
+        return mMmsContentLocation;
+    }
+
+    public final String getMmsTransactionId() {
+        return mMmsTransactionId;
+    }
+
+    public final boolean getMessageSeen() {
+        return mSeen;
+    }
+
+    public final long getMmsExpiry() {
+        return mMmsExpiry;
+    }
+
+    /**
+     * For incoming MMS messages this returns the retrieve-status value
+     * For sent MMS messages this returns the response-status value
+     * See PduHeaders.java for possible values
+     * Otherwise (SMS etc) this is RAW_TELEPHONY_STATUS_UNDEFINED
+     */
+    public final int getRawTelephonyStatus() {
+        return mRawStatus;
+    }
+
+    public final void setMessageSeen(final boolean hasSeen) {
+        mSeen = hasSeen;
+    }
+
+    public final boolean getInResendWindow(final long now) {
+        final long maxAgeToResend = BugleGservices.get().getLong(
+                BugleGservicesKeys.MESSAGE_RESEND_TIMEOUT_MS,
+                BugleGservicesKeys.MESSAGE_RESEND_TIMEOUT_MS_DEFAULT);
+        final long age = now - mRetryStartTimestamp;
+        return age < maxAgeToResend;
+    }
+
+    public final boolean getInDownloadWindow(final long now) {
+        final long maxAgeToRedownload = BugleGservices.get().getLong(
+                BugleGservicesKeys.MESSAGE_DOWNLOAD_TIMEOUT_MS,
+                BugleGservicesKeys.MESSAGE_DOWNLOAD_TIMEOUT_MS_DEFAULT);
+        final long age = now - mRetryStartTimestamp;
+        return age < maxAgeToRedownload;
+    }
+
+    static boolean getShowDownloadMessage(final int status) {
+        if (OsUtil.isSecondaryUser()) {
+            // Secondary users can't download mms's. Mms's are downloaded by bugle running as the
+            // primary user.
+            return false;
+        }
+        // Should show option for manual download if status is manual download or failed
+        return (status == BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
+                status == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD ||
+                // If debug is enabled, allow to download an expired or unavailable message.
+                (DebugUtils.isDebugEnabled()
+                        && status == BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE));
+    }
+
+    public boolean canDownloadMessage() {
+        if (OsUtil.isSecondaryUser()) {
+            // Secondary users can't download mms's. Mms's are downloaded by bugle running as the
+            // primary user.
+            return false;
+        }
+        // Can download if status is retrying auto/manual downloading
+        return (mStatus == BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD ||
+                mStatus == BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD);
+    }
+
+    public boolean canRedownloadMessage() {
+        if (OsUtil.isSecondaryUser()) {
+            // Secondary users can't download mms's. Mms's are downloaded by bugle running as the
+            // primary user.
+            return false;
+        }
+        // Can redownload if status is manual download not started or download failed
+        return (mStatus == BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
+                mStatus == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD ||
+                // If debug is enabled, allow to download an expired or unavailable message.
+                (DebugUtils.isDebugEnabled()
+                        && mStatus == BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE));
+    }
+
+    static boolean getShowResendMessage(final int status) {
+        // Should show option to resend if status is failed
+        return (status == BUGLE_STATUS_OUTGOING_FAILED);
+    }
+
+    static boolean getOneClickResendMessage(final int status, final int rawStatus) {
+        // Should show option to resend if status is failed
+        return (status == BUGLE_STATUS_OUTGOING_FAILED
+                && rawStatus == RAW_TELEPHONY_STATUS_UNDEFINED);
+    }
+
+    public boolean canResendMessage() {
+        // Manual retry allowed only from failed
+        return (mStatus == BUGLE_STATUS_OUTGOING_FAILED);
+    }
+
+    public boolean canSendMessage() {
+        // Sending messages must be in yet_to_send or awaiting_retry state
+        return (mStatus == BUGLE_STATUS_OUTGOING_YET_TO_SEND ||
+                mStatus == BUGLE_STATUS_OUTGOING_AWAITING_RETRY);
+    }
+
+    public final boolean getYetToSend() {
+        return (mStatus == BUGLE_STATUS_OUTGOING_YET_TO_SEND);
+    }
+
+    public final boolean getIsMms() {
+        return mProtocol == MessageData.PROTOCOL_MMS
+                || mProtocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION;
+    }
+
+    public static final boolean getIsMmsNotification(final int protocol) {
+        return (protocol == MessageData.PROTOCOL_MMS_PUSH_NOTIFICATION);
+    }
+
+    public final boolean getIsMmsNotification() {
+        return getIsMmsNotification(mProtocol);
+    }
+
+    public static final boolean getIsSms(final int protocol) {
+        return protocol == (MessageData.PROTOCOL_SMS);
+    }
+
+    public final boolean getIsSms() {
+        return getIsSms(mProtocol);
+    }
+
+    public static boolean getIsIncoming(final int status) {
+        return (status >= MessageData.BUGLE_STATUS_FIRST_INCOMING);
+    }
+
+    public boolean getIsIncoming() {
+        return getIsIncoming(mStatus);
+    }
+
+    public long getRetryStartTimestamp() {
+        return mRetryStartTimestamp;
+    }
+
+    public final String getMessageText() {
+        final String separator = System.getProperty("line.separator");
+        final StringBuilder text = new StringBuilder();
+        for (final MessagePartData part : mParts) {
+            if (!part.isAttachment() && !TextUtils.isEmpty(part.getText())) {
+                if (text.length() > 0) {
+                    text.append(separator);
+                }
+                text.append(part.getText());
+            }
+        }
+        return text.toString();
+    }
+
+    /**
+     * Takes all captions from attachments and adds them as a prefix to the first text part or
+     * appends a text part
+     */
+    public final void consolidateText() {
+        final String separator = System.getProperty("line.separator");
+        final StringBuilder captionText = new StringBuilder();
+        MessagePartData firstTextPart = null;
+        int firstTextPartIndex = -1;
+        for (int i = 0; i < mParts.size(); i++) {
+            final MessagePartData part = mParts.get(i);
+            if (firstTextPart == null && !part.isAttachment()) {
+                firstTextPart = part;
+                firstTextPartIndex = i;
+            }
+            if (part.isAttachment() && !TextUtils.isEmpty(part.getText())) {
+                if (captionText.length() > 0) {
+                    captionText.append(separator);
+                }
+                captionText.append(part.getText());
+            }
+        }
+
+        if (captionText.length() == 0) {
+            // Nothing to consolidate
+            return;
+        }
+
+        if (firstTextPart == null) {
+            addPart(MessagePartData.createTextMessagePart(captionText.toString()));
+        } else {
+            final String partText = firstTextPart.getText();
+            if (partText.length() > 0) {
+                captionText.append(separator);
+                captionText.append(partText);
+            }
+            mParts.set(firstTextPartIndex,
+                    MessagePartData.createTextMessagePart(captionText.toString()));
+        }
+    }
+
+    public final MessagePartData getFirstAttachment() {
+        for (final MessagePartData part : mParts) {
+            if (part.isAttachment()) {
+                return part;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Updates the messageId for this message.
+     * Can be used to reset the messageId prior to persisting (which will assign a new messageId)
+     *  or can be called on a message that does not yet have a valid messageId to set it.
+     */
+    public void updateMessageId(final String messageId) {
+        Assert.isTrue(TextUtils.isEmpty(messageId) || TextUtils.isEmpty(mMessageId));
+        mMessageId = messageId;
+
+        // TODO : This should probably also call updateMessageId on the message parts. We
+        // may also want to make messages effectively immutable once they have a valid message id.
+    }
+
+    public final void updateSendingMessage(final String conversationId, final Uri messageUri,
+            final long timestamp) {
+        mConversationId = conversationId;
+        mSmsMessageUri = messageUri;
+        mRead = true;
+        mSeen = true;
+        mReceivedTimestamp = timestamp;
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_YET_TO_SEND;
+        mRetryStartTimestamp = timestamp;
+    }
+
+    public final void markMessageManualResend(final long timestamp) {
+        // Manual send updates timestamp and transitions back to initial sending status.
+        mReceivedTimestamp = timestamp;
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_SENDING;
+    }
+
+    public final void markMessageSending(final long timestamp) {
+        // Initial send
+        mStatus = BUGLE_STATUS_OUTGOING_SENDING;
+        mSentTimestamp = timestamp;
+    }
+
+    public final void markMessageResending(final long timestamp) {
+        // Auto resend of message
+        mStatus = BUGLE_STATUS_OUTGOING_RESENDING;
+        mSentTimestamp = timestamp;
+    }
+
+    public final void markMessageSent(final long timestamp) {
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_COMPLETE;
+    }
+
+    public final void markMessageFailed(final long timestamp) {
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_FAILED;
+    }
+
+    public final void markMessageFailedEmergencyNumber(final long timestamp) {
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER;
+    }
+
+    public final void markMessageNotSent(final long timestamp) {
+        mSentTimestamp = timestamp;
+        mStatus = BUGLE_STATUS_OUTGOING_AWAITING_RETRY;
+    }
+
+    public final void updateSizesForImageParts() {
+        for (final MessagePartData part : getParts()) {
+            part.decodeAndSaveSizeIfImage(false /* saveToStorage */);
+        }
+    }
+
+    public final void setRetryStartTimestamp(final long timestamp) {
+        mRetryStartTimestamp = timestamp;
+    }
+
+    public final void setRawTelephonyStatus(final int rawStatus) {
+        mRawStatus = rawStatus;
+    }
+
+    public boolean hasContent() {
+        return !TextUtils.isEmpty(mMmsSubject) ||
+                getFirstAttachment() != null ||
+                !TextUtils.isEmpty(getMessageText());
+    }
+
+    public final void bindSelfId(final String selfId) {
+        mSelfId = selfId;
+    }
+
+    public final void bindParticipantId(final String participantId) {
+        mParticipantId = participantId;
+    }
+
+    protected MessageData(final Parcel in) {
+        mMessageId = in.readString();
+        mConversationId = in.readString();
+        mParticipantId = in.readString();
+        mSelfId = in.readString();
+        mSentTimestamp = in.readLong();
+        mReceivedTimestamp = in.readLong();
+        mSeen = (in.readInt() != 0);
+        mRead = (in.readInt() != 0);
+        mProtocol = in.readInt();
+        mStatus = in.readInt();
+        final String smsMessageUri = in.readString();
+        mSmsMessageUri = (smsMessageUri == null ? null : Uri.parse(smsMessageUri));
+        mSmsPriority = in.readInt();
+        mSmsMessageSize = in.readLong();
+        mMmsExpiry = in.readLong();
+        mMmsSubject = in.readString();
+        mMmsTransactionId = in.readString();
+        mMmsContentLocation = in.readString();
+        mRawStatus = in.readInt();
+        mRetryStartTimestamp = in.readLong();
+
+        // Read parts
+        mParts = new ArrayList<MessagePartData>();
+        final int partCount = in.readInt();
+        for (int i = 0; i < partCount; i++) {
+            mParts.add((MessagePartData) in.readParcelable(MessagePartData.class.getClassLoader()));
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(final Parcel dest, final int flags) {
+        dest.writeString(mMessageId);
+        dest.writeString(mConversationId);
+        dest.writeString(mParticipantId);
+        dest.writeString(mSelfId);
+        dest.writeLong(mSentTimestamp);
+        dest.writeLong(mReceivedTimestamp);
+        dest.writeInt(mRead ? 1 : 0);
+        dest.writeInt(mSeen ? 1 : 0);
+        dest.writeInt(mProtocol);
+        dest.writeInt(mStatus);
+        final String smsMessageUri = (mSmsMessageUri == null) ? null : mSmsMessageUri.toString();
+        dest.writeString(smsMessageUri);
+        dest.writeInt(mSmsPriority);
+        dest.writeLong(mSmsMessageSize);
+        dest.writeLong(mMmsExpiry);
+        dest.writeString(mMmsSubject);
+        dest.writeString(mMmsTransactionId);
+        dest.writeString(mMmsContentLocation);
+        dest.writeInt(mRawStatus);
+        dest.writeLong(mRetryStartTimestamp);
+
+        // Write parts
+        dest.writeInt(mParts.size());
+        for (final MessagePartData messagePartData : mParts) {
+            dest.writeParcelable(messagePartData, flags);
+        }
+    }
+
+    public static final Parcelable.Creator<MessageData> CREATOR
+            = new Parcelable.Creator<MessageData>() {
+        @Override
+        public MessageData createFromParcel(final Parcel in) {
+            return new MessageData(in);
+        }
+
+        @Override
+        public MessageData[] newArray(final int size) {
+            return new MessageData[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return toString(mMessageId, mParts);
+    }
+
+    public static String toString(String messageId, List<MessagePartData> parts) {
+        StringBuilder sb = new StringBuilder();
+        if (messageId != null) {
+            sb.append(messageId);
+            sb.append(": ");
+        }
+        for (MessagePartData part : parts) {
+            sb.append(part.toString());
+            sb.append(" ");
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/MessagePartData.java b/src/com/android/messaging/datamodel/data/MessagePartData.java
new file mode 100644
index 0000000..ea24876
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/MessagePartData.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteStatement;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.UpdateMessagePartSizeAction;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.GifTranscoder;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UriUtil;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Represents a single message part. Messages consist of one or more parts which may contain
+ * either text or media.
+ */
+public class MessagePartData implements Parcelable {
+    public static final int UNSPECIFIED_SIZE = MessagingContentProvider.UNSPECIFIED_SIZE;
+
+    public static final String[] ACCEPTABLE_GALLERY_MEDIA_TYPES =
+            new String[] {
+                // Acceptable image types
+                ContentType.IMAGE_JPEG, ContentType.IMAGE_JPG, ContentType.IMAGE_PNG,
+                ContentType.IMAGE_GIF, ContentType.IMAGE_WBMP, ContentType.IMAGE_X_MS_BMP,
+                // Acceptable video types
+                ContentType.VIDEO_3GP, ContentType.VIDEO_3GPP, ContentType.VIDEO_3G2,
+                ContentType.VIDEO_H263, ContentType.VIDEO_M4V, ContentType.VIDEO_MP4,
+                ContentType.VIDEO_MPEG, ContentType.VIDEO_MPEG4, ContentType.VIDEO_WEBM,
+                // Acceptable audio types
+                ContentType.AUDIO_MP3, ContentType.AUDIO_MP4, ContentType.AUDIO_MIDI,
+                ContentType.AUDIO_MID, ContentType.AUDIO_AMR, ContentType.AUDIO_X_WAV,
+                ContentType.AUDIO_AAC, ContentType.AUDIO_X_MIDI, ContentType.AUDIO_X_MID,
+                ContentType.AUDIO_X_MP3
+            };
+
+    private static final String[] sProjection = {
+        PartColumns._ID,
+        PartColumns.MESSAGE_ID,
+        PartColumns.TEXT,
+        PartColumns.CONTENT_URI,
+        PartColumns.CONTENT_TYPE,
+        PartColumns.WIDTH,
+        PartColumns.HEIGHT,
+    };
+
+    private static final int INDEX_ID = 0;
+    private static final int INDEX_MESSAGE_ID = 1;
+    private static final int INDEX_TEXT = 2;
+    private static final int INDEX_CONTENT_URI = 3;
+    private static final int INDEX_CONTENT_TYPE = 4;
+    private static final int INDEX_WIDTH = 5;
+    private static final int INDEX_HEIGHT = 6;
+    // This isn't part of the projection
+    private static final int INDEX_CONVERSATION_ID = 7;
+
+    // SQL statement to insert a "complete" message part row (columns based on projection above).
+    private static final String INSERT_MESSAGE_PART_SQL =
+            "INSERT INTO " + DatabaseHelper.PARTS_TABLE + " ( "
+                    + TextUtils.join(",", Arrays.copyOfRange(sProjection, 1, INDEX_CONVERSATION_ID))
+                    + ", " + PartColumns.CONVERSATION_ID
+                    + ") VALUES (?, ?, ?, ?, ?, ?, ?)";
+
+    // Used for stuff that's ignored or arbitrarily compressed.
+    private static final long NO_MINIMUM_SIZE = 0;
+
+    private String mPartId;
+    private String mMessageId;
+    private String mText;
+    private Uri mContentUri;
+    private String mContentType;
+    private int mWidth;
+    private int mHeight;
+    // This kind of part can only be attached once and with no other attachment
+    private boolean mSinglePartOnly;
+
+    /** Transient data: true if destroy was already called */
+    private boolean mDestroyed;
+
+    /**
+     * Create an "empty" message part
+     */
+    protected MessagePartData() {
+        this(null, null, UNSPECIFIED_SIZE, UNSPECIFIED_SIZE);
+    }
+
+    /**
+     * Create a populated text message part
+     */
+    protected MessagePartData(final String messageText) {
+        this(null, messageText, ContentType.TEXT_PLAIN, null, UNSPECIFIED_SIZE, UNSPECIFIED_SIZE,
+                false /*singlePartOnly*/);
+    }
+
+    /**
+     * Create a populated attachment message part
+     */
+    protected MessagePartData(final String contentType, final Uri contentUri,
+            final int width, final int height) {
+        this(null, null, contentType, contentUri, width, height, false /*singlePartOnly*/);
+    }
+
+    /**
+     * Create a populated attachment message part, with additional caption text
+     */
+    protected MessagePartData(final String messageText, final String contentType,
+            final Uri contentUri, final int width, final int height) {
+        this(null, messageText, contentType, contentUri, width, height, false /*singlePartOnly*/);
+    }
+
+    /**
+     * Create a populated attachment message part, with additional caption text, single part only
+     */
+    protected MessagePartData(final String messageText, final String contentType,
+            final Uri contentUri, final int width, final int height, final boolean singlePartOnly) {
+        this(null, messageText, contentType, contentUri, width, height, singlePartOnly);
+    }
+
+    /**
+     * Create a populated message part
+     */
+    private MessagePartData(final String messageId, final String messageText,
+            final String contentType, final Uri contentUri, final int width, final int height,
+            final boolean singlePartOnly) {
+        mMessageId = messageId;
+        mText = messageText;
+        mContentType = contentType;
+        mContentUri = contentUri;
+        mWidth = width;
+        mHeight = height;
+        mSinglePartOnly = singlePartOnly;
+    }
+
+    /**
+     * Create a "text" message part
+     */
+    public static MessagePartData createTextMessagePart(final String messageText) {
+        return new MessagePartData(messageText);
+    }
+
+    /**
+     * Create a "media" message part
+     */
+    public static MessagePartData createMediaMessagePart(final String contentType,
+            final Uri contentUri, final int width, final int height) {
+        return new MessagePartData(contentType, contentUri, width, height);
+    }
+
+    /**
+     * Create a "media" message part with caption
+     */
+    public static MessagePartData createMediaMessagePart(final String caption,
+            final String contentType, final Uri contentUri, final int width, final int height) {
+        return new MessagePartData(null, caption, contentType, contentUri, width, height,
+                false /*singlePartOnly*/
+        );
+    }
+
+    /**
+     * Create an empty "text" message part
+     */
+    public static MessagePartData createEmptyMessagePart() {
+        return new MessagePartData("");
+    }
+
+    /**
+     * Creates a new message part reading from the cursor
+     */
+    public static MessagePartData createFromCursor(final Cursor cursor) {
+        final MessagePartData part = new MessagePartData();
+        part.bind(cursor);
+        return part;
+    }
+
+    public static String[] getProjection() {
+        return sProjection;
+    }
+
+    /**
+     * Updates the part id.
+     * Can be used to reset the partId just prior to persisting (which will assign a new partId)
+     *  or can be called on a part that does not yet have a valid part id to set it.
+     */
+    public void updatePartId(final String partId) {
+        Assert.isTrue(TextUtils.isEmpty(partId) || TextUtils.isEmpty(mPartId));
+        mPartId = partId;
+    }
+
+    /**
+     * Updates the messageId for the part.
+     * Can be used to reset the messageId prior to persisting (which will assign a new messageId)
+     *  or can be called on a part that does not yet have a valid messageId to set it.
+     */
+    public void updateMessageId(final String messageId) {
+        Assert.isTrue(TextUtils.isEmpty(messageId) || TextUtils.isEmpty(mMessageId));
+        mMessageId = messageId;
+    }
+
+    protected static String getMessageId(final Cursor cursor) {
+        return cursor.getString(INDEX_MESSAGE_ID);
+    }
+
+    protected void bind(final Cursor cursor) {
+        mPartId = cursor.getString(INDEX_ID);
+        mMessageId = cursor.getString(INDEX_MESSAGE_ID);
+        mText = cursor.getString(INDEX_TEXT);
+        mContentUri = UriUtil.uriFromString(cursor.getString(INDEX_CONTENT_URI));
+        mContentType = cursor.getString(INDEX_CONTENT_TYPE);
+        mWidth = cursor.getInt(INDEX_WIDTH);
+        mHeight = cursor.getInt(INDEX_HEIGHT);
+    }
+
+    public final void populate(final ContentValues values) {
+        // Must have a valid messageId on a part
+        Assert.isTrue(!TextUtils.isEmpty(mMessageId));
+        values.put(PartColumns.MESSAGE_ID, mMessageId);
+        values.put(PartColumns.TEXT, mText);
+        values.put(PartColumns.CONTENT_URI, UriUtil.stringFromUri(mContentUri));
+        values.put(PartColumns.CONTENT_TYPE, mContentType);
+        if (mWidth != UNSPECIFIED_SIZE) {
+            values.put(PartColumns.WIDTH, mWidth);
+        }
+        if (mHeight != UNSPECIFIED_SIZE) {
+            values.put(PartColumns.HEIGHT, mHeight);
+        }
+    }
+
+    /**
+     * Note this is not thread safe so callers need to make sure they own the wrapper + statements
+     * while they call this and use the returned value.
+     */
+    public SQLiteStatement getInsertStatement(final DatabaseWrapper db,
+                                              final String conversationId) {
+        final SQLiteStatement insert = db.getStatementInTransaction(
+                DatabaseWrapper.INDEX_INSERT_MESSAGE_PART, INSERT_MESSAGE_PART_SQL);
+        insert.clearBindings();
+        insert.bindString(INDEX_MESSAGE_ID, mMessageId);
+        if (mText != null) {
+            insert.bindString(INDEX_TEXT, mText);
+        }
+        if (mContentUri != null) {
+            insert.bindString(INDEX_CONTENT_URI, mContentUri.toString());
+        }
+        if (mContentType != null) {
+            insert.bindString(INDEX_CONTENT_TYPE, mContentType);
+        }
+        insert.bindLong(INDEX_WIDTH, mWidth);
+        insert.bindLong(INDEX_HEIGHT, mHeight);
+        insert.bindString(INDEX_CONVERSATION_ID, conversationId);
+        return insert;
+    }
+
+    public final String getPartId() {
+        return mPartId;
+    }
+
+    public final String getMessageId() {
+        return mMessageId;
+    }
+
+    public final String getText() {
+        return mText;
+    }
+
+    public final Uri getContentUri() {
+        return mContentUri;
+    }
+
+    public boolean isAttachment() {
+        return mContentUri != null;
+    }
+
+    public boolean isText() {
+        return ContentType.isTextType(mContentType);
+    }
+
+    public boolean isImage() {
+        return ContentType.isImageType(mContentType);
+    }
+
+    public boolean isMedia() {
+        return ContentType.isMediaType(mContentType);
+    }
+
+    public boolean isVCard() {
+        return ContentType.isVCardType(mContentType);
+    }
+
+    public boolean isAudio() {
+        return ContentType.isAudioType(mContentType);
+    }
+
+    public boolean isVideo() {
+        return ContentType.isVideoType(mContentType);
+    }
+
+    public final String getContentType() {
+        return mContentType;
+    }
+
+    public final int getWidth() {
+        return mWidth;
+    }
+
+    public final int getHeight() {
+        return mHeight;
+    }
+
+    public static boolean isSupportedMediaType(final String contentType) {
+        return ContentType.isVCardType(contentType)
+                || Arrays.asList(ACCEPTABLE_GALLERY_MEDIA_TYPES).contains(contentType);
+    }
+
+    /**
+    *
+    * @return true if this part can only exist by itself, with no other attachments
+    */
+    public boolean getSinglePartOnly() {
+        return mSinglePartOnly;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    protected MessagePartData(final Parcel in) {
+        mMessageId = in.readString();
+        mText = in.readString();
+        mContentUri = UriUtil.uriFromString(in.readString());
+        mContentType = in.readString();
+        mWidth = in.readInt();
+        mHeight = in.readInt();
+    }
+
+    @Override
+    public void writeToParcel(final Parcel dest, final int flags) {
+        Assert.isTrue(!mDestroyed);
+        dest.writeString(mMessageId);
+        dest.writeString(mText);
+        dest.writeString(UriUtil.stringFromUri(mContentUri));
+        dest.writeString(mContentType);
+        dest.writeInt(mWidth);
+        dest.writeInt(mHeight);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof MessagePartData)) {
+          return false;
+        }
+
+        MessagePartData lhs = (MessagePartData) o;
+        return mWidth == lhs.mWidth && mHeight == lhs.mHeight &&
+                TextUtils.equals(mMessageId, lhs.mMessageId) &&
+                TextUtils.equals(mText, lhs.mText) &&
+                TextUtils.equals(mContentType, lhs.mContentType) &&
+                (mContentUri == null ? lhs.mContentUri == null
+                                     : mContentUri.equals(lhs.mContentUri));
+    }
+
+    @Override public int hashCode() {
+        int result = 17;
+        result = 31 * result + mWidth;
+        result = 31 * result + mHeight;
+        result = 31 * result + (mMessageId == null ? 0 : mMessageId.hashCode());
+        result = 31 * result + (mText == null ? 0 : mText.hashCode());
+        result = 31 * result + (mContentType == null ? 0 : mContentType.hashCode());
+        result = 31 * result + (mContentUri == null ? 0 : mContentUri.hashCode());
+        return result;
+      }
+
+    public static final Parcelable.Creator<MessagePartData> CREATOR
+            = new Parcelable.Creator<MessagePartData>() {
+        @Override
+        public MessagePartData createFromParcel(final Parcel in) {
+            return new MessagePartData(in);
+        }
+
+        @Override
+        public MessagePartData[] newArray(final int size) {
+            return new MessagePartData[size];
+        }
+    };
+
+    protected Uri shouldDestroy() {
+        // We should never double-destroy.
+        Assert.isTrue(!mDestroyed);
+        mDestroyed = true;
+        Uri contentUri = mContentUri;
+        mContentUri = null;
+        mContentType = null;
+        // Only destroy the image if it's staged in our scratch space.
+        if (!MediaScratchFileProvider.isMediaScratchSpaceUri(contentUri)) {
+            contentUri = null;
+        }
+        return contentUri;
+    }
+
+    /**
+     * If application owns content associated with this part delete it (on background thread)
+     */
+    public void destroyAsync() {
+        final Uri contentUri = shouldDestroy();
+        if (contentUri != null) {
+            SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                @Override
+                public void run() {
+                    Factory.get().getApplicationContext().getContentResolver().delete(
+                            contentUri, null, null);
+                }
+            });
+        }
+    }
+
+    /**
+     * If application owns content associated with this part delete it
+     */
+    public void destroySync() {
+        final Uri contentUri = shouldDestroy();
+        if (contentUri != null) {
+            Factory.get().getApplicationContext().getContentResolver().delete(
+                    contentUri, null, null);
+        }
+    }
+
+    /**
+     * If this is an image part, decode the image header and potentially save the size to the db.
+     */
+    public void decodeAndSaveSizeIfImage(final boolean saveToStorage) {
+        if (isImage()) {
+            final Rect imageSize = ImageUtils.decodeImageBounds(
+                    Factory.get().getApplicationContext(), mContentUri);
+            if (imageSize.width() != ImageRequest.UNSPECIFIED_SIZE &&
+                    imageSize.height() != ImageRequest.UNSPECIFIED_SIZE) {
+                mWidth = imageSize.width();
+                mHeight = imageSize.height();
+                if (saveToStorage) {
+                    UpdateMessagePartSizeAction.updateSize(mPartId, mWidth, mHeight);
+                }
+            }
+        }
+    }
+
+    /**
+     * Computes the minimum size that this MessagePartData could be compressed/downsampled/encoded
+     * before sending to meet the maximum message size imposed by the carriers. This is used to
+     * determine right before sending a message whether a message could possibly be sent. If not
+     * then the user is given a chance to unselect some/all of the attachments.
+     *
+     * TODO: computing the minimum size could be expensive. Should we cache the
+     * computed value in db to be retrieved later?
+     *
+     * @return the carrier-independent minimum size, in bytes.
+     */
+    @DoesNotRunOnMainThread
+    public long getMinimumSizeInBytesForSending() {
+        Assert.isNotMainThread();
+        if (!isAttachment()) {
+            // No limit is imposed on non-attachment part (i.e. plain text), so treat it as zero.
+            return NO_MINIMUM_SIZE;
+        } else if (isImage()) {
+            // GIFs are resized by the native transcoder (exposed by GifTranscoder).
+            if (ImageUtils.isGif(mContentType, mContentUri)) {
+                final long originalImageSize = UriUtil.getContentSize(mContentUri);
+                // Wish we could save the size here, but we don't have a part id yet
+                decodeAndSaveSizeIfImage(false /* saveToStorage */);
+                return GifTranscoder.canBeTranscoded(mWidth, mHeight) ?
+                        GifTranscoder.estimateFileSizeAfterTranscode(originalImageSize)
+                        : originalImageSize;
+            }
+            // Other images should be arbitrarily resized by ImageResizer before sending.
+            return MmsUtils.MIN_IMAGE_BYTE_SIZE;
+        } else if (isMedia()) {
+            // We can't compress attachments except images.
+            return UriUtil.getContentSize(mContentUri);
+        } else {
+            // This is some unknown media type that we don't know how to handle. Log an error
+            // and try sending it anyway.
+            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Unknown attachment type " + getContentType());
+            return NO_MINIMUM_SIZE;
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (isText()) {
+            return LogUtil.sanitizePII(getText());
+        } else {
+            return getContentType() + " (" + getContentUri() + ")";
+        }
+    }
+
+    /**
+     *
+     * @return true if this part can only exist by itself, with no other attachments
+     */
+    public boolean isSinglePartOnly() {
+        return mSinglePartOnly;
+    }
+
+    public void setSinglePartOnly(final boolean isSinglePartOnly) {
+        mSinglePartOnly = isSinglePartOnly;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/ParticipantData.java b/src/com/android/messaging/datamodel/data/ParticipantData.java
new file mode 100644
index 0000000..95c74e2
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ParticipantData.java
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.content.ContentValues;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.SubscriptionInfo;
+import android.text.TextUtils;
+
+import androidx.appcompat.mms.MmsManager;
+import androidx.collection.ArrayMap;
+
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.TextUtil;
+
+/**
+ * A class that encapsulates all of the data for a specific participant in a conversation.
+ */
+public class ParticipantData implements Parcelable {
+
+    private static final ArrayMap<Integer, String> sSubIdtoParticipantIdCache =
+            new ArrayMap<Integer, String>();
+
+    // We always use -1 as default/invalid sub id although system may give us anything negative
+    public static final int DEFAULT_SELF_SUB_ID = MmsManager.DEFAULT_SUB_ID;
+
+    // This needs to be something apart from valid or DEFAULT_SELF_SUB_ID
+    public static final int OTHER_THAN_SELF_SUB_ID = DEFAULT_SELF_SUB_ID - 1;
+
+    // Active slot ids are non-negative. Using -1 to designate to inactive self participants.
+    public static final int INVALID_SLOT_ID = -1;
+
+    // TODO: may make sense to move this to common place?
+    public static final long PARTICIPANT_CONTACT_ID_NOT_RESOLVED = -1;
+    public static final long PARTICIPANT_CONTACT_ID_NOT_FOUND = -2;
+
+    public static class ParticipantsQuery {
+        public static final String[] PROJECTION = new String[] {
+            ParticipantColumns._ID,
+            ParticipantColumns.SUB_ID,
+            ParticipantColumns.SIM_SLOT_ID,
+            ParticipantColumns.NORMALIZED_DESTINATION,
+            ParticipantColumns.SEND_DESTINATION,
+            ParticipantColumns.DISPLAY_DESTINATION,
+            ParticipantColumns.FULL_NAME,
+            ParticipantColumns.FIRST_NAME,
+            ParticipantColumns.PROFILE_PHOTO_URI,
+            ParticipantColumns.CONTACT_ID,
+            ParticipantColumns.LOOKUP_KEY,
+            ParticipantColumns.BLOCKED,
+            ParticipantColumns.SUBSCRIPTION_COLOR,
+            ParticipantColumns.SUBSCRIPTION_NAME,
+            ParticipantColumns.CONTACT_DESTINATION,
+        };
+
+        public static final int INDEX_ID                        = 0;
+        public static final int INDEX_SUB_ID                    = 1;
+        public static final int INDEX_SIM_SLOT_ID               = 2;
+        public static final int INDEX_NORMALIZED_DESTINATION    = 3;
+        public static final int INDEX_SEND_DESTINATION          = 4;
+        public static final int INDEX_DISPLAY_DESTINATION       = 5;
+        public static final int INDEX_FULL_NAME                 = 6;
+        public static final int INDEX_FIRST_NAME                = 7;
+        public static final int INDEX_PROFILE_PHOTO_URI         = 8;
+        public static final int INDEX_CONTACT_ID                = 9;
+        public static final int INDEX_LOOKUP_KEY                = 10;
+        public static final int INDEX_BLOCKED                   = 11;
+        public static final int INDEX_SUBSCRIPTION_COLOR        = 12;
+        public static final int INDEX_SUBSCRIPTION_NAME         = 13;
+        public static final int INDEX_CONTACT_DESTINATION       = 14;
+    }
+
+    /**
+     * @return The MMS unknown sender participant entity
+     */
+    public static String getUnknownSenderDestination() {
+        // This is a hard coded string rather than a localized one because we don't want it to
+        // change when you change locale.
+        return "\u02BCUNKNOWN_SENDER!\u02BC";
+    }
+
+    private String mParticipantId;
+    private int mSubId;
+    private int mSlotId;
+    private String mNormalizedDestination;
+    private String mSendDestination;
+    private String mDisplayDestination;
+    private String mContactDestination;
+    private String mFullName;
+    private String mFirstName;
+    private String mProfilePhotoUri;
+    private long mContactId;
+    private String mLookupKey;
+    private int mSubscriptionColor;
+    private String mSubscriptionName;
+    private boolean mIsEmailAddress;
+    private boolean mBlocked;
+
+    // Don't call constructor directly
+    private ParticipantData() {
+    }
+
+    public static ParticipantData getFromCursor(final Cursor cursor) {
+        final ParticipantData pd = new ParticipantData();
+        pd.mParticipantId = cursor.getString(ParticipantsQuery.INDEX_ID);
+        pd.mSubId = cursor.getInt(ParticipantsQuery.INDEX_SUB_ID);
+        pd.mSlotId = cursor.getInt(ParticipantsQuery.INDEX_SIM_SLOT_ID);
+        pd.mNormalizedDestination = cursor.getString(
+                ParticipantsQuery.INDEX_NORMALIZED_DESTINATION);
+        pd.mSendDestination = cursor.getString(ParticipantsQuery.INDEX_SEND_DESTINATION);
+        pd.mDisplayDestination = cursor.getString(ParticipantsQuery.INDEX_DISPLAY_DESTINATION);
+        pd.mContactDestination = cursor.getString(ParticipantsQuery.INDEX_CONTACT_DESTINATION);
+        pd.mFullName = cursor.getString(ParticipantsQuery.INDEX_FULL_NAME);
+        pd.mFirstName = cursor.getString(ParticipantsQuery.INDEX_FIRST_NAME);
+        pd.mProfilePhotoUri = cursor.getString(ParticipantsQuery.INDEX_PROFILE_PHOTO_URI);
+        pd.mContactId = cursor.getLong(ParticipantsQuery.INDEX_CONTACT_ID);
+        pd.mLookupKey = cursor.getString(ParticipantsQuery.INDEX_LOOKUP_KEY);
+        pd.mIsEmailAddress = MmsSmsUtils.isEmailAddress(pd.mSendDestination);
+        pd.mBlocked = cursor.getInt(ParticipantsQuery.INDEX_BLOCKED) != 0;
+        pd.mSubscriptionColor = cursor.getInt(ParticipantsQuery.INDEX_SUBSCRIPTION_COLOR);
+        pd.mSubscriptionName = cursor.getString(ParticipantsQuery.INDEX_SUBSCRIPTION_NAME);
+        pd.maybeSetupUnknownSender();
+        return pd;
+    }
+
+    public static ParticipantData getFromId(final DatabaseWrapper dbWrapper,
+            final String participantId) {
+        Cursor cursor = null;
+        try {
+            cursor = dbWrapper.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantsQuery.PROJECTION,
+                    ParticipantColumns._ID + " =?",
+                    new String[] { participantId }, null, null, null);
+
+            if (cursor.moveToFirst()) {
+                return ParticipantData.getFromCursor(cursor);
+            } else {
+                return null;
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    public static ParticipantData getFromRecipientEntry(final RecipientEntry recipientEntry) {
+        final ParticipantData pd = new ParticipantData();
+        pd.mParticipantId = null;
+        pd.mSubId = OTHER_THAN_SELF_SUB_ID;
+        pd.mSlotId = INVALID_SLOT_ID;
+        pd.mSendDestination = TextUtil.replaceUnicodeDigits(recipientEntry.getDestination());
+        pd.mIsEmailAddress = MmsSmsUtils.isEmailAddress(pd.mSendDestination);
+        pd.mNormalizedDestination = pd.mIsEmailAddress ?
+                pd.mSendDestination :
+                PhoneUtils.getDefault().getCanonicalBySystemLocale(pd.mSendDestination);
+        pd.mDisplayDestination = pd.mIsEmailAddress ?
+                pd.mNormalizedDestination :
+                PhoneUtils.getDefault().formatForDisplay(pd.mNormalizedDestination);
+        pd.mFullName = recipientEntry.getDisplayName();
+        pd.mFirstName = null;
+        pd.mProfilePhotoUri = (recipientEntry.getPhotoThumbnailUri() == null) ? null :
+                recipientEntry.getPhotoThumbnailUri().toString();
+        pd.mContactId = recipientEntry.getContactId();
+        if (pd.mContactId < 0) {
+            // ParticipantData only supports real contact ids (>=0) based on faith that the contacts
+            // provider will continue to only use non-negative ids.  The UI uses contactId < 0 for
+            // special handling. We convert those to 'not resolved'
+            pd.mContactId = PARTICIPANT_CONTACT_ID_NOT_RESOLVED;
+        }
+        pd.mLookupKey = recipientEntry.getLookupKey();
+        pd.mBlocked = false;
+        pd.mSubscriptionColor = Color.TRANSPARENT;
+        pd.mSubscriptionName = null;
+        pd.maybeSetupUnknownSender();
+        return pd;
+    }
+
+    // Shared code for getFromRawPhoneBySystemLocale and getFromRawPhoneBySimLocale
+    private static ParticipantData getFromRawPhone(final String phoneNumber) {
+        Assert.isTrue(phoneNumber != null);
+        final ParticipantData pd = new ParticipantData();
+        pd.mParticipantId = null;
+        pd.mSubId = OTHER_THAN_SELF_SUB_ID;
+        pd.mSlotId = INVALID_SLOT_ID;
+        pd.mSendDestination = TextUtil.replaceUnicodeDigits(phoneNumber);
+        pd.mIsEmailAddress = MmsSmsUtils.isEmailAddress(pd.mSendDestination);
+        pd.mFullName = null;
+        pd.mFirstName = null;
+        pd.mProfilePhotoUri = null;
+        pd.mContactId = PARTICIPANT_CONTACT_ID_NOT_RESOLVED;
+        pd.mLookupKey = null;
+        pd.mBlocked = false;
+        pd.mSubscriptionColor = Color.TRANSPARENT;
+        pd.mSubscriptionName = null;
+        return pd;
+    }
+
+    /**
+     * Get an instance from a raw phone number and using system locale to normalize it.
+     *
+     * Use this when creating a participant that is for displaying UI and not associated
+     * with a specific SIM. For example, when creating a conversation using user entered
+     * phone number.
+     *
+     * @param phoneNumber The raw phone number
+     * @return instance
+     */
+    public static ParticipantData getFromRawPhoneBySystemLocale(final String phoneNumber) {
+        final ParticipantData pd = getFromRawPhone(phoneNumber);
+        pd.mNormalizedDestination = pd.mIsEmailAddress ?
+                pd.mSendDestination :
+                PhoneUtils.getDefault().getCanonicalBySystemLocale(pd.mSendDestination);
+        pd.mDisplayDestination = pd.mIsEmailAddress ?
+                pd.mNormalizedDestination :
+                PhoneUtils.getDefault().formatForDisplay(pd.mNormalizedDestination);
+        pd.maybeSetupUnknownSender();
+        return pd;
+    }
+
+    /**
+     * Get an instance from a raw phone number and using SIM or system locale to normalize it.
+     *
+     * Use this when creating a participant that is associated with a specific SIM. For example,
+     * the sender of a received message or the recipient of a sending message that is already
+     * targeted at a specific SIM.
+     *
+     * @param phoneNumber The raw phone number
+     * @return instance
+     */
+    public static ParticipantData getFromRawPhoneBySimLocale(
+            final String phoneNumber, final int subId) {
+        final ParticipantData pd = getFromRawPhone(phoneNumber);
+        pd.mNormalizedDestination = pd.mIsEmailAddress ?
+                pd.mSendDestination :
+                PhoneUtils.get(subId).getCanonicalBySimLocale(pd.mSendDestination);
+        pd.mDisplayDestination = pd.mIsEmailAddress ?
+                pd.mNormalizedDestination :
+                PhoneUtils.getDefault().formatForDisplay(pd.mNormalizedDestination);
+        pd.maybeSetupUnknownSender();
+        return pd;
+    }
+
+    public static ParticipantData getSelfParticipant(final int subId) {
+        Assert.isTrue(subId != OTHER_THAN_SELF_SUB_ID);
+        final ParticipantData pd = new ParticipantData();
+        pd.mParticipantId = null;
+        pd.mSubId = subId;
+        pd.mSlotId = INVALID_SLOT_ID;
+        pd.mIsEmailAddress = false;
+        pd.mSendDestination = null;
+        pd.mNormalizedDestination = null;
+        pd.mDisplayDestination = null;
+        pd.mFullName = null;
+        pd.mFirstName = null;
+        pd.mProfilePhotoUri = null;
+        pd.mContactId = PARTICIPANT_CONTACT_ID_NOT_RESOLVED;
+        pd.mLookupKey = null;
+        pd.mBlocked = false;
+        pd.mSubscriptionColor = Color.TRANSPARENT;
+        pd.mSubscriptionName = null;
+        return pd;
+    }
+
+    public static String getParticipantId(final DatabaseWrapper db, final int subId) {
+        String id;
+        synchronized (sSubIdtoParticipantIdCache) {
+            id = sSubIdtoParticipantIdCache.get(subId);
+        }
+
+        if (id != null) {
+            return id;
+        }
+
+        try (final Cursor cursor =
+                    db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                            new String[] {ParticipantColumns._ID},
+                            ParticipantColumns.SUB_ID + " =?",
+                            new String[] {Integer.toString(subId)}, null, null, null)) {
+
+            if (cursor.moveToFirst()) {
+                // We found an existing participant in the database
+                id = cursor.getString(0);
+                synchronized (sSubIdtoParticipantIdCache) {
+                    // Add it to the cache for next time
+                    sSubIdtoParticipantIdCache.put(subId, id);
+                }
+            }
+        }
+        return id;
+    }
+
+    private void maybeSetupUnknownSender() {
+        if (isUnknownSender()) {
+            // Because your locale may change, we setup the display string for the unknown sender
+            // on the fly rather than relying on the version in the database.
+            final Resources resources = Factory.get().getApplicationContext().getResources();
+            mDisplayDestination = resources.getString(R.string.unknown_sender);
+            mFullName = mDisplayDestination;
+        }
+    }
+
+    public String getNormalizedDestination() {
+        return mNormalizedDestination;
+    }
+
+    public String getSendDestination() {
+        return mSendDestination;
+    }
+
+    public String getDisplayDestination() {
+        return mDisplayDestination;
+    }
+
+    public String getContactDestination() {
+        return mContactDestination;
+    }
+
+    public String getFullName() {
+        return mFullName;
+    }
+
+    public String getFirstName() {
+        return mFirstName;
+    }
+
+    public String getDisplayName(final boolean preferFullName) {
+        if (preferFullName) {
+            // Prefer full name over first name
+            if (!TextUtils.isEmpty(mFullName)) {
+                return mFullName;
+            }
+            if (!TextUtils.isEmpty(mFirstName)) {
+                return mFirstName;
+            }
+        } else {
+            // Prefer first name over full name
+            if (!TextUtils.isEmpty(mFirstName)) {
+                return mFirstName;
+            }
+            if (!TextUtils.isEmpty(mFullName)) {
+                return mFullName;
+            }
+        }
+
+        // Fallback to the display destination
+        if (!TextUtils.isEmpty(mDisplayDestination)) {
+            return mDisplayDestination;
+        }
+
+        return Factory.get().getApplicationContext().getResources().getString(
+                R.string.unknown_sender);
+    }
+
+    public String getProfilePhotoUri() {
+        return mProfilePhotoUri;
+    }
+
+    public long getContactId() {
+        return mContactId;
+    }
+
+    public String getLookupKey() {
+        return mLookupKey;
+    }
+
+    public boolean updatePhoneNumberForSelfIfChanged() {
+        final String phoneNumber =
+                PhoneUtils.get(mSubId).getCanonicalForSelf(true/*allowOverride*/);
+        boolean changed = false;
+        if (isSelf() && !TextUtils.equals(phoneNumber, mNormalizedDestination)) {
+            mNormalizedDestination = phoneNumber;
+            mSendDestination = phoneNumber;
+            mDisplayDestination = mIsEmailAddress ?
+                    phoneNumber :
+                    PhoneUtils.getDefault().formatForDisplay(phoneNumber);
+            changed = true;
+        }
+        return changed;
+    }
+
+    public boolean updateSubscriptionInfoForSelfIfChanged(final SubscriptionInfo subscriptionInfo) {
+        boolean changed = false;
+        if (isSelf()) {
+            if (subscriptionInfo == null) {
+                // The subscription is inactive. Check if the participant is still active.
+                if (isActiveSubscription()) {
+                    mSlotId = INVALID_SLOT_ID;
+                    mSubscriptionColor = Color.TRANSPARENT;
+                    mSubscriptionName = "";
+                    changed = true;
+                }
+            } else {
+                final int slotId = subscriptionInfo.getSimSlotIndex();
+                final int color = subscriptionInfo.getIconTint();
+                final CharSequence name = subscriptionInfo.getDisplayName();
+                if (mSlotId != slotId || mSubscriptionColor != color || mSubscriptionName != name) {
+                    mSlotId = slotId;
+                    mSubscriptionColor = color;
+                    mSubscriptionName = name.toString();
+                    changed = true;
+                }
+            }
+        }
+        return changed;
+    }
+
+    public void setFullName(final String fullName) {
+        mFullName = fullName;
+    }
+
+    public void setFirstName(final String firstName) {
+        mFirstName = firstName;
+    }
+
+    public void setProfilePhotoUri(final String profilePhotoUri) {
+        mProfilePhotoUri = profilePhotoUri;
+    }
+
+    public void setContactId(final long contactId) {
+        mContactId = contactId;
+    }
+
+    public void setLookupKey(final String lookupKey) {
+        mLookupKey = lookupKey;
+    }
+
+    public void setSendDestination(final String destination) {
+        mSendDestination = destination;
+    }
+
+    public void setContactDestination(final String destination) {
+        mContactDestination = destination;
+    }
+
+    public int getSubId() {
+        return mSubId;
+    }
+
+    /**
+     * @return whether this sub is active. Note that {@link ParticipantData#DEFAULT_SELF_SUB_ID} is
+     *         is considered as active if there is any active SIM.
+     */
+    public boolean isActiveSubscription() {
+        return mSlotId != INVALID_SLOT_ID;
+    }
+
+    public boolean isDefaultSelf() {
+        return mSubId == ParticipantData.DEFAULT_SELF_SUB_ID;
+    }
+
+    public int getSlotId() {
+        return mSlotId;
+    }
+
+    /**
+     * Slot IDs in the subscription manager is zero-based, but we want to show it
+     * as 1-based in UI.
+     */
+    public int getDisplaySlotId() {
+        return getSlotId() + 1;
+    }
+
+    public int getSubscriptionColor() {
+        Assert.isTrue(isActiveSubscription());
+        // Force the alpha channel to 0xff to ensure the returned color is solid.
+        return mSubscriptionColor | 0xff000000;
+    }
+
+    public String getSubscriptionName() {
+        Assert.isTrue(isActiveSubscription());
+        return mSubscriptionName;
+    }
+
+    public String getId() {
+        return mParticipantId;
+    }
+
+    public boolean isSelf() {
+        return (mSubId != OTHER_THAN_SELF_SUB_ID);
+    }
+
+    public boolean isEmail() {
+        return mIsEmailAddress;
+    }
+
+    public boolean isContactIdResolved() {
+        return (mContactId != PARTICIPANT_CONTACT_ID_NOT_RESOLVED);
+    }
+
+    public boolean isBlocked() {
+        return mBlocked;
+    }
+
+    public boolean isUnknownSender() {
+        final String unknownSender = ParticipantData.getUnknownSenderDestination();
+        return (TextUtils.equals(mSendDestination, unknownSender));
+    }
+
+    public ContentValues toContentValues() {
+        final ContentValues values = new ContentValues();
+        values.put(ParticipantColumns.SUB_ID, mSubId);
+        values.put(ParticipantColumns.SIM_SLOT_ID, mSlotId);
+        values.put(DatabaseHelper.ParticipantColumns.SEND_DESTINATION, mSendDestination);
+
+        if (!isUnknownSender()) {
+            values.put(DatabaseHelper.ParticipantColumns.DISPLAY_DESTINATION, mDisplayDestination);
+            values.put(DatabaseHelper.ParticipantColumns.NORMALIZED_DESTINATION,
+                    mNormalizedDestination);
+            values.put(ParticipantColumns.FULL_NAME, mFullName);
+            values.put(ParticipantColumns.FIRST_NAME, mFirstName);
+        }
+
+        values.put(ParticipantColumns.PROFILE_PHOTO_URI, mProfilePhotoUri);
+        values.put(ParticipantColumns.CONTACT_ID, mContactId);
+        values.put(ParticipantColumns.LOOKUP_KEY, mLookupKey);
+        values.put(ParticipantColumns.BLOCKED, mBlocked);
+        values.put(ParticipantColumns.SUBSCRIPTION_COLOR, mSubscriptionColor);
+        values.put(ParticipantColumns.SUBSCRIPTION_NAME, mSubscriptionName);
+        return values;
+    }
+
+    public ParticipantData(final Parcel in) {
+        mParticipantId = in.readString();
+        mSubId = in.readInt();
+        mSlotId = in.readInt();
+        mNormalizedDestination = in.readString();
+        mSendDestination = in.readString();
+        mDisplayDestination = in.readString();
+        mFullName = in.readString();
+        mFirstName = in.readString();
+        mProfilePhotoUri = in.readString();
+        mContactId = in.readLong();
+        mLookupKey = in.readString();
+        mIsEmailAddress = in.readInt() != 0;
+        mBlocked = in.readInt() != 0;
+        mSubscriptionColor = in.readInt();
+        mSubscriptionName = in.readString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(final Parcel dest, final int flags) {
+        dest.writeString(mParticipantId);
+        dest.writeInt(mSubId);
+        dest.writeInt(mSlotId);
+        dest.writeString(mNormalizedDestination);
+        dest.writeString(mSendDestination);
+        dest.writeString(mDisplayDestination);
+        dest.writeString(mFullName);
+        dest.writeString(mFirstName);
+        dest.writeString(mProfilePhotoUri);
+        dest.writeLong(mContactId);
+        dest.writeString(mLookupKey);
+        dest.writeInt(mIsEmailAddress ? 1 : 0);
+        dest.writeInt(mBlocked ? 1 : 0);
+        dest.writeInt(mSubscriptionColor);
+        dest.writeString(mSubscriptionName);
+    }
+
+    public static final Parcelable.Creator<ParticipantData> CREATOR
+    = new Parcelable.Creator<ParticipantData>() {
+        @Override
+        public ParticipantData createFromParcel(final Parcel in) {
+            return new ParticipantData(in);
+        }
+
+        @Override
+        public ParticipantData[] newArray(final int size) {
+            return new ParticipantData[size];
+        }
+    };
+}
diff --git a/src/com/android/messaging/datamodel/data/ParticipantListItemData.java b/src/com/android/messaging/datamodel/data/ParticipantListItemData.java
new file mode 100644
index 0000000..f6c9b5f
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/ParticipantListItemData.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.action.BugleActionToasts;
+import com.android.messaging.datamodel.action.UpdateDestinationBlockedAction;
+import com.android.messaging.util.AvatarUriUtil;
+
+/**
+ * Helps visualize a ParticipantData in a PersonItemView
+ */
+public class ParticipantListItemData extends PersonItemData {
+    private final Uri mAvatarUri;
+    private final String mDisplayName;
+    private final String mDetails;
+    private final long mContactId;
+    private final String mLookupKey;
+    private final String mNormalizedDestination;
+
+    /**
+     * Constructor. Takes necessary info from the incoming ParticipantData.
+     */
+    public ParticipantListItemData(final ParticipantData participant) {
+        mAvatarUri = AvatarUriUtil.createAvatarUri(participant);
+        mContactId = participant.getContactId();
+        mLookupKey = participant.getLookupKey();
+        mNormalizedDestination = participant.getNormalizedDestination();
+        if (TextUtils.isEmpty(participant.getFullName())) {
+            mDisplayName = participant.getSendDestination();
+            mDetails = null;
+        } else {
+            mDisplayName = participant.getFullName();
+            mDetails = (participant.isUnknownSender()) ? null : participant.getSendDestination();
+        }
+    }
+
+    @Override
+    public Uri getAvatarUri() {
+        return mAvatarUri;
+    }
+
+    @Override
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    @Override
+    public String getDetails() {
+        return mDetails;
+    }
+
+    @Override
+    public Intent getClickIntent() {
+        return null;
+    }
+
+    @Override
+    public long getContactId() {
+        return mContactId;
+    }
+
+    @Override
+    public String getLookupKey() {
+        return mLookupKey;
+    }
+
+    @Override
+    public String getNormalizedDestination() {
+        return mNormalizedDestination;
+    }
+
+    public void unblock(final Context context) {
+        UpdateDestinationBlockedAction.updateDestinationBlocked(
+                mNormalizedDestination, false, null,
+                BugleActionToasts.makeUpdateDestinationBlockedActionListener(context));
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/PendingAttachmentData.java b/src/com/android/messaging/datamodel/data/PendingAttachmentData.java
new file mode 100644
index 0000000..a5b5460
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/PendingAttachmentData.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import androidx.annotation.NonNull;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * Represents a "pending" message part that acts as a placeholder for the actual attachment being
+ * loaded. It handles the task to load and persist the attachment from a Uri to local scratch
+ * folder. This item is not persisted to the database.
+ */
+public class PendingAttachmentData extends MessagePartData {
+    /** The pending state. This is the initial state where we haven't started loading yet */
+    public static final int STATE_PENDING = 0;
+
+    /** The state for when we are currently loading the attachment to the scratch space */
+    public static final int STATE_LOADING = 1;
+
+    /** The attachment has been successfully loaded and no longer pending */
+    public static final int STATE_LOADED = 2;
+
+    /** The attachment failed to load */
+    public static final int STATE_FAILED = 3;
+
+    private static final int LOAD_MEDIA_TIME_LIMIT_MILLIS = 60 * 1000;  // 60s
+
+    /** The current state of the pending attachment. Refer to the STATE_* states above */
+    private int mCurrentState;
+
+    /**
+     * Create a new instance of PendingAttachmentData with an output Uri.
+     * @param sourceUri the source Uri of the attachment. The Uri maybe temporary or remote,
+     * so we need to persist it to local storage.
+     */
+    protected PendingAttachmentData(final String caption, final String contentType,
+            @NonNull final Uri sourceUri, final int width, final int height,
+            final boolean onlySingleAttachment) {
+        super(caption, contentType, sourceUri, width, height, onlySingleAttachment);
+        mCurrentState = STATE_PENDING;
+    }
+
+    /**
+     * Creates a pending attachment data that is able to load from the given source uri and
+     * persist the media resource locally in the scratch folder.
+     */
+    public static PendingAttachmentData createPendingAttachmentData(final String contentType,
+            final Uri sourceUri) {
+        return createPendingAttachmentData(null, contentType, sourceUri, UNSPECIFIED_SIZE,
+                UNSPECIFIED_SIZE);
+    }
+
+    public static PendingAttachmentData createPendingAttachmentData(final String caption,
+            final String contentType, final Uri sourceUri, final int width, final int height) {
+        Assert.isTrue(ContentType.isMediaType(contentType));
+        return new PendingAttachmentData(caption, contentType, sourceUri, width, height,
+                false /*onlySingleAttachment*/);
+    }
+
+    public static PendingAttachmentData createPendingAttachmentData(final String caption,
+            final String contentType, final Uri sourceUri, final int width, final int height,
+            final boolean onlySingleAttachment) {
+        Assert.isTrue(ContentType.isMediaType(contentType));
+        return new PendingAttachmentData(caption, contentType, sourceUri, width, height,
+                onlySingleAttachment);
+    }
+
+    public int getCurrentState() {
+        return mCurrentState;
+    }
+
+    public void loadAttachmentForDraft(final DraftMessageData draftMessageData,
+            final String bindingId) {
+        if (mCurrentState != STATE_PENDING) {
+            return;
+        }
+        mCurrentState = STATE_LOADING;
+
+        // Kick off a SafeAsyncTask to load the content of the media and persist it locally.
+        // Note: we need to persist the media locally even if it's not remote, because we
+        // want to be able to resend the media in case the message failed to send.
+        new SafeAsyncTask<Void, Void, MessagePartData>(LOAD_MEDIA_TIME_LIMIT_MILLIS,
+                true /* cancelExecutionOnTimeout */) {
+            @Override
+            protected MessagePartData doInBackgroundTimed(final Void... params) {
+                final Uri contentUri = getContentUri();
+                final Uri persistedUri = UriUtil.persistContentToScratchSpace(contentUri);
+                if (persistedUri != null) {
+                    return MessagePartData.createMediaMessagePart(
+                            getText(),
+                            getContentType(),
+                            persistedUri,
+                            getWidth(),
+                            getHeight());
+                }
+                return null;
+            }
+
+            @Override
+            protected void onCancelled() {
+                LogUtil.w(LogUtil.BUGLE_TAG, "Timeout while retrieving media");
+                mCurrentState = STATE_FAILED;
+                if (draftMessageData.isBound(bindingId)) {
+                    draftMessageData.removePendingAttachment(PendingAttachmentData.this);
+                }
+            }
+
+            @Override
+            protected void onPostExecute(final MessagePartData attachment) {
+                if (attachment != null) {
+                    mCurrentState = STATE_LOADED;
+                    if (draftMessageData.isBound(bindingId)) {
+                        draftMessageData.updatePendingAttachment(attachment,
+                                PendingAttachmentData.this);
+                    } else {
+                        // The draft message data is no longer bound, drop the loaded attachment.
+                        attachment.destroyAsync();
+                    }
+                } else {
+                    // Media load failed. We already logged in doInBackground() so don't need to
+                    // do that again.
+                    mCurrentState = STATE_FAILED;
+                    if (draftMessageData.isBound(bindingId)) {
+                        draftMessageData.onPendingAttachmentLoadFailed(PendingAttachmentData.this);
+                        draftMessageData.removePendingAttachment(PendingAttachmentData.this);
+                    }
+                }
+            }
+        }.executeOnThreadPool();
+    }
+
+    protected PendingAttachmentData(final Parcel in) {
+        super(in);
+        mCurrentState = in.readInt();
+    }
+
+    @Override
+    public void writeToParcel(final Parcel out, final int flags) {
+        super.writeToParcel(out, flags);
+        out.writeInt(mCurrentState);
+    }
+
+    public static final Parcelable.Creator<PendingAttachmentData> CREATOR
+        = new Parcelable.Creator<PendingAttachmentData>() {
+            @Override
+            public PendingAttachmentData createFromParcel(final Parcel in) {
+                return new PendingAttachmentData(in);
+            }
+
+            @Override
+            public PendingAttachmentData[] newArray(final int size) {
+                return new PendingAttachmentData[size];
+            }
+        };
+}
diff --git a/src/com/android/messaging/datamodel/data/PeopleAndOptionsData.java b/src/com/android/messaging/datamodel/data/PeopleAndOptionsData.java
new file mode 100644
index 0000000..650a037
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/PeopleAndOptionsData.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.BugleActionToasts;
+import com.android.messaging.datamodel.action.UpdateConversationOptionsAction;
+import com.android.messaging.datamodel.action.UpdateDestinationBlockedAction;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.List;
+
+/**
+ * Services data needs for PeopleAndOptionsFragment.
+ */
+public class PeopleAndOptionsData extends BindableData implements
+        LoaderManager.LoaderCallbacks<Cursor> {
+    public interface PeopleAndOptionsDataListener {
+        void onOptionsCursorUpdated(PeopleAndOptionsData data, Cursor cursor);
+        void onParticipantsListLoaded(PeopleAndOptionsData data,
+                List<ParticipantData> participants);
+    }
+
+    private static final String BINDING_ID = "bindingId";
+    private final Context mContext;
+    private final String mConversationId;
+    private final ConversationParticipantsData mParticipantData;
+    private LoaderManager mLoaderManager;
+    private PeopleAndOptionsDataListener mListener;
+
+    public PeopleAndOptionsData(final String conversationId, final Context context,
+            final PeopleAndOptionsDataListener listener) {
+        mListener = listener;
+        mContext = context;
+        mConversationId = conversationId;
+        mParticipantData = new ConversationParticipantsData();
+    }
+
+    private static final int CONVERSATION_OPTIONS_LOADER = 1;
+    private static final int PARTICIPANT_LOADER = 2;
+
+    @Override
+    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+        final String bindingId = args.getString(BINDING_ID);
+        // Check if data still bound to the requesting ui element
+        if (isBound(bindingId)) {
+            switch (id) {
+                case CONVERSATION_OPTIONS_LOADER: {
+                    final Uri uri =
+                            MessagingContentProvider.buildConversationMetadataUri(mConversationId);
+                    return new BoundCursorLoader(bindingId, mContext, uri,
+                            PeopleOptionsItemData.PROJECTION, null, null, null);
+                }
+
+                case PARTICIPANT_LOADER: {
+                    final Uri uri =
+                            MessagingContentProvider
+                                    .buildConversationParticipantsUri(mConversationId);
+                    return new BoundCursorLoader(bindingId, mContext, uri,
+                            ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
+                }
+
+                default:
+                    Assert.fail("Unknown loader id for PeopleAndOptionsFragment!");
+                    break;
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding PeopleAndOptionsFragment");
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        if (isBound(cursorLoader.getBindingId())) {
+            switch (loader.getId()) {
+                case CONVERSATION_OPTIONS_LOADER:
+                    mListener.onOptionsCursorUpdated(this, data);
+                    break;
+
+                case PARTICIPANT_LOADER:
+                    mParticipantData.bind(data);
+                    mListener.onParticipantsListLoaded(this,
+                            mParticipantData.getParticipantListExcludingSelf());
+                    break;
+
+                default:
+                    Assert.fail("Unknown loader id for PeopleAndOptionsFragment!");
+                    break;
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG,
+                    "Loader finished after unbinding PeopleAndOptionsFragment");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onLoaderReset(final Loader<Cursor> loader) {
+        final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
+        if (isBound(cursorLoader.getBindingId())) {
+            switch (loader.getId()) {
+                case CONVERSATION_OPTIONS_LOADER:
+                    mListener.onOptionsCursorUpdated(this, null);
+                    break;
+
+                case PARTICIPANT_LOADER:
+                    mParticipantData.bind(null);
+                    break;
+
+                default:
+                    Assert.fail("Unknown loader id for PeopleAndOptionsFragment!");
+                    break;
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding PeopleAndOptionsFragment");
+        }
+    }
+
+    public void init(final LoaderManager loaderManager,
+            final BindingBase<PeopleAndOptionsData> binding) {
+        final Bundle args = new Bundle();
+        args.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(CONVERSATION_OPTIONS_LOADER, args, this);
+        mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(CONVERSATION_OPTIONS_LOADER);
+            mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    public void enableConversationNotifications(final BindingBase<PeopleAndOptionsData> binding,
+            final boolean enable) {
+        final String bindingId = binding.getBindingId();
+        if (isBound(bindingId)) {
+            UpdateConversationOptionsAction.enableConversationNotifications(
+                    mConversationId, enable);
+        }
+    }
+
+    public void setConversationNotificationSound(final BindingBase<PeopleAndOptionsData> binding,
+            final String ringtoneUri) {
+        final String bindingId = binding.getBindingId();
+        if (isBound(bindingId)) {
+            UpdateConversationOptionsAction.setConversationNotificationSound(mConversationId,
+                    ringtoneUri);
+        }
+    }
+
+    public void enableConversationNotificationVibration(
+            final BindingBase<PeopleAndOptionsData> binding, final boolean enable) {
+        final String bindingId = binding.getBindingId();
+        if (isBound(bindingId)) {
+            UpdateConversationOptionsAction.enableVibrationForConversationNotification(
+                    mConversationId, enable);
+        }
+    }
+
+    public void setDestinationBlocked(final BindingBase<PeopleAndOptionsData> binding,
+            final boolean blocked) {
+        final String bindingId = binding.getBindingId();
+        final ParticipantData participantData = mParticipantData.getOtherParticipant();
+        if (isBound(bindingId) && participantData != null) {
+            UpdateDestinationBlockedAction.updateDestinationBlocked(
+                    participantData.getNormalizedDestination(),
+                    blocked, mConversationId,
+                    BugleActionToasts.makeUpdateDestinationBlockedActionListener(mContext));
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/PeopleOptionsItemData.java b/src/com/android/messaging/datamodel/data/PeopleOptionsItemData.java
new file mode 100644
index 0000000..5af6a30
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/PeopleOptionsItemData.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationListItemData.ConversationListViewColumns;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.RingtoneUtil;
+
+public class PeopleOptionsItemData {
+    public static final String[] PROJECTION = {
+        ConversationListViewColumns.NOTIFICATION_ENABLED,
+        ConversationListViewColumns.NOTIFICATION_SOUND_URI,
+        ConversationListViewColumns.NOTIFICATION_VIBRATION,
+    };
+
+    // Column index for query projection.
+    private static final int INDEX_NOTIFICATION_ENABLED = 0;
+    private static final int INDEX_NOTIFICATION_SOUND_URI = 1;
+    private static final int INDEX_NOTIFICATION_VIBRATION = 2;
+
+    // Identification for each setting that's surfaced to the UI layer.
+    public static final int SETTING_NOTIFICATION_ENABLED = 0;
+    public static final int SETTING_NOTIFICATION_SOUND_URI = 1;
+    public static final int SETTING_NOTIFICATION_VIBRATION = 2;
+    public static final int SETTING_BLOCKED = 3;
+    public static final int SETTINGS_COUNT = 4;
+
+    // Type of UI switch to show for the toggle button.
+    public static final int TOGGLE_TYPE_CHECKBOX = 0;
+    public static final int TOGGLE_TYPE_SWITCH = 1;
+
+    private String mTitle;
+    private String mSubtitle;
+    private Uri mRingtoneUri;
+    private boolean mCheckable;
+    private boolean mChecked;
+    private boolean mEnabled;
+    private int mItemId;
+    private ParticipantData mOtherParticipant;
+
+    private final Context mContext;
+
+    public PeopleOptionsItemData(final Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Bind to a specific setting column on conversation metadata cursor. (Note
+     * that it binds to columns because it treats individual columns of the cursor as
+     * separate options to display for the conversation, e.g. notification settings).
+     */
+    public void bind(
+            final Cursor cursor, final ParticipantData otherParticipant, final int settingType) {
+        mSubtitle = null;
+        mRingtoneUri = null;
+        mCheckable = true;
+        mEnabled = true;
+        mItemId = settingType;
+        mOtherParticipant = otherParticipant;
+
+        final boolean notificationEnabled = cursor.getInt(INDEX_NOTIFICATION_ENABLED) == 1;
+        switch (settingType) {
+            case SETTING_NOTIFICATION_ENABLED:
+                mTitle = mContext.getString(R.string.notifications_enabled_conversation_pref_title);
+                mChecked = notificationEnabled;
+                break;
+
+            case SETTING_NOTIFICATION_SOUND_URI:
+                mTitle = mContext.getString(R.string.notification_sound_pref_title);
+                final String ringtoneString = cursor.getString(INDEX_NOTIFICATION_SOUND_URI);
+                Uri ringtoneUri = RingtoneUtil.getNotificationRingtoneUri(ringtoneString);
+
+                mSubtitle = mContext.getString(R.string.silent_ringtone);
+                if (ringtoneUri != null) {
+                    final Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri);
+                    if (ringtone != null) {
+                        mSubtitle = ringtone.getTitle(mContext);
+                    }
+                }
+                mCheckable = false;
+                mRingtoneUri = ringtoneUri;
+                mEnabled = notificationEnabled;
+                break;
+
+            case SETTING_NOTIFICATION_VIBRATION:
+                mTitle = mContext.getString(R.string.notification_vibrate_pref_title);
+                mChecked = cursor.getInt(INDEX_NOTIFICATION_VIBRATION) == 1;
+                mEnabled = notificationEnabled;
+                break;
+
+            case SETTING_BLOCKED:
+                Assert.notNull(otherParticipant);
+                final int resourceId = otherParticipant.isBlocked() ?
+                        R.string.unblock_contact_title : R.string.block_contact_title;
+                mTitle = mContext.getString(resourceId, otherParticipant.getDisplayDestination());
+                mCheckable = false;
+                break;
+
+             default:
+                 Assert.fail("Unsupported conversation option type!");
+        }
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public String getSubtitle() {
+        return mSubtitle;
+    }
+
+    public boolean getCheckable() {
+        return mCheckable;
+    }
+
+    public boolean getChecked() {
+        return mChecked;
+    }
+
+    public boolean getEnabled() {
+        return mEnabled;
+    }
+
+    public int getItemId() {
+        return mItemId;
+    }
+
+    public Uri getRingtoneUri() {
+        return mRingtoneUri;
+    }
+
+    public ParticipantData getOtherParticipant() {
+        return mOtherParticipant;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/PersonItemData.java b/src/com/android/messaging/datamodel/data/PersonItemData.java
new file mode 100644
index 0000000..a0a1ce8
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/PersonItemData.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.messaging.datamodel.binding.BindableData;
+
+/**
+ * Bridges between any particpant/contact related data and data displayed in the PersonItemView.
+ */
+public abstract class PersonItemData extends BindableData {
+    /**
+     * The UI component that listens for data change and update accordingly.
+     */
+    public interface PersonItemDataListener {
+        void onPersonDataUpdated(PersonItemData data);
+        void onPersonDataFailed(PersonItemData data, Exception exception);
+    }
+
+    private PersonItemDataListener mListener;
+
+    public abstract Uri getAvatarUri();
+    public abstract String getDisplayName();
+    public abstract String getDetails();
+    public abstract Intent getClickIntent();
+    public abstract long getContactId();
+    public abstract String getLookupKey();
+    public abstract String getNormalizedDestination();
+
+    public void setListener(final PersonItemDataListener listener) {
+        if (isBound()) {
+            mListener = listener;
+        }
+    }
+
+    protected void notifyDataUpdated() {
+        if (isBound() && mListener != null) {
+            mListener.onPersonDataUpdated(this);
+        }
+    }
+
+    protected void notifyDataFailed(final Exception exception) {
+        if (isBound() && mListener != null) {
+            mListener.onPersonDataFailed(this, exception);
+        }
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/SelfParticipantsData.java b/src/com/android/messaging/datamodel/data/SelfParticipantsData.java
new file mode 100644
index 0000000..f389a78
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/SelfParticipantsData.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.database.Cursor;
+import androidx.collection.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import com.android.messaging.util.OsUtil;
+
+/**
+ * A class that contains the list of all self participants potentially involved in a conversation.
+ * This class contains both active/inactive self entries when there is multi-SIM support.
+ */
+public class SelfParticipantsData {
+    /**
+     * The map from self participant ids to self-participant data entries in the participants table.
+     * This includes both active, inactive and default (with subId ==
+     * {@link ParticipantData#DEFAULT_SELF_SUB_ID}) subscriptions.
+     */
+    private final ArrayMap<String, ParticipantData> mSelfParticipantMap;
+
+    public SelfParticipantsData() {
+        mSelfParticipantMap = new ArrayMap<String, ParticipantData>();
+    }
+
+    public void bind(final Cursor cursor) {
+        mSelfParticipantMap.clear();
+        if (cursor != null) {
+            while (cursor.moveToNext()) {
+                final ParticipantData newParticipant = ParticipantData.getFromCursor(cursor);
+                mSelfParticipantMap.put(newParticipant.getId(), newParticipant);
+            }
+        }
+    }
+
+    /**
+     * Gets the list of self participants for all subscriptions.
+     * @param activeOnly if set, returns active self entries only (i.e. those with SIMs plugged in).
+     */
+    public List<ParticipantData> getSelfParticipants(final boolean activeOnly) {
+         List<ParticipantData> list = new ArrayList<ParticipantData>();
+        for (final ParticipantData self : mSelfParticipantMap.values()) {
+            if (!activeOnly || self.isActiveSubscription()) {
+                list.add(self);
+            }
+        }
+        Collections.sort(
+                list,
+                new Comparator() {
+                    public int compare(Object o1, Object o2) {
+                        int slotId1 = ((ParticipantData) o1).getSlotId();
+                        int slotId2 = ((ParticipantData) o2).getSlotId();
+                        return slotId1 > slotId2 ? 1 : -1;
+                    }
+                });
+        return list;
+    }
+
+    /**
+     * Gets the self participant corresponding to the given self id.
+     */
+    ParticipantData getSelfParticipantById(final String selfId) {
+        return mSelfParticipantMap.get(selfId);
+    }
+
+    /**
+     * Returns if a given self id represents the default self.
+     */
+    boolean isDefaultSelf(final String selfId) {
+        if (!OsUtil.isAtLeastL_MR1()) {
+            return true;
+        }
+        final ParticipantData self = getSelfParticipantById(selfId);
+        return self == null ? false : self.getSubId() == ParticipantData.DEFAULT_SELF_SUB_ID;
+    }
+
+    public int getSelfParticipantsCountExcludingDefault(final boolean activeOnly) {
+        int count = 0;
+        for (final ParticipantData self : mSelfParticipantMap.values()) {
+            if (!self.isDefaultSelf() && (!activeOnly || self.isActiveSubscription())) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    public ParticipantData getDefaultSelfParticipant() {
+        for (final ParticipantData self : mSelfParticipantMap.values()) {
+            if (self.isDefaultSelf()) {
+                return self;
+            }
+        }
+        return null;
+    }
+
+    boolean isLoaded() {
+        return !mSelfParticipantMap.isEmpty();
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/SettingsData.java b/src/com/android/messaging/datamodel/data/SettingsData.java
new file mode 100644
index 0000000..7474619
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/SettingsData.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.BoundCursorLoader;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Services SettingsFragment's data needs for loading active self participants to display
+ * the list of active subscriptions.
+ */
+public class SettingsData extends BindableData implements
+        LoaderManager.LoaderCallbacks<Cursor> {
+    public interface SettingsDataListener {
+        void onSelfParticipantDataLoaded(SettingsData data);
+    }
+
+    public static class SettingsItem {
+        public static final int TYPE_GENERAL_SETTINGS = 1;
+        public static final int TYPE_PER_SUBSCRIPTION_SETTINGS = 2;
+
+        private final String mDisplayName;
+        private final String mDisplayDetail;
+        private final String mActivityTitle;
+        private final int mType;
+        private final int mSubId;
+
+        private SettingsItem(final String displayName, final String displayDetail,
+                final String activityTitle, final int type, final int subId) {
+            mDisplayName = displayName;
+            mDisplayDetail = displayDetail;
+            mActivityTitle = activityTitle;
+            mType = type;
+            mSubId = subId;
+        }
+
+        public String getDisplayName() {
+            return mDisplayName;
+        }
+
+        public String getDisplayDetail() {
+            return mDisplayDetail;
+        }
+
+        public int getType() {
+            return mType;
+        }
+
+        public int getSubId() {
+            return mSubId;
+        }
+
+        public String getActivityTitle() {
+            return mActivityTitle;
+        }
+
+        public static SettingsItem fromSelfParticipant(final Context context,
+                final ParticipantData self) {
+            Assert.isTrue(self.isSelf());
+            Assert.isTrue(self.isActiveSubscription());
+            final String displayDetail = TextUtils.isEmpty(self.getDisplayDestination()) ?
+                    context.getString(R.string.sim_settings_unknown_number) :
+                        self.getDisplayDestination();
+            final String displayName = context.getString(R.string.sim_specific_settings,
+                    self.getSubscriptionName());
+            return new SettingsItem(displayName, displayDetail, displayName,
+                    TYPE_PER_SUBSCRIPTION_SETTINGS, self.getSubId());
+        }
+
+        public static SettingsItem createGeneralSettingsItem(final Context context) {
+            return new SettingsItem(context.getString(R.string.general_settings),
+                    null, context.getString(R.string.general_settings_activity_title),
+                    TYPE_GENERAL_SETTINGS, -1);
+        }
+
+        public static SettingsItem createDefaultMmsSettingsItem(final Context context,
+                final int subId) {
+            return new SettingsItem(context.getString(R.string.advanced_settings),
+                    null, context.getString(R.string.advanced_settings_activity_title),
+                    TYPE_PER_SUBSCRIPTION_SETTINGS, subId);
+        }
+    }
+
+    private static final String BINDING_ID = "bindingId";
+    private final Context mContext;
+    private final SelfParticipantsData mSelfParticipantsData;
+    private LoaderManager mLoaderManager;
+    private SettingsDataListener mListener;
+
+    public SettingsData(final Context context,
+            final SettingsDataListener listener) {
+        mListener = listener;
+        mContext = context;
+        mSelfParticipantsData = new SelfParticipantsData();
+    }
+
+    private static final int SELF_PARTICIPANT_LOADER = 1;
+
+    @Override
+    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
+        Assert.equals(SELF_PARTICIPANT_LOADER, id);
+        Loader<Cursor> loader = null;
+
+        final String bindingId = args.getString(BINDING_ID);
+        // Check if data still bound to the requesting ui element
+        if (isBound(bindingId)) {
+            loader = new BoundCursorLoader(bindingId, mContext,
+                    MessagingContentProvider.PARTICIPANTS_URI,
+                    ParticipantData.ParticipantsQuery.PROJECTION,
+                    ParticipantColumns.SUB_ID + " <> ?",
+                    new String[] { String.valueOf(ParticipantData.OTHER_THAN_SELF_SUB_ID) },
+                    null);
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Creating self loader after unbinding");
+        }
+        return loader;
+    }
+
+    @Override
+    public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
+        final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+        // Check if data still bound to the requesting ui element
+        if (isBound(loader.getBindingId())) {
+            mSelfParticipantsData.bind(data);
+            mListener.onSelfParticipantDataLoaded(this);
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Self loader finished after unbinding");
+        }
+    }
+
+    @Override
+    public void onLoaderReset(final Loader<Cursor> generic) {
+        final BoundCursorLoader loader = (BoundCursorLoader) generic;
+
+        // Check if data still bound to the requesting ui element
+        if (isBound(loader.getBindingId())) {
+            mSelfParticipantsData.bind(null);
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Self loader reset after unbinding");
+        }
+    }
+
+    public void init(final LoaderManager loaderManager,
+            final BindingBase<SettingsData> binding) {
+        final Bundle args = new Bundle();
+        args.putString(BINDING_ID, binding.getBindingId());
+        mLoaderManager = loaderManager;
+        mLoaderManager.initLoader(SELF_PARTICIPANT_LOADER, args, this);
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+
+        // This could be null if we bind but the caller doesn't init the BindableData
+        if (mLoaderManager != null) {
+            mLoaderManager.destroyLoader(SELF_PARTICIPANT_LOADER);
+            mLoaderManager = null;
+        }
+    }
+
+    public List<SettingsItem> getSettingsItems() {
+        final List<ParticipantData> selfs = mSelfParticipantsData.getSelfParticipants(true);
+        final List<SettingsItem> settingsItems = new ArrayList<SettingsItem>();
+        // First goes the general settings, followed by per-subscription settings.
+        settingsItems.add(SettingsItem.createGeneralSettingsItem(mContext));
+        // For per-subscription settings, show the actual SIM name with phone number if the
+        // platorm is at least L-MR1 and there are multiple active SIMs.
+        final int activeSubCountExcludingDefault =
+                mSelfParticipantsData.getSelfParticipantsCountExcludingDefault(true);
+        if (OsUtil.isAtLeastL_MR1() && activeSubCountExcludingDefault > 0) {
+            for (ParticipantData self : selfs) {
+                if (!self.isDefaultSelf()) {
+                    if (activeSubCountExcludingDefault > 1) {
+                        settingsItems.add(SettingsItem.fromSelfParticipant(mContext, self));
+                    } else {
+                        // This is the only active non-default SIM.
+                        settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext,
+                                self.getSubId()));
+                        break;
+                    }
+                }
+            }
+        } else {
+            // Either pre-L-MR1, or there's no active SIM, so show the default MMS settings.
+            settingsItems.add(SettingsItem.createDefaultMmsSettingsItem(mContext,
+                    ParticipantData.DEFAULT_SELF_SUB_ID));
+        }
+        return settingsItems;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/SubscriptionListData.java b/src/com/android/messaging/datamodel/data/SubscriptionListData.java
new file mode 100644
index 0000000..b5d4e4b
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/SubscriptionListData.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.content.Context;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * This is a UI facing data model component that holds a list of
+ * {@link SubscriptionListData.SubscriptionListEntry}'s, one for each *active* subscriptions.
+ *
+ * This is used to:
+ * 1) Show a list of SIMs in the SIM Selector
+ * 2) Show the currently selected SIM in the compose message view
+ * 3) Show SIM indicators on conversation message views
+ *
+ * It builds on top of SelfParticipantsData and performs additional logic such as determining
+ * the set of icons to use for the individual Subs.
+ */
+public class SubscriptionListData {
+    /**
+     * Represents a single sub that backs UI.
+     */
+    public static class SubscriptionListEntry {
+        public final String selfParticipantId;
+        public final Uri iconUri;
+        public final Uri selectedIconUri;
+        public final String displayName;
+        public final int displayColor;
+        public final String displayDestination;
+
+        private SubscriptionListEntry(final String selfParticipantId, final Uri iconUri,
+                final Uri selectedIconUri, final String displayName, final int displayColor,
+                final String displayDestination) {
+            this.selfParticipantId = selfParticipantId;
+            this.iconUri = iconUri;
+            this.selectedIconUri = selectedIconUri;
+            this.displayName = displayName;
+            this.displayColor = displayColor;
+            this.displayDestination = displayDestination;
+        }
+
+        static SubscriptionListEntry fromSelfParticipantData(
+                final ParticipantData selfParticipantData, final Context context) {
+            Assert.isTrue(selfParticipantData.isSelf());
+            Assert.isTrue(selfParticipantData.isActiveSubscription());
+            final int slotId = selfParticipantData.getDisplaySlotId();
+            final String iconIdentifier = String.format(Locale.getDefault(), "%d", slotId);
+            final String subscriptionName = selfParticipantData.getSubscriptionName();
+            final String displayName = TextUtils.isEmpty(subscriptionName) ?
+                    context.getString(R.string.sim_slot_identifier, slotId) : subscriptionName;
+            return new SubscriptionListEntry(selfParticipantData.getId(),
+                    AvatarUriUtil.createAvatarUri(selfParticipantData, iconIdentifier,
+                            false /* selected */, false /* incoming */),
+                    AvatarUriUtil.createAvatarUri(selfParticipantData, iconIdentifier,
+                            true /* selected */, false /* incoming */),
+                    displayName, selfParticipantData.getSubscriptionColor(),
+                    selfParticipantData.getDisplayDestination());
+        }
+    }
+
+    private final List<SubscriptionListEntry> mEntriesExcludingDefault;
+    private SubscriptionListEntry mDefaultEntry;
+    private final Context mContext;
+
+    public SubscriptionListData(final Context context) {
+        mEntriesExcludingDefault = new ArrayList<SubscriptionListEntry>();
+        mContext = context;
+    }
+
+    public void bind(final List<ParticipantData> subs) {
+        mEntriesExcludingDefault.clear();
+        mDefaultEntry = null;
+        for (final ParticipantData sub : subs) {
+            final SubscriptionListEntry entry =
+                    SubscriptionListEntry.fromSelfParticipantData(sub, mContext);
+            if (!sub.isDefaultSelf()) {
+                mEntriesExcludingDefault.add(entry);
+            } else {
+                mDefaultEntry = entry;
+            }
+        }
+    }
+
+    public List<SubscriptionListEntry> getActiveSubscriptionEntriesExcludingDefault() {
+        return mEntriesExcludingDefault;
+    }
+
+    public SubscriptionListEntry getActiveSubscriptionEntryBySelfId(final String selfId,
+            final boolean excludeDefault) {
+        if (mDefaultEntry != null && TextUtils.equals(mDefaultEntry.selfParticipantId, selfId)) {
+            return excludeDefault ? null : mDefaultEntry;
+        }
+
+        for (final SubscriptionListEntry entry : mEntriesExcludingDefault) {
+            if (TextUtils.equals(entry.selfParticipantId, selfId)) {
+                return entry;
+            }
+        }
+        return null;
+    }
+
+    public boolean hasData() {
+        return !mEntriesExcludingDefault.isEmpty() || mDefaultEntry != null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/data/VCardContactItemData.java b/src/com/android/messaging/datamodel/data/VCardContactItemData.java
new file mode 100644
index 0000000..8abf493
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/VCardContactItemData.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.media.BindableMediaRequest;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+import com.android.messaging.datamodel.media.VCardRequestDescriptor;
+import com.android.messaging.datamodel.media.VCardResource;
+import com.android.messaging.datamodel.media.VCardResourceEntry;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ContactUtil;
+
+import java.util.List;
+
+/**
+ * Data class for visualizing and loading data for a VCard contact.
+ */
+public class VCardContactItemData extends PersonItemData
+        implements MediaResourceLoadListener<VCardResource> {
+    private final Context mContext;
+    private final Uri mVCardUri;
+    private String mDetails;
+    private final Binding<BindableMediaRequest<VCardResource>> mBinding =
+            BindingBase.createBinding(this);
+    private VCardResource mVCardResource;
+
+    private static final Uri sDefaultAvatarUri =
+            AvatarUriUtil.createAvatarUri(null, null, null, null);
+
+    /**
+     * Constructor. This parses data from the given MessagePartData describing the vcard
+     */
+    public VCardContactItemData(final Context context, final MessagePartData messagePartData) {
+        this(context, messagePartData.getContentUri());
+        Assert.isTrue(messagePartData.isVCard());
+    }
+
+    /**
+     * Constructor. This parses data from the given VCard Uri
+     */
+    public VCardContactItemData(final Context context, final Uri vCardUri) {
+        mContext = context;
+        mDetails = mContext.getString(R.string.loading_vcard);
+        mVCardUri = vCardUri;
+    }
+
+    @Override
+    public Uri getAvatarUri() {
+        if (hasValidVCard()) {
+            final List<VCardResourceEntry> vcards = mVCardResource.getVCards();
+            Assert.isTrue(vcards.size() > 0);
+            if (vcards.size() == 1) {
+                return vcards.get(0).getAvatarUri();
+            }
+        }
+        return sDefaultAvatarUri;
+    }
+
+    @Override
+    public String getDisplayName() {
+        if (hasValidVCard()) {
+            final List<VCardResourceEntry> vcards = mVCardResource.getVCards();
+            Assert.isTrue(vcards.size() > 0);
+            if (vcards.size() == 1) {
+                return vcards.get(0).getDisplayName();
+            } else {
+                return mContext.getResources().getQuantityString(
+                        R.plurals.vcard_multiple_display_name, vcards.size(), vcards.size());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getDetails() {
+        return mDetails;
+    }
+
+    @Override
+    public Intent getClickIntent() {
+        return null;
+    }
+
+    @Override
+    public long getContactId() {
+        return ContactUtil.INVALID_CONTACT_ID;
+    }
+
+    @Override
+    public String getLookupKey() {
+        return null;
+    }
+
+    @Override
+    public String getNormalizedDestination() {
+        return null;
+    }
+
+    public VCardResource getVCardResource() {
+        return hasValidVCard() ? mVCardResource : null;
+    }
+
+    public Uri getVCardUri() {
+        return hasValidVCard() ? mVCardUri : null;
+    }
+
+    public boolean hasValidVCard() {
+        return isBound() && mVCardResource != null;
+    }
+
+    @Override
+    public void bind(final String bindingId) {
+        super.bind(bindingId);
+
+        // Bind and request the VCard from media resource manager.
+        mBinding.bind(new VCardRequestDescriptor(mVCardUri).buildAsyncMediaRequest(mContext, this));
+        MediaResourceManager.get().requestMediaResourceAsync(mBinding.getData());
+    }
+
+    @Override
+    public void unbind(final String bindingId) {
+        super.unbind(bindingId);
+        mBinding.unbind();
+        if (mVCardResource != null) {
+            mVCardResource.release();
+            mVCardResource = null;
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof VCardContactItemData)) {
+            return false;
+        }
+
+        final VCardContactItemData lhs = (VCardContactItemData) o;
+        return mVCardUri.equals(lhs.mVCardUri);
+    }
+
+    @Override
+    public void onMediaResourceLoaded(final MediaRequest<VCardResource> request,
+            final VCardResource resource, final boolean isCached) {
+        Assert.isTrue(mVCardResource == null);
+        mBinding.ensureBound();
+        mDetails = mContext.getString(R.string.vcard_tap_hint);
+        mVCardResource = resource;
+        mVCardResource.addRef();
+        notifyDataUpdated();
+    }
+
+    @Override
+    public void onMediaResourceLoadError(final MediaRequest<VCardResource> request,
+            final Exception exception) {
+        mBinding.ensureBound();
+        mDetails = mContext.getString(R.string.failed_loading_vcard);
+        notifyDataFailed(exception);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/AsyncMediaRequestWrapper.java b/src/com/android/messaging/datamodel/media/AsyncMediaRequestWrapper.java
new file mode 100644
index 0000000..380d93c
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/AsyncMediaRequestWrapper.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+
+import java.util.List;
+
+/**
+ * A mix-in style class that wraps around a normal, threading-agnostic MediaRequest object with
+ * functionalities offered by {@link BindableMediaRequest} to allow for async processing.
+ */
+class AsyncMediaRequestWrapper<T extends RefCountedMediaResource> extends BindableMediaRequest<T> {
+
+    /**
+     * Create a new async media request wrapper instance given the listener.
+     */
+    public static <T extends RefCountedMediaResource> AsyncMediaRequestWrapper<T>
+            createWith(final MediaRequest<T> wrappedRequest,
+                    final MediaResourceLoadListener<T> listener) {
+        return new AsyncMediaRequestWrapper<T>(listener, wrappedRequest);
+    }
+
+    private final MediaRequest<T> mWrappedRequest;
+
+    private AsyncMediaRequestWrapper(final MediaResourceLoadListener<T> listener,
+            final MediaRequest<T> wrappedRequest) {
+        super(listener);
+        mWrappedRequest = wrappedRequest;
+    }
+
+    @Override
+    public String getKey() {
+        return mWrappedRequest.getKey();
+    }
+
+    @Override
+    public MediaCache<T> getMediaCache() {
+        return mWrappedRequest.getMediaCache();
+    }
+
+    @Override
+    public int getRequestType() {
+        return mWrappedRequest.getRequestType();
+    }
+
+    @Override
+    public T loadMediaBlocking(List<MediaRequest<T>> chainedTask) throws Exception {
+        return mWrappedRequest.loadMediaBlocking(chainedTask);
+    }
+
+    @Override
+    public int getCacheId() {
+        return mWrappedRequest.getCacheId();
+    }
+
+    @Override
+    public MediaRequestDescriptor<T> getDescriptor() {
+        return mWrappedRequest.getDescriptor();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/AvatarGroupRequestDescriptor.java b/src/com/android/messaging/datamodel/media/AvatarGroupRequestDescriptor.java
new file mode 100644
index 0000000..719b296
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/AvatarGroupRequestDescriptor.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.RectF;
+import android.net.Uri;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class AvatarGroupRequestDescriptor extends CompositeImageRequestDescriptor {
+    private static final int MAX_GROUP_SIZE = 4;
+
+    public AvatarGroupRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight) {
+        this(convertToDescriptor(uri, desiredWidth, desiredHeight), desiredWidth, desiredHeight);
+    }
+
+    public AvatarGroupRequestDescriptor(final List<? extends ImageRequestDescriptor> descriptors,
+            final int desiredWidth, final int desiredHeight) {
+        super(descriptors, desiredWidth, desiredHeight);
+        Assert.isTrue(descriptors.size() <= MAX_GROUP_SIZE);
+    }
+
+    private static List<? extends ImageRequestDescriptor> convertToDescriptor(final Uri uri,
+            final int desiredWidth, final int desiredHeight) {
+        final List<String> participantUriStrings = AvatarUriUtil.getGroupParticipantUris(uri);
+        final List<AvatarRequestDescriptor> avatarDescriptors =
+                new ArrayList<AvatarRequestDescriptor>(participantUriStrings.size());
+        for (final String uriString : participantUriStrings) {
+            final AvatarRequestDescriptor descriptor = new AvatarRequestDescriptor(
+                    Uri.parse(uriString), desiredWidth, desiredHeight);
+            avatarDescriptors.add(descriptor);
+        }
+        return avatarDescriptors;
+    }
+
+    @Override
+    public CompositeImageRequest<?> buildBatchImageRequest(final Context context) {
+        return new CompositeImageRequest<AvatarGroupRequestDescriptor>(context, this);
+    }
+
+    @Override
+    public List<RectF> getChildRequestTargetRects() {
+        return Arrays.asList(generateDestRectArray());
+    }
+
+    /**
+     * Generates an array of {@link RectF} which represents where each of the individual avatar
+     * should be located in the final group avatar image. The location of each avatar depends on
+     * the size of the group and the size of the overall group avatar size.
+     */
+    private RectF[] generateDestRectArray() {
+        final int groupSize = mDescriptors.size();
+        final float width = desiredWidth;
+        final float height = desiredHeight;
+        final float halfWidth = width / 2F;
+        final float halfHeight = height / 2F;
+        final RectF[] destArray = new RectF[groupSize];
+        switch (groupSize) {
+            case 2:
+                /**
+                 * +-------+
+                 * | 0 |   |
+                 * +-------+
+                 * |   | 1 |
+                 * +-------+
+                 *
+                 * We want two circles which touches in the center. To get this we know that the
+                 * diagonal of the overall group avatar is squareRoot(2) * w We also know that the
+                 * two circles touches the at the center of the overall group avatar and the
+                 * distance from the center of the circle to the corner of the group avatar is
+                 * radius * squareRoot(2). Therefore, the following emerges.
+                 *
+                 * w * squareRoot(2) = 2 (radius + radius * squareRoot(2))
+                 * Solving for radius we get:
+                 * d = 2 * radius = ( squareRoot(2) / (squareRoot(2) + 1)) * w
+                 * d = (2 - squareRoot(2)) * w
+                 */
+                final float diameter = (float) ((2 - Math.sqrt(2)) * width);
+                destArray[0] = new RectF(0, 0, diameter, diameter);
+                destArray[1] = new RectF(width - diameter, height - diameter, width, height);
+                break;
+            case 3:
+                /**
+                 * +-------+
+                 * | | 0 | |
+                 * +-------+
+                 * | 1 | 2 |
+                 * +-------+
+                 *   i0
+                 *   |\
+                 * a | \ c
+                 *   --- i2
+                 *    b
+                 *
+                 * a = radius * squareRoot(3) due to the triangle being a 30-60-90 right triangle.
+                 * b = radius of circle
+                 * c = 2 * radius of circle
+                 *
+                 * All three of the images are circles and therefore image zero will not touch
+                 * image one or image two. Move image zero down so it touches image one and image
+                 * two. This can be done by keeping image zero in the center and moving it down
+                 * slightly. The amount to move down can be calculated by solving a right triangle.
+                 * We know that the center x of image two to the center x of image zero is the
+                 * radius of the circle, this is the length of edge b. Also we know that the
+                 * distance from image zero to image two's center is 2 * radius, edge c. From this
+                 * we know that the distance from center y of image two to center y of image one,
+                 * edge a, is equal to radius * squareRoot(3) due to this triangle being a 30-60-90
+                 * right triangle.
+                 */
+                final float quarterWidth = width / 4F;
+                final float threeQuarterWidth = 3 * quarterWidth;
+                final float radius = height / 4F;
+                final float imageTwoCenterY = height - radius;
+                final float lengthOfEdgeA = (float) (radius * Math.sqrt(3));
+                final float imageZeroCenterY = imageTwoCenterY - lengthOfEdgeA;
+                final float imageZeroTop = imageZeroCenterY - radius;
+                final float imageZeroBottom = imageZeroCenterY + radius;
+                destArray[0] = new RectF(
+                        quarterWidth, imageZeroTop, threeQuarterWidth, imageZeroBottom);
+                destArray[1] = new RectF(0, halfHeight, halfWidth, height);
+                destArray[2] = new RectF(halfWidth, halfHeight, width, height);
+                break;
+            default:
+                /**
+                 * +-------+
+                 * | 0 | 1 |
+                 * +-------+
+                 * | 2 | 3 |
+                 * +-------+
+                 */
+                destArray[0] = new RectF(0, 0, halfWidth, halfHeight);
+                destArray[1] = new RectF(halfWidth, 0, width, halfHeight);
+                destArray[2] = new RectF(0, halfHeight, halfWidth, height);
+                destArray[3] = new RectF(halfWidth, halfHeight, width, height);
+                break;
+        }
+        return destArray;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/AvatarRequest.java b/src/com/android/messaging/datamodel/media/AvatarRequest.java
new file mode 100644
index 0000000..6a738c7
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/AvatarRequest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.media.ExifInterface;
+import android.net.Uri;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UriUtil;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+public class AvatarRequest extends UriImageRequest<AvatarRequestDescriptor> {
+    private static Bitmap sDefaultPersonBitmap;
+    private static Bitmap sDefaultPersonBitmapLarge;
+
+    public AvatarRequest(final Context context,
+            final AvatarRequestDescriptor descriptor) {
+        super(context, descriptor);
+    }
+
+    @Override
+    protected InputStream getInputStreamForResource() throws FileNotFoundException {
+        if (UriUtil.isLocalResourceUri(mDescriptor.uri)) {
+            return super.getInputStreamForResource();
+        } else {
+            final Uri primaryUri = AvatarUriUtil.getPrimaryUri(mDescriptor.uri);
+            Assert.isTrue(UriUtil.isLocalResourceUri(primaryUri));
+            return mContext.getContentResolver().openInputStream(primaryUri);
+        }
+    }
+
+    /**
+     * We can load multiple types of images for avatars depending on the uri. The uri should be
+     * built by {@link com.android.messaging.util.AvatarUriUtil} which will decide on
+     * what uri to build based on the available profile photo and name. Here we will check if the
+     * image is a local resource (ie profile photo uri), if the resource isn't a local one we will
+     * generate a tile with the first letter of the name.
+     */
+    @Override
+    protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTasks)
+            throws IOException {
+        Assert.isNotMainThread();
+        String avatarType = AvatarUriUtil.getAvatarType(mDescriptor.uri);
+        Bitmap bitmap = null;
+        int orientation = ExifInterface.ORIENTATION_NORMAL;
+        final boolean isLocalResourceUri = UriUtil.isLocalResourceUri(mDescriptor.uri) ||
+                AvatarUriUtil.TYPE_LOCAL_RESOURCE_URI.equals(avatarType);
+        if (isLocalResourceUri) {
+            try {
+                ImageResource imageResource = super.loadMediaInternal(chainedTasks);
+                bitmap = imageResource.getBitmap();
+                orientation = imageResource.mOrientation;
+            } catch (Exception ex) {
+                // If we encountered any exceptions trying to load the local avatar resource,
+                // fall back to generated avatar.
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "AvatarRequest: failed to load local avatar " +
+                        "resource, switching to fallback rendering", ex);
+            }
+        }
+
+        final int width = mDescriptor.desiredWidth;
+        final int height = mDescriptor.desiredHeight;
+        // Check to see if we already got the bitmap. If not get a fallback avatar
+        if (bitmap == null) {
+            Uri generatedUri = mDescriptor.uri;
+            if (isLocalResourceUri) {
+                // If we are here, we just failed to load the local resource. Use the fallback Uri
+                // if possible.
+                generatedUri = AvatarUriUtil.getFallbackUri(mDescriptor.uri);
+                if (generatedUri == null) {
+                    // No fallback Uri was provided, use the default avatar.
+                    generatedUri = AvatarUriUtil.DEFAULT_BACKGROUND_AVATAR;
+                }
+            }
+
+            avatarType = AvatarUriUtil.getAvatarType(generatedUri);
+            if (AvatarUriUtil.TYPE_LETTER_TILE_URI.equals(avatarType)) {
+                final String name = AvatarUriUtil.getName(generatedUri);
+                bitmap = renderLetterTile(name, width, height);
+            } else {
+                bitmap = renderDefaultAvatar(width, height);
+            }
+        }
+        return new DecodedImageResource(getKey(), bitmap, orientation);
+    }
+
+    private Bitmap renderDefaultAvatar(final int width, final int height) {
+        final Bitmap bitmap = getBitmapPool().createOrReuseBitmap(width, height,
+                getBackgroundColor());
+        final Canvas canvas = new Canvas(bitmap);
+
+        if (sDefaultPersonBitmap == null) {
+            final BitmapDrawable defaultPerson = (BitmapDrawable) mContext.getResources()
+                    .getDrawable(R.drawable.ic_person_light);
+            sDefaultPersonBitmap = defaultPerson.getBitmap();
+        }
+        if (sDefaultPersonBitmapLarge == null) {
+            final BitmapDrawable largeDefaultPerson = (BitmapDrawable) mContext.getResources()
+                    .getDrawable(R.drawable.ic_person_light_large);
+            sDefaultPersonBitmapLarge = largeDefaultPerson.getBitmap();
+        }
+
+        Bitmap defaultPerson = null;
+        if (mDescriptor.isWearBackground) {
+            final BitmapDrawable wearDefaultPerson = (BitmapDrawable) mContext.getResources()
+                    .getDrawable(R.drawable.ic_person_wear);
+            defaultPerson = wearDefaultPerson.getBitmap();
+        } else {
+            final boolean isLargeDefault = (width > sDefaultPersonBitmap.getWidth()) ||
+                    (height > sDefaultPersonBitmap.getHeight());
+            defaultPerson =
+                    isLargeDefault ? sDefaultPersonBitmapLarge : sDefaultPersonBitmap;
+        }
+
+        final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        final Matrix matrix = new Matrix();
+        final RectF source = new RectF(0, 0, defaultPerson.getWidth(), defaultPerson.getHeight());
+        final RectF dest = new RectF(0, 0, width, height);
+        matrix.setRectToRect(source, dest, Matrix.ScaleToFit.FILL);
+
+        canvas.drawBitmap(defaultPerson, matrix, paint);
+
+        return bitmap;
+    }
+
+    private Bitmap renderLetterTile(final String name, final int width, final int height) {
+        final float halfWidth = width / 2;
+        final float halfHeight = height / 2;
+        final int minOfWidthAndHeight = Math.min(width, height);
+        final Bitmap bitmap = getBitmapPool().createOrReuseBitmap(width, height,
+                getBackgroundColor());
+        final Resources resources = mContext.getResources();
+        final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        paint.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
+        paint.setColor(resources.getColor(R.color.letter_tile_font_color));
+        final float letterToTileRatio = resources.getFraction(R.dimen.letter_to_tile_ratio, 1, 1);
+        paint.setTextSize(letterToTileRatio * minOfWidthAndHeight);
+
+        final String firstCharString = name.substring(0, 1).toUpperCase();
+        final Rect textBound = new Rect();
+        paint.getTextBounds(firstCharString, 0, 1, textBound);
+
+        final Canvas canvas = new Canvas(bitmap);
+        final float xOffset = halfWidth - textBound.centerX();
+        final float yOffset = halfHeight - textBound.centerY();
+        canvas.drawText(firstCharString, xOffset, yOffset, paint);
+
+        return bitmap;
+    }
+
+    private int getBackgroundColor() {
+        return mContext.getResources().getColor(R.color.primary_color);
+    }
+
+    @Override
+    public int getCacheId() {
+        return BugleMediaCacheManager.AVATAR_IMAGE_CACHE;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/AvatarRequestDescriptor.java b/src/com/android/messaging/datamodel/media/AvatarRequestDescriptor.java
new file mode 100644
index 0000000..9afa9ad
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/AvatarRequestDescriptor.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.UriUtil;
+
+public class AvatarRequestDescriptor extends UriImageRequestDescriptor {
+    final boolean isWearBackground;
+
+    public AvatarRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight) {
+        this(uri, desiredWidth, desiredHeight, true /* cropToCircle */);
+    }
+
+    public AvatarRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight, final boolean cropToCircle) {
+        this(uri, desiredWidth, desiredHeight, cropToCircle, false /* isWearBackground */);
+    }
+
+    public AvatarRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight, boolean cropToCircle, boolean isWearBackground) {
+        super(uri, desiredWidth, desiredHeight, false /* allowCompression */, true /* isStatic */,
+                cropToCircle,
+                ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+        Assert.isTrue(uri == null || UriUtil.isLocalResourceUri(uri) ||
+                AvatarUriUtil.isAvatarUri(uri));
+        this.isWearBackground = isWearBackground;
+    }
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(final Context context) {
+        final String avatarType = uri == null ? null : AvatarUriUtil.getAvatarType(uri);
+        if (AvatarUriUtil.TYPE_SIM_SELECTOR_URI.equals(avatarType)) {
+            return new SimSelectorAvatarRequest(context, this);
+        } else {
+            return new AvatarRequest(context, this);
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/BindableMediaRequest.java b/src/com/android/messaging/datamodel/media/BindableMediaRequest.java
new file mode 100644
index 0000000..d979323
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/BindableMediaRequest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import com.android.messaging.datamodel.binding.BindableOnceData;
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+
+/**
+ * The {@link MediaRequest} interface is threading-model-oblivious, allowing the implementations to
+ * be processed synchronously or asynchronously.
+ * This is a {@link MediaRequest} implementation that includes functionalities such as binding and
+ * event callbacks for multi-threaded media request processing.
+ */
+public abstract class BindableMediaRequest<T extends RefCountedMediaResource>
+        extends BindableOnceData
+        implements MediaRequest<T>, MediaResourceLoadListener<T> {
+    private MediaResourceLoadListener<T> mListener;
+
+    public BindableMediaRequest(final MediaResourceLoadListener<T> listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Delegates the media resource callback to the listener. Performs binding check to ensure
+     * the listener is still bound to this request.
+     */
+    @Override
+    public void onMediaResourceLoaded(final MediaRequest<T> request, final T resource,
+            final boolean cached) {
+        if (isBound() && mListener != null) {
+            mListener.onMediaResourceLoaded(request, resource, cached);
+        }
+    }
+
+    /**
+     * Delegates the media resource callback to the listener. Performs binding check to ensure
+     * the listener is still bound to this request.
+     */
+    @Override
+    public void onMediaResourceLoadError(final MediaRequest<T> request, final Exception exception) {
+        if (isBound() && mListener != null) {
+            mListener.onMediaResourceLoadError(request, exception);
+        }
+    }
+
+    @Override
+    protected void unregisterListeners() {
+        mListener = null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/BugleMediaCacheManager.java b/src/com/android/messaging/datamodel/media/BugleMediaCacheManager.java
new file mode 100644
index 0000000..c41ba60
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/BugleMediaCacheManager.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import com.android.messaging.util.Assert;
+
+/**
+ * An implementation of {@link MediaCacheManager} that creates caches specific to Bugle's needs.
+ *
+ * To create a new type of cache, add to the list of cache ids and create a new MediaCache<>
+ * for your cache id / media resource type in createMediaCacheById().
+ */
+public class BugleMediaCacheManager extends MediaCacheManager {
+    // List of available cache ids.
+    public static final int DEFAULT_IMAGE_CACHE = 1;
+    public static final int AVATAR_IMAGE_CACHE = 2;
+    public static final int VCARD_CACHE = 3;
+
+    // VCard cache size - we compute the size by count, not by bytes.
+    private static final int VCARD_CACHE_SIZE = 5;
+    private static final int SHARED_IMAGE_CACHE_SIZE = 1024 * 10;   // 10MB
+
+    @Override
+    protected MediaCache<?> createMediaCacheById(final int id) {
+        switch (id) {
+            case DEFAULT_IMAGE_CACHE:
+                return new PoolableImageCache(SHARED_IMAGE_CACHE_SIZE, id, "DefaultImageCache");
+
+            case AVATAR_IMAGE_CACHE:
+                return new PoolableImageCache(id, "AvatarImageCache");
+
+            case VCARD_CACHE:
+                return new MediaCache<VCardResource>(VCARD_CACHE_SIZE, id, "VCardCache");
+
+            default:
+                Assert.fail("BugleMediaCacheManager: unsupported cache id " + id);
+                break;
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/CompositeImageRequest.java b/src/com/android/messaging/datamodel/media/CompositeImageRequest.java
new file mode 100644
index 0000000..66f1bff
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/CompositeImageRequest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ImageUtils;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Requests a composite image resource. The composite image resource is constructed by first
+ * sequentially requesting a number of sub image resources specified by
+ * {@link CompositeImageRequestDescriptor#getChildRequestDescriptors()}. After this, the
+ * individual sub images are composed into the final image onto their respective target rects
+ * returned by {@link CompositeImageRequestDescriptor#getChildRequestTargetRects()}.
+ */
+public class CompositeImageRequest<D extends CompositeImageRequestDescriptor>
+        extends ImageRequest<D> {
+    private final Bitmap mBitmap;
+    private final Canvas mCanvas;
+    private final Paint mPaint;
+
+    public CompositeImageRequest(final Context context, final D descriptor) {
+        super(context, descriptor);
+        mBitmap = getBitmapPool().createOrReuseBitmap(
+                mDescriptor.desiredWidth, mDescriptor.desiredHeight);
+        mCanvas = new Canvas(mBitmap);
+        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    }
+
+    @Override
+    protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTask) {
+        final List<? extends ImageRequestDescriptor> descriptors =
+                mDescriptor.getChildRequestDescriptors();
+        final List<RectF> targetRects = mDescriptor.getChildRequestTargetRects();
+        Assert.equals(descriptors.size(), targetRects.size());
+        Assert.isTrue(descriptors.size() > 1);
+
+        for (int i = 0; i < descriptors.size(); i++) {
+            final MediaRequest<ImageResource> request =
+                    descriptors.get(i).buildSyncMediaRequest(mContext);
+            // Synchronously request the child image.
+            final ImageResource resource =
+                    MediaResourceManager.get().requestMediaResourceSync(request);
+            if (resource != null) {
+                try {
+                    final RectF avatarDestOnGroup = targetRects.get(i);
+
+                    // Draw the bitmap into a smaller size with a circle mask.
+                    final Bitmap resourceBitmap = resource.getBitmap();
+                    final RectF resourceRect = new RectF(
+                            0, 0, resourceBitmap.getWidth(), resourceBitmap.getHeight());
+                    final Bitmap smallCircleBitmap = getBitmapPool().createOrReuseBitmap(
+                            Math.round(avatarDestOnGroup.width()),
+                            Math.round(avatarDestOnGroup.height()));
+                    final RectF smallCircleRect = new RectF(
+                            0, 0, smallCircleBitmap.getWidth(), smallCircleBitmap.getHeight());
+                    final Canvas smallCircleCanvas = new Canvas(smallCircleBitmap);
+                    ImageUtils.drawBitmapWithCircleOnCanvas(resource.getBitmap(), smallCircleCanvas,
+                            resourceRect, smallCircleRect, null /* bitmapPaint */,
+                            false /* fillBackground */,
+                            ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                            ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+                    final Matrix matrix = new Matrix();
+                    matrix.setRectToRect(smallCircleRect, avatarDestOnGroup,
+                            Matrix.ScaleToFit.FILL);
+                    mCanvas.drawBitmap(smallCircleBitmap, matrix, mPaint);
+                } finally {
+                    resource.release();
+                }
+            }
+        }
+
+        return new DecodedImageResource(getKey(), mBitmap, ExifInterface.ORIENTATION_NORMAL);
+    }
+
+    @Override
+    public int getCacheId() {
+        return BugleMediaCacheManager.AVATAR_IMAGE_CACHE;
+    }
+
+    @Override
+    protected InputStream getInputStreamForResource() throws FileNotFoundException {
+        throw new IllegalStateException("Composite image request doesn't support input stream!");
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/CompositeImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/CompositeImageRequestDescriptor.java
new file mode 100644
index 0000000..071130e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/CompositeImageRequestDescriptor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.RectF;
+
+import com.google.common.base.Joiner;
+
+import java.util.List;
+
+public abstract class CompositeImageRequestDescriptor extends ImageRequestDescriptor {
+    protected final List<? extends ImageRequestDescriptor> mDescriptors;
+    private final String mKey;
+
+    public CompositeImageRequestDescriptor(final List<? extends ImageRequestDescriptor> descriptors,
+            final int desiredWidth, final int desiredHeight) {
+        super(desiredWidth, desiredHeight);
+        mDescriptors = descriptors;
+
+        final String[] keyParts = new String[descriptors.size()];
+        for (int i = 0; i < descriptors.size(); i++) {
+            keyParts[i] = descriptors.get(i).getKey();
+        }
+        mKey = Joiner.on(",").skipNulls().join(keyParts);
+    }
+
+    /**
+     * Gets a key that uniquely identify all the underlying image resource to be loaded (e.g. Uri or
+     * file path).
+     */
+    @Override
+    public String getKey() {
+        return mKey;
+    }
+
+    public List<? extends ImageRequestDescriptor> getChildRequestDescriptors(){
+        return mDescriptors;
+    }
+
+    public abstract List<RectF> getChildRequestTargetRects();
+    public abstract CompositeImageRequest<?> buildBatchImageRequest(final Context context);
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(final Context context) {
+        return buildBatchImageRequest(context);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/CustomVCardEntry.java b/src/com/android/messaging/datamodel/media/CustomVCardEntry.java
new file mode 100644
index 0000000..965259f
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/CustomVCardEntry.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.accounts.Account;
+import androidx.collection.ArrayMap;
+
+import com.android.vcard.VCardEntry;
+import com.android.vcard.VCardProperty;
+
+import java.util.Map;
+
+/**
+ * Class which extends VCardEntry to add support for unknown properties.  Currently there is a TODO
+ * to add this in the VCardEntry code, but we have to extend it to add the needed support
+ */
+public class CustomVCardEntry extends VCardEntry {
+    // List of properties keyed by their name for easy lookup
+    private final Map<String, VCardProperty> mAllProperties;
+
+    public CustomVCardEntry(int vCardType, Account account) {
+        super(vCardType, account);
+        mAllProperties = new ArrayMap<String, VCardProperty>();
+    }
+
+    @Override
+    public void addProperty(VCardProperty property) {
+        super.addProperty(property);
+        mAllProperties.put(property.getName(), property);
+    }
+
+    public VCardProperty getProperty(String name) {
+        return mAllProperties.get(name);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/CustomVCardEntryConstructor.java b/src/com/android/messaging/datamodel/media/CustomVCardEntryConstructor.java
new file mode 100644
index 0000000..06b10a3
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/CustomVCardEntryConstructor.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.accounts.Account;
+import com.android.vcard.VCardConfig;
+import com.android.vcard.VCardInterpreter;
+import com.android.vcard.VCardProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CustomVCardEntryConstructor implements VCardInterpreter {
+
+    public interface EntryHandler {
+        /**
+         * Called when the parsing started.
+         */
+        public void onStart();
+
+        /**
+         * The method called when one vCard entry is created. Children come before their parent in
+         * nested vCard files.
+         *
+         * e.g.
+         * In the following vCard, the entry for "entry2" comes before one for "entry1".
+         * <code>
+         * BEGIN:VCARD
+         * N:entry1
+         * BEGIN:VCARD
+         * N:entry2
+         * END:VCARD
+         * END:VCARD
+         * </code>
+         */
+        public void onEntryCreated(final CustomVCardEntry entry);
+
+        /**
+         * Called when the parsing ended.
+         * Able to be use this method for showing performance log, etc.
+         */
+        public void onEnd();
+    }
+
+    /**
+     * Represents current stack of VCardEntry. Used to support nested vCard (vCard 2.1).
+     */
+    private final List<CustomVCardEntry> mEntryStack = new ArrayList<CustomVCardEntry>();
+    private CustomVCardEntry mCurrentEntry;
+
+    private final int mVCardType;
+    private final Account mAccount;
+
+    private final List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>();
+
+    public CustomVCardEntryConstructor() {
+        this(VCardConfig.VCARD_TYPE_V21_GENERIC, null);
+    }
+
+    public CustomVCardEntryConstructor(final int vcardType) {
+        this(vcardType, null);
+    }
+
+    public CustomVCardEntryConstructor(final int vcardType, final Account account) {
+        mVCardType = vcardType;
+        mAccount = account;
+    }
+
+    public void addEntryHandler(EntryHandler entryHandler) {
+        mEntryHandlers.add(entryHandler);
+    }
+
+    @Override
+    public void onVCardStarted() {
+        for (EntryHandler entryHandler : mEntryHandlers) {
+            entryHandler.onStart();
+        }
+    }
+
+    @Override
+    public void onVCardEnded() {
+        for (EntryHandler entryHandler : mEntryHandlers) {
+            entryHandler.onEnd();
+        }
+    }
+
+    public void clear() {
+        mCurrentEntry = null;
+        mEntryStack.clear();
+    }
+
+    @Override
+    public void onEntryStarted() {
+        mCurrentEntry = new CustomVCardEntry(mVCardType, mAccount);
+        mEntryStack.add(mCurrentEntry);
+    }
+
+    @Override
+    public void onEntryEnded() {
+        mCurrentEntry.consolidateFields();
+        for (EntryHandler entryHandler : mEntryHandlers) {
+            entryHandler.onEntryCreated(mCurrentEntry);
+        }
+
+        final int size = mEntryStack.size();
+        if (size > 1) {
+            CustomVCardEntry parent = mEntryStack.get(size - 2);
+            parent.addChild(mCurrentEntry);
+            mCurrentEntry = parent;
+        } else {
+            mCurrentEntry = null;
+        }
+        mEntryStack.remove(size - 1);
+    }
+
+    @Override
+    public void onPropertyCreated(VCardProperty property) {
+        mCurrentEntry.addProperty(property);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/DecodedImageResource.java b/src/com/android/messaging/datamodel/media/DecodedImageResource.java
new file mode 100644
index 0000000..3627ba4
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/DecodedImageResource.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+
+import com.android.messaging.ui.OrientedBitmapDrawable;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+import java.util.List;
+
+
+/**
+ * Container class for holding a bitmap resource used by the MediaResourceManager. This resource
+ * can both be cached (albeit not very storage-efficiently) and directly used by the UI.
+ */
+public class DecodedImageResource extends ImageResource {
+    private static final int BITMAP_QUALITY = 100;
+    private static final int COMPRESS_QUALITY = 50;
+
+    private Bitmap mBitmap;
+    private final int mOrientation;
+    private boolean mCacheable = true;
+
+    public DecodedImageResource(final String key, final Bitmap bitmap, int orientation) {
+        super(key, orientation);
+        mBitmap = bitmap;
+        mOrientation = orientation;
+    }
+
+    /**
+     * Gets the contained bitmap.
+     */
+    @Override
+    public Bitmap getBitmap() {
+        acquireLock();
+        try {
+            return mBitmap;
+        } finally {
+            releaseLock();
+        }
+    }
+
+    /**
+     * Attempt to reuse the bitmap in the image resource and repurpose it for something else.
+     * After this, the image resource will relinquish ownership on the bitmap resource so that
+     * it doesn't try to recycle it when getting closed.
+     */
+    @Override
+    public Bitmap reuseBitmap() {
+        acquireLock();
+        try {
+            assertSingularRefCount();
+            final Bitmap retBitmap = mBitmap;
+            mBitmap = null;
+            return retBitmap;
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    public boolean supportsBitmapReuse() {
+        return true;
+    }
+
+    @Override
+    public byte[] getBytes() {
+        acquireLock();
+        try {
+            return ImageUtils.bitmapToBytes(mBitmap, BITMAP_QUALITY);
+        } catch (final Exception e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error trying to get the bitmap bytes " + e);
+        } finally {
+            releaseLock();
+        }
+        return null;
+    }
+
+    /**
+     * Gets the orientation of the image as one of the ExifInterface.ORIENTATION_* constants
+     */
+    @Override
+    public int getOrientation() {
+        return mOrientation;
+    }
+
+    @Override
+    public int getMediaSize() {
+        acquireLock();
+        try {
+            Assert.notNull(mBitmap);
+            if (OsUtil.isAtLeastKLP()) {
+                return mBitmap.getAllocationByteCount();
+            } else {
+                return mBitmap.getRowBytes() * mBitmap.getHeight();
+            }
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    protected void close() {
+        acquireLock();
+        try {
+            if (mBitmap != null) {
+                mBitmap.recycle();
+                mBitmap = null;
+            }
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    public Drawable getDrawable(Resources resources) {
+        acquireLock();
+        try {
+            Assert.notNull(mBitmap);
+            return OrientedBitmapDrawable.create(getOrientation(), resources, mBitmap);
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    boolean isCacheable() {
+        return mCacheable;
+    }
+
+    public void setCacheable(final boolean cacheable) {
+        mCacheable = cacheable;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    MediaRequest<? extends RefCountedMediaResource> getMediaEncodingRequest(
+            final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
+        Assert.isFalse(isEncoded());
+        if (getBitmap().hasAlpha()) {
+            // We can't compress images with alpha, as JPEG encoding doesn't support this.
+            return null;
+        }
+        return new EncodeImageRequest((MediaRequest<ImageResource>) originalRequest);
+    }
+
+    /**
+     * A MediaRequest that encodes the contained image resource.
+     */
+    private class EncodeImageRequest implements MediaRequest<ImageResource> {
+        private final MediaRequest<ImageResource> mOriginalImageRequest;
+
+        public EncodeImageRequest(MediaRequest<ImageResource> originalImageRequest) {
+            mOriginalImageRequest = originalImageRequest;
+            // Hold a ref onto the encoded resource before the request finishes.
+            DecodedImageResource.this.addRef();
+        }
+
+        @Override
+        public String getKey() {
+            return DecodedImageResource.this.getKey();
+        }
+
+        @Override
+        @DoesNotRunOnMainThread
+        public ImageResource loadMediaBlocking(List<MediaRequest<ImageResource>> chainedRequests)
+                throws Exception {
+            Assert.isNotMainThread();
+            acquireLock();
+            Bitmap scaledBitmap = null;
+            try {
+                Bitmap bitmap = getBitmap();
+                Assert.isFalse(bitmap.hasAlpha());
+                final int bitmapWidth = bitmap.getWidth();
+                final int bitmapHeight = bitmap.getHeight();
+                // The original bitmap was loaded using sub-sampling which was fast in terms of
+                // loading speed, but not optimized for caching, encoding and rendering (since
+                // bitmap resizing to fit the UI image views happens on the UI thread and should
+                // be avoided if possible). Therefore, try to resize the bitmap to the exact desired
+                // size before compressing it.
+                if (bitmapWidth > 0 && bitmapHeight > 0 &&
+                        mOriginalImageRequest instanceof ImageRequest<?>) {
+                    final ImageRequestDescriptor descriptor =
+                            ((ImageRequest<?>) mOriginalImageRequest).getDescriptor();
+                    final float targetScale = Math.max(
+                            (float) descriptor.desiredWidth / bitmapWidth,
+                            (float) descriptor.desiredHeight / bitmapHeight);
+                    final int targetWidth = (int) (bitmapWidth * targetScale);
+                    final int targetHeight = (int) (bitmapHeight * targetScale);
+                    // Only try to scale down the image to the desired size.
+                    if (targetScale < 1.0f && targetWidth > 0 && targetHeight > 0 &&
+                            targetWidth != bitmapWidth && targetHeight != bitmapHeight) {
+                        scaledBitmap = bitmap =
+                                Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
+                    }
+                }
+                byte[] encodedBytes = ImageUtils.bitmapToBytes(bitmap, COMPRESS_QUALITY);
+                return new EncodedImageResource(getKey(), encodedBytes, getOrientation());
+            } catch (Exception ex) {
+                // Something went wrong during bitmap compression, fall back to just using the
+                // original bitmap.
+                LogUtil.e(LogUtil.BUGLE_IMAGE_TAG, "Error compressing bitmap", ex);
+                return DecodedImageResource.this;
+            } finally {
+                if (scaledBitmap != null && scaledBitmap != getBitmap()) {
+                    scaledBitmap.recycle();
+                    scaledBitmap = null;
+                }
+                releaseLock();
+                release();
+            }
+        }
+
+        @Override
+        public MediaCache<ImageResource> getMediaCache() {
+            return mOriginalImageRequest.getMediaCache();
+        }
+
+        @Override
+        public int getCacheId() {
+            return mOriginalImageRequest.getCacheId();
+        }
+
+        @Override
+        public int getRequestType() {
+            return REQUEST_ENCODE_MEDIA;
+        }
+
+        @Override
+        public MediaRequestDescriptor<ImageResource> getDescriptor() {
+            return mOriginalImageRequest.getDescriptor();
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/EncodedImageResource.java b/src/com/android/messaging/datamodel/media/EncodedImageResource.java
new file mode 100644
index 0000000..0bc94e5
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/EncodedImageResource.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A cache-facing image resource that's much more compact than the raw Bitmap objects stored in
+ * {@link com.android.messaging.datamodel.media.DecodedImageResource}.
+ *
+ * This resource is created from a regular Bitmap-based ImageResource before being pushed to
+ * {@link com.android.messaging.datamodel.media.MediaCache}, if the image request
+ * allows for resource encoding/compression.
+ *
+ * During resource retrieval on cache hit,
+ * {@link #getMediaDecodingRequest(MediaRequest)} is invoked to create a async
+ * decode task, which decodes the compressed byte array back to a regular image resource to
+ * be consumed by the UI.
+ */
+public class EncodedImageResource extends ImageResource {
+    private final byte[] mImageBytes;
+
+    public EncodedImageResource(String key, byte[] imageBytes, int orientation) {
+        super(key, orientation);
+        mImageBytes = imageBytes;
+    }
+
+    @Override
+    @DoesNotRunOnMainThread
+    public Bitmap getBitmap() {
+        acquireLock();
+        try {
+            // This should only be called during the decode request.
+            Assert.isNotMainThread();
+            return BitmapFactory.decodeByteArray(mImageBytes, 0, mImageBytes.length);
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    public byte[] getBytes() {
+        acquireLock();
+        try {
+            return Arrays.copyOf(mImageBytes, mImageBytes.length);
+        } finally {
+            releaseLock();
+        }
+    }
+
+    @Override
+    public Bitmap reuseBitmap() {
+        return null;
+    }
+
+    @Override
+    public boolean supportsBitmapReuse() {
+        return false;
+    }
+
+    @Override
+    public int getMediaSize() {
+        return mImageBytes.length;
+    }
+
+    @Override
+    protected void close() {
+    }
+
+    @Override
+    public Drawable getDrawable(Resources resources) {
+        return null;
+    }
+
+    @Override
+    boolean isEncoded() {
+        return true;
+    }
+
+    @Override
+    MediaRequest<? extends RefCountedMediaResource> getMediaDecodingRequest(
+            final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
+        Assert.isTrue(isEncoded());
+        return new DecodeImageRequest();
+    }
+
+    /**
+     * A MediaRequest that decodes the encoded image resource. This class is chained to the
+     * original media request that requested the image, so it inherits the listener and
+     * properties such as binding.
+     */
+    private class DecodeImageRequest implements MediaRequest<ImageResource> {
+        public DecodeImageRequest() {
+            // Hold a ref onto the encoded resource before the request finishes.
+            addRef();
+        }
+
+        @Override
+        public String getKey() {
+            return EncodedImageResource.this.getKey();
+        }
+
+        @Override
+        @DoesNotRunOnMainThread
+        public ImageResource loadMediaBlocking(List<MediaRequest<ImageResource>> chainedTask)
+                throws Exception {
+            Assert.isNotMainThread();
+            acquireLock();
+            try {
+                final Bitmap decodedBitmap = BitmapFactory.decodeByteArray(mImageBytes, 0,
+                        mImageBytes.length);
+                return new DecodedImageResource(getKey(), decodedBitmap, getOrientation());
+            } finally {
+                releaseLock();
+                release();
+            }
+        }
+
+        @Override
+        public MediaCache<ImageResource> getMediaCache() {
+            // Decoded resource is non-cachable, it's for UI consumption only (for now at least)
+            return null;
+        }
+
+        @Override
+        public int getCacheId() {
+            return 0;
+        }
+
+        @Override
+        public int getRequestType() {
+            return REQUEST_DECODE_MEDIA;
+        }
+
+        @Override
+        public MediaRequestDescriptor<ImageResource> getDescriptor() {
+            return null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/FileImageRequest.java b/src/com/android/messaging/datamodel/media/FileImageRequest.java
new file mode 100644
index 0000000..31c053a
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/FileImageRequest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.ExifInterface;
+
+import com.android.messaging.datamodel.media.PoolableImageCache.ReusableImageResourcePool;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+
+/**
+ * Serves file system based image requests. Since file paths can be expressed in Uri form, this
+ * extends regular UriImageRequest but performs additional optimizations such as loading thumbnails
+ * directly from Exif information.
+ */
+public class FileImageRequest extends UriImageRequest {
+    private final String mPath;
+    private final boolean mCanUseThumbnail;
+
+    public FileImageRequest(final Context context,
+            final FileImageRequestDescriptor descriptor) {
+        super(context, descriptor);
+        mPath = descriptor.path;
+        mCanUseThumbnail = descriptor.canUseThumbnail;
+    }
+
+    @Override
+    protected Bitmap loadBitmapInternal()
+            throws IOException {
+        // Before using the FileInputStream, check if the Exif has a thumbnail that we can use.
+        if (mCanUseThumbnail) {
+            byte[] thumbnail = null;
+            try {
+                final ExifInterface exif = new ExifInterface(mPath);
+                if (exif.hasThumbnail()) {
+                    thumbnail = exif.getThumbnail();
+                }
+            } catch (final IOException e) {
+                // Nothing to do
+            }
+
+            if (thumbnail != null) {
+                final BitmapFactory.Options options = PoolableImageCache.getBitmapOptionsForPool(
+                        false /* scaled */, 0 /* inputDensity */, 0 /* targetDensity */);
+                // First, check dimensions of the bitmap.
+                options.inJustDecodeBounds = true;
+                BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length, options);
+
+                // Calculate inSampleSize
+                options.inSampleSize = ImageUtils.get().calculateInSampleSize(options,
+                        mDescriptor.desiredWidth, mDescriptor.desiredHeight);
+
+                options.inJustDecodeBounds = false;
+
+                // Actually decode the bitmap, optionally using the bitmap pool.
+                try {
+                    // Get the orientation. We should be able to get the orientation from
+                    // the thumbnail itself but at least on some phones, the thumbnail
+                    // doesn't have an orientation tag. So use the outer image's orientation
+                    // tag and hope for the best.
+                    mOrientation = ImageUtils.getOrientation(getInputStreamForResource());
+                    if (com.android.messaging.util.exif.ExifInterface.
+                            getOrientationParams(mOrientation).invertDimensions) {
+                        mDescriptor.updateSourceDimensions(options.outHeight, options.outWidth);
+                    } else {
+                        mDescriptor.updateSourceDimensions(options.outWidth, options.outHeight);
+                    }
+                    final ReusableImageResourcePool bitmapPool = getBitmapPool();
+                    if (bitmapPool == null) {
+                        return BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length,
+                                options);
+                    } else {
+                        final int sampledWidth = options.outWidth / options.inSampleSize;
+                        final int sampledHeight = options.outHeight / options.inSampleSize;
+                        return bitmapPool.decodeByteArray(thumbnail, options, sampledWidth,
+                                sampledHeight);
+                    }
+                } catch (IOException ex) {
+                    // If the thumbnail is broken due to IOException, this will
+                    // fall back to default bitmap loading.
+                    LogUtil.e(LogUtil.BUGLE_IMAGE_TAG, "FileImageRequest: failed to load " +
+                            "thumbnail from Exif", ex);
+                }
+            }
+        }
+
+        // Fall back to default InputStream-based loading if no thumbnails could be retrieved.
+        return super.loadBitmapInternal();
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/FileImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/FileImageRequestDescriptor.java
new file mode 100644
index 0000000..00105f5
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/FileImageRequestDescriptor.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * Holds image request info about file system based image resource.
+ */
+public class FileImageRequestDescriptor extends UriImageRequestDescriptor {
+    public final String path;
+
+    // Can we use the thumbnail image from Exif data?
+    public final boolean canUseThumbnail;
+
+    /**
+     * Convenience constructor for when the image file's dimensions are not known.
+     */
+    public FileImageRequestDescriptor(final String path, final int desiredWidth,
+            final int desiredHeight, final boolean canUseThumbnail, final boolean canCompress,
+            final boolean isStatic) {
+        this(path, desiredWidth, desiredHeight, FileImageRequest.UNSPECIFIED_SIZE,
+                FileImageRequest.UNSPECIFIED_SIZE, canUseThumbnail, canCompress, isStatic);
+    }
+
+    /**
+     * Creates a new file image request with this descriptor. Oftentimes image file metadata
+     * has information such as the size of the image. Provide these metrics if they are known.
+     */
+    public FileImageRequestDescriptor(final String path, final int desiredWidth,
+            final int desiredHeight, final int sourceWidth, final int sourceHeight,
+            final boolean canUseThumbnail, final boolean canCompress, final boolean isStatic) {
+        super(UriUtil.getUriForResourceFile(path), desiredWidth, desiredHeight, sourceWidth,
+                sourceHeight, canCompress,  isStatic, false /* cropToCircle */,
+                ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+        this.path = path;
+        this.canUseThumbnail = canUseThumbnail;
+    }
+
+    @Override
+    public String getKey() {
+        final String prefixKey = super.getKey();
+        return prefixKey == null ? null : new StringBuilder(prefixKey).append(KEY_PART_DELIMITER)
+                .append(canUseThumbnail).toString();
+    }
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(final Context context) {
+        return new FileImageRequest(context, this);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/GifImageResource.java b/src/com/android/messaging/datamodel/media/GifImageResource.java
new file mode 100644
index 0000000..cbea1ee
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/GifImageResource.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.media.ExifInterface;
+import android.support.rastermill.FrameSequence;
+import android.support.rastermill.FrameSequenceDrawable;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class GifImageResource extends ImageResource {
+    private FrameSequence mFrameSequence;
+
+    public GifImageResource(String key, FrameSequence frameSequence) {
+        // GIF does not support exif tags
+        super(key, ExifInterface.ORIENTATION_NORMAL);
+        mFrameSequence = frameSequence;
+    }
+
+    public static GifImageResource createGifImageResource(String key, InputStream inputStream) {
+        final FrameSequence frameSequence;
+        try {
+            frameSequence = FrameSequence.decodeStream(inputStream);
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                // Nothing to do if we fail closing the stream
+            }
+        }
+        if (frameSequence == null) {
+            return null;
+        }
+        return new GifImageResource(key, frameSequence);
+    }
+
+    @Override
+    public Drawable getDrawable(Resources resources) {
+        try {
+            return new FrameSequenceDrawable(mFrameSequence);
+        } catch (final Throwable t) {
+            // Malicious gif images can make the platform throw different kind of throwables, such
+            // as OutOfMemoryError and NullPointerException. Catch them all.
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error getting drawable for GIF", t);
+            return null;
+        }
+    }
+
+    @Override
+    public Bitmap getBitmap() {
+        Assert.fail("GetBitmap() should never be called on a gif.");
+        return null;
+    }
+
+    @Override
+    public byte[] getBytes() {
+        Assert.fail("GetBytes() should never be called on a gif.");
+        return null;
+    }
+
+    @Override
+    public Bitmap reuseBitmap() {
+        return null;
+    }
+
+    @Override
+    public boolean supportsBitmapReuse() {
+        // FrameSequenceDrawable a.) takes two bitmaps and thus does not fit into the current
+        // bitmap pool architecture b.) will rarely use bitmaps from one FrameSequenceDrawable to
+        // the next that are the same sizes since they are used by attachments.
+        return false;
+    }
+
+    @Override
+    public int getMediaSize() {
+        Assert.fail("GifImageResource should not be used by a media cache");
+        // Only used by the media cache, which this does not use.
+        return 0;
+    }
+
+    @Override
+    public boolean isCacheable() {
+        return false;
+    }
+
+    @Override
+    protected void close() {
+        acquireLock();
+        try {
+            if (mFrameSequence != null) {
+                mFrameSequence = null;
+            }
+        } finally {
+            releaseLock();
+        }
+    }
+
+}
diff --git a/src/com/android/messaging/datamodel/media/ImageRequest.java b/src/com/android/messaging/datamodel/media/ImageRequest.java
new file mode 100644
index 0000000..ab8880d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/ImageRequest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.media.PoolableImageCache.ReusableImageResourcePool;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.exif.ExifInterface;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Base class that serves an image request for resolving, retrieving and decoding bitmap resources.
+ *
+ * Subclasses may choose to load images from different medium, such as from the file system or
+ * from the local content resolver, by overriding the abstract getInputStreamForResource() method.
+ */
+public abstract class ImageRequest<D extends ImageRequestDescriptor>
+        implements MediaRequest<ImageResource> {
+    public static final int UNSPECIFIED_SIZE = MessagePartData.UNSPECIFIED_SIZE;
+
+    protected final Context mContext;
+    protected final D mDescriptor;
+    protected int mOrientation;
+
+    /**
+     * Creates a new image request with the given descriptor.
+     */
+    public ImageRequest(final Context context, final D descriptor) {
+        mContext = context;
+        mDescriptor = descriptor;
+    }
+
+    /**
+     * Gets a key that uniquely identify the underlying image resource to be loaded (e.g. Uri or
+     * file path).
+     */
+    @Override
+    public String getKey() {
+        return mDescriptor.getKey();
+    }
+
+    /**
+     * Returns the image request descriptor attached to this request.
+     */
+    @Override
+    public D getDescriptor() {
+        return mDescriptor;
+    }
+
+    @Override
+    public int getRequestType() {
+        return MediaRequest.REQUEST_LOAD_MEDIA;
+    }
+
+    /**
+     * Allows sub classes to specify that they want us to call getBitmapForResource rather than
+     * getInputStreamForResource
+     */
+    protected boolean hasBitmapObject() {
+        return false;
+    }
+
+    protected Bitmap getBitmapForResource() throws IOException {
+        return null;
+    }
+
+    /**
+     * Retrieves an input stream from which image resource could be loaded.
+     * @throws FileNotFoundException
+     */
+    protected abstract InputStream getInputStreamForResource() throws FileNotFoundException;
+
+    /**
+     * Loads the image resource. This method is final; to override the media loading behavior
+     * the subclass should override {@link #loadMediaInternal(List)}
+     */
+    @Override
+    public final ImageResource loadMediaBlocking(List<MediaRequest<ImageResource>> chainedTask)
+            throws IOException {
+        Assert.isNotMainThread();
+        final ImageResource loadedResource = loadMediaInternal(chainedTask);
+        return postProcessOnBitmapResourceLoaded(loadedResource);
+    }
+
+    protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTask)
+            throws IOException {
+        if (!mDescriptor.isStatic() && isGif()) {
+            final GifImageResource gifImageResource =
+                    GifImageResource.createGifImageResource(getKey(), getInputStreamForResource());
+            if (gifImageResource == null) {
+                throw new RuntimeException("Error decoding gif");
+            }
+            return gifImageResource;
+        } else {
+            final Bitmap loadedBitmap = loadBitmapInternal();
+            if (loadedBitmap == null) {
+                throw new RuntimeException("failed decoding bitmap");
+            }
+            return new DecodedImageResource(getKey(), loadedBitmap, mOrientation);
+        }
+    }
+
+    protected boolean isGif() throws FileNotFoundException {
+        return ImageUtils.isGif(getInputStreamForResource());
+    }
+
+    /**
+     * The internal routine for loading the image. The caller may optionally provide the width
+     * and height of the source image if known so that we don't need to manually decode those.
+     */
+    protected Bitmap loadBitmapInternal() throws IOException {
+
+        final boolean unknownSize = mDescriptor.sourceWidth == UNSPECIFIED_SIZE ||
+                mDescriptor.sourceHeight == UNSPECIFIED_SIZE;
+
+        // If the ImageRequest has a Bitmap object rather than a stream, there's little to do here
+        if (hasBitmapObject()) {
+            final Bitmap bitmap = getBitmapForResource();
+            if (bitmap != null && unknownSize) {
+                mDescriptor.updateSourceDimensions(bitmap.getWidth(), bitmap.getHeight());
+            }
+            return bitmap;
+        }
+
+        mOrientation = ImageUtils.getOrientation(getInputStreamForResource());
+
+        final BitmapFactory.Options options = PoolableImageCache.getBitmapOptionsForPool(
+                false /* scaled */, 0 /* inputDensity */, 0 /* targetDensity */);
+        // First, check dimensions of the bitmap if not already known.
+        if (unknownSize) {
+            final InputStream inputStream = getInputStreamForResource();
+            if (inputStream != null) {
+                try {
+                    options.inJustDecodeBounds = true;
+                    BitmapFactory.decodeStream(inputStream, null, options);
+                    // This is called when dimensions of image were unknown to allow db update
+                    if (ExifInterface.getOrientationParams(mOrientation).invertDimensions) {
+                        mDescriptor.updateSourceDimensions(options.outHeight, options.outWidth);
+                    } else {
+                        mDescriptor.updateSourceDimensions(options.outWidth, options.outHeight);
+                    }
+                } finally {
+                    inputStream.close();
+                }
+            } else {
+                throw new FileNotFoundException();
+            }
+        } else {
+            options.outWidth = mDescriptor.sourceWidth;
+            options.outHeight = mDescriptor.sourceHeight;
+        }
+
+        // Calculate inSampleSize
+        options.inSampleSize = ImageUtils.get().calculateInSampleSize(options,
+                mDescriptor.desiredWidth, mDescriptor.desiredHeight);
+        Assert.isTrue(options.inSampleSize > 0);
+
+        // Reopen the input stream and actually decode the bitmap. The initial
+        // BitmapFactory.decodeStream() reads the header portion of the bitmap stream and leave
+        // the input stream at the last read position. Since this input stream doesn't support
+        // mark() and reset(), the only viable way to reload the input stream is to re-open it.
+        // Alternatively, we could decode the bitmap into a byte array first and act on the byte
+        // array, but that also means the entire bitmap (for example a 10MB image from the gallery)
+        // without downsampling will have to be loaded into memory up front, which we don't want
+        // as it gives a much bigger possibility of OOM when handling big images. Therefore, the
+        // solution here is to close and reopen the bitmap input stream.
+        // For inline images the size is cached in DB and this hit is only taken once per image
+        final InputStream inputStream = getInputStreamForResource();
+        if (inputStream != null) {
+            try {
+                options.inJustDecodeBounds = false;
+
+                // Actually decode the bitmap, optionally using the bitmap pool.
+                final ReusableImageResourcePool bitmapPool = getBitmapPool();
+                if (bitmapPool == null) {
+                    return BitmapFactory.decodeStream(inputStream, null, options);
+                } else {
+                    final int sampledWidth = (options.outWidth + options.inSampleSize - 1) /
+                            options.inSampleSize;
+                    final int sampledHeight = (options.outHeight + options.inSampleSize - 1) /
+                            options.inSampleSize;
+                    return bitmapPool.decodeSampledBitmapFromInputStream(
+                            inputStream, options, sampledWidth, sampledHeight);
+                }
+            } finally {
+                inputStream.close();
+            }
+        } else {
+            throw new FileNotFoundException();
+        }
+    }
+
+    private ImageResource postProcessOnBitmapResourceLoaded(final ImageResource loadedResource) {
+        if (mDescriptor.cropToCircle && loadedResource instanceof DecodedImageResource) {
+            final int width = mDescriptor.desiredWidth;
+            final int height = mDescriptor.desiredHeight;
+            final Bitmap sourceBitmap = loadedResource.getBitmap();
+            final Bitmap targetBitmap = getBitmapPool().createOrReuseBitmap(width, height);
+            final RectF dest = new RectF(0, 0, width, height);
+            final RectF source = new RectF(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight());
+            final int backgroundColor = mDescriptor.circleBackgroundColor;
+            final int strokeColor = mDescriptor.circleStrokeColor;
+            ImageUtils.drawBitmapWithCircleOnCanvas(sourceBitmap, new Canvas(targetBitmap), source,
+                    dest, null, backgroundColor == 0 ? false : true /* fillBackground */,
+                            backgroundColor, strokeColor);
+            return new DecodedImageResource(getKey(), targetBitmap,
+                    loadedResource.getOrientation());
+        }
+        return loadedResource;
+    }
+
+    /**
+     * Returns the bitmap pool for this image request.
+     */
+    protected ReusableImageResourcePool getBitmapPool() {
+        return MediaCacheManager.get().getOrCreateBitmapPoolForCache(getCacheId());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public MediaCache<ImageResource> getMediaCache() {
+        return (MediaCache<ImageResource>) MediaCacheManager.get().getOrCreateMediaCacheById(
+                getCacheId());
+    }
+
+    /**
+     * Returns the cache id. Subclasses may override this to use a different cache.
+     */
+    @Override
+    public int getCacheId() {
+        return BugleMediaCacheManager.DEFAULT_IMAGE_CACHE;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/ImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/ImageRequestDescriptor.java
new file mode 100644
index 0000000..20cb9af
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/ImageRequestDescriptor.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+
+import com.android.messaging.util.Assert;
+
+/**
+ * The base ImageRequest descriptor that describes the requirement of the requested image
+ * resource, including the desired size. It holds request info that will be consumed by
+ * ImageRequest instances. Subclasses of ImageRequest are expected to take
+ * more descriptions such as content URI or file path.
+ */
+public abstract class ImageRequestDescriptor extends MediaRequestDescriptor<ImageResource> {
+    /** Desired size for the image (if known). This is used for bitmap downsampling */
+    public final int desiredWidth;
+    public final int desiredHeight;
+
+    /** Source size of the image (if known). This is used so that we don't have to manually decode
+     *  the metrics from the image resource */
+    public final int sourceWidth;
+    public final int sourceHeight;
+
+    /**
+     * A static image resource is required, even if the image format supports animation (like Gif).
+     */
+    public final boolean isStatic;
+
+    /**
+     * The loaded image will be cropped to circular shape.
+     */
+    public final boolean cropToCircle;
+
+    /**
+     * The loaded image will be cropped to circular shape with the background color.
+     */
+    public final int circleBackgroundColor;
+
+    /**
+     * The loaded image will be cropped to circular shape with a stroke color.
+     */
+    public final int circleStrokeColor;
+
+    protected static final char KEY_PART_DELIMITER = '|';
+
+    /**
+     * Creates a new image request with unspecified width and height. In this case, the full
+     * bitmap is loaded and decoded, so unless you are sure that the image will be of
+     * reasonable size, you should consider limiting at least one of the two dimensions
+     * (for example, limiting the image width to the width of the ImageView container).
+     */
+    public ImageRequestDescriptor() {
+        this(ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE,
+                ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE, false, false, 0, 0);
+    }
+
+    public ImageRequestDescriptor(final int desiredWidth, final int desiredHeight) {
+        this(desiredWidth, desiredHeight,
+                ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE, false, false, 0, 0);
+    }
+
+    public ImageRequestDescriptor(final int desiredWidth,
+            final int desiredHeight, final int sourceWidth, final int sourceHeight,
+            final boolean isStatic, final boolean cropToCircle, final int circleBackgroundColor,
+            int circleStrokeColor) {
+        Assert.isTrue(desiredWidth == ImageRequest.UNSPECIFIED_SIZE || desiredWidth > 0);
+        Assert.isTrue(desiredHeight == ImageRequest.UNSPECIFIED_SIZE || desiredHeight > 0);
+        Assert.isTrue(sourceWidth == ImageRequest.UNSPECIFIED_SIZE || sourceWidth > 0);
+        Assert.isTrue(sourceHeight == ImageRequest.UNSPECIFIED_SIZE || sourceHeight > 0);
+        this.desiredWidth = desiredWidth;
+        this.desiredHeight = desiredHeight;
+        this.sourceWidth = sourceWidth;
+        this.sourceHeight = sourceHeight;
+        this.isStatic = isStatic;
+        this.cropToCircle = cropToCircle;
+        this.circleBackgroundColor = circleBackgroundColor;
+        this.circleStrokeColor = circleStrokeColor;
+    }
+
+    public String getKey() {
+        return new StringBuilder()
+                .append(desiredWidth).append(KEY_PART_DELIMITER)
+                .append(desiredHeight).append(KEY_PART_DELIMITER)
+                .append(String.valueOf(cropToCircle)).append(KEY_PART_DELIMITER)
+                .append(String.valueOf(circleBackgroundColor)).append(KEY_PART_DELIMITER)
+                .append(String.valueOf(isStatic)).toString();
+    }
+
+    public boolean isStatic() {
+        return isStatic;
+    }
+
+    @Override
+    public abstract MediaRequest<ImageResource> buildSyncMediaRequest(Context context);
+
+    // Called once source dimensions finally determined upon loading the image
+    public void updateSourceDimensions(final int sourceWidth, final int sourceHeight) {
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/ImageResource.java b/src/com/android/messaging/datamodel/media/ImageResource.java
new file mode 100644
index 0000000..75d817d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/ImageResource.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Base class for holding some form of image resource. The subclass gets to define the specific
+ * type of data format it's holding, whether it be Bitmap objects or compressed byte arrays.
+ */
+public abstract class ImageResource extends RefCountedMediaResource {
+    protected final int mOrientation;
+
+    public ImageResource(final String key, int orientation) {
+        super(key);
+        mOrientation = orientation;
+    }
+
+    /**
+     * Gets the contained image in drawable format.
+     */
+    public abstract Drawable getDrawable(Resources resources);
+
+    /**
+     * Gets the contained image in bitmap format.
+     */
+    public abstract Bitmap getBitmap();
+
+    /**
+     * Gets the contained image in byte array format.
+     */
+    public abstract byte[] getBytes();
+
+    /**
+     * Attempt to reuse the bitmap in the image resource and re-purpose it for something else.
+     * After this, the image resource will relinquish ownership on the bitmap resource so that
+     * it doesn't try to recycle it when getting closed.
+     */
+    public abstract Bitmap reuseBitmap();
+    public abstract boolean supportsBitmapReuse();
+
+    /**
+     * Gets the orientation of the image as one of the ExifInterface.ORIENTATION_* constants
+     */
+    public int getOrientation() {
+        return mOrientation;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/MediaBytes.java b/src/com/android/messaging/datamodel/media/MediaBytes.java
new file mode 100644
index 0000000..823bf27
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaBytes.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+
+/**
+ * Container class for handing around media information used by the MediaResourceManager.
+ */
+public class MediaBytes extends RefCountedMediaResource {
+    private final byte[] mBytes;
+
+    public MediaBytes(final String key, final byte[] bytes) {
+        super(key);
+        mBytes = bytes;
+    }
+
+    public byte[] getMediaBytes() {
+        return mBytes;
+    }
+
+    @Override
+    public int getMediaSize() {
+        return mBytes.length;
+    }
+
+    @Override
+    protected void close() {
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/MediaCache.java b/src/com/android/messaging/datamodel/media/MediaCache.java
new file mode 100644
index 0000000..510da2d
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaCache.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.util.LruCache;
+
+import com.android.messaging.util.LogUtil;
+
+/**
+ * A modified LruCache that is able to hold RefCountedMediaResource instances. It releases
+ * ref on the entries as they are evicted from the cache, and it uses the media resource
+ * size in kilobytes, instead of the entry count, as the size of the cache.
+ *
+ * This class is used by the MediaResourceManager class to maintain a number of caches for
+ * holding different types of {@link RefCountedMediaResource}
+ */
+public class MediaCache<T extends RefCountedMediaResource> extends LruCache<String, T> {
+    private static final String TAG = LogUtil.BUGLE_IMAGE_TAG;
+
+    // Default memory cache size in kilobytes
+    protected static final int DEFAULT_MEDIA_RESOURCE_CACHE_SIZE_IN_KILOBYTES = 1024 * 5;  // 5MB
+
+    // Unique identifier for the cache.
+    private final int mId;
+    // Descriptive name given to the cache for debugging purposes.
+    private final String mName;
+
+    // Convenience constructor that uses the default cache size.
+    public MediaCache(final int id, final String name) {
+        this(DEFAULT_MEDIA_RESOURCE_CACHE_SIZE_IN_KILOBYTES, id, name);
+    }
+
+    public MediaCache(final int maxSize, final int id, final String name) {
+        super(maxSize);
+        mId = id;
+        mName = name;
+    }
+
+    public void destroy() {
+        evictAll();
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * Gets a media resource from this cache. Must use this method to get resource instead of get()
+     * to ensure addRef() on the resource.
+     */
+    public synchronized T fetchResourceFromCache(final String key) {
+        final T ret = get(key);
+        if (ret != null) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "cache hit in mediaCache @ " + getName() +
+                        ", total cache hit = " + hitCount() +
+                        ", total cache miss = " + missCount());
+            }
+            ret.addRef();
+        } else if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "cache miss in mediaCache @ " + getName() +
+                    ", total cache hit = " + hitCount() +
+                    ", total cache miss = " + missCount());
+        }
+        return ret;
+    }
+
+    /**
+     * Add a media resource to this cache. Must use this method to add resource instead of put()
+     * to ensure addRef() on the resource.
+     */
+    public synchronized T addResourceToCache(final String key, final T mediaResource) {
+        mediaResource.addRef();
+        return put(key, mediaResource);
+    }
+
+    /**
+     * Notify the removed entry that is no longer being cached
+     */
+    @Override
+    protected synchronized void entryRemoved(final boolean evicted, final String key,
+            final T oldValue, final T newValue) {
+        oldValue.release();
+    }
+
+    /**
+     * Measure item size in kilobytes rather than units which is more practical
+     * for a media resource cache
+     */
+    @Override
+    protected int sizeOf(final String key, final T value) {
+        final int mediaSizeInKilobytes = value.getMediaSize() / 1024;
+        // Never zero-count any resource, count as at least 1KB.
+        return mediaSizeInKilobytes == 0 ? 1 : mediaSizeInKilobytes;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/MediaCacheManager.java b/src/com/android/messaging/datamodel/media/MediaCacheManager.java
new file mode 100644
index 0000000..6e029f2
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaCacheManager.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.util.SparseArray;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.MemoryCacheManager.MemoryCache;
+import com.android.messaging.datamodel.media.PoolableImageCache.ReusableImageResourcePool;
+
+/**
+ * Manages a set of media caches by id.
+ */
+public abstract class MediaCacheManager implements MemoryCache {
+    public static MediaCacheManager get() {
+        return Factory.get().getMediaCacheManager();
+    }
+
+    protected final SparseArray<MediaCache<?>> mCaches;
+
+    public MediaCacheManager() {
+        mCaches = new SparseArray<MediaCache<?>>();
+        MemoryCacheManager.get().registerMemoryCache(this);
+    }
+
+    @Override
+    public void reclaim() {
+        final int count = mCaches.size();
+        for (int i = 0; i < count; i++) {
+            mCaches.valueAt(i).destroy();
+        }
+        mCaches.clear();
+    }
+
+    public synchronized MediaCache<?> getOrCreateMediaCacheById(final int id) {
+        MediaCache<?> cache = mCaches.get(id);
+        if (cache == null) {
+            cache = createMediaCacheById(id);
+            if (cache != null) {
+                mCaches.put(id, cache);
+            }
+        }
+        return cache;
+    }
+
+    public ReusableImageResourcePool getOrCreateBitmapPoolForCache(final int cacheId) {
+        final MediaCache<?> cache = getOrCreateMediaCacheById(cacheId);
+        if (cache != null && cache instanceof PoolableImageCache) {
+            return ((PoolableImageCache) cache).asReusableBitmapPool();
+        }
+        return null;
+    }
+
+    protected abstract MediaCache<?> createMediaCacheById(final int id);
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/MediaRequest.java b/src/com/android/messaging/datamodel/media/MediaRequest.java
new file mode 100644
index 0000000..78ae85e
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaRequest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import java.util.List;
+
+/**
+ * Keeps track of a media loading request. MediaResourceManager uses this interface to load, encode,
+ * decode, and cache different types of media resource.
+ *
+ * This interface defines a media request class that's threading-model-oblivious. Wrapper classes
+ * (such as {@link AsyncMediaRequestWrapper} wraps around any base media request to offer async
+ * extensions).
+ */
+public interface MediaRequest<T extends RefCountedMediaResource> {
+    public static final int REQUEST_ENCODE_MEDIA = 1;
+    public static final int REQUEST_DECODE_MEDIA = 2;
+    public static final int REQUEST_LOAD_MEDIA = 3;
+
+    /**
+     * Returns a unique key used for storing and looking up the MediaRequest.
+     */
+    String getKey();
+
+    /**
+     * This method performs the heavy-lifting work of synchronously loading the media bytes for
+     * this MediaRequest on a single threaded executor.
+     * @param chainedTask subsequent tasks to be performed after this request is complete. For
+     * example, an image request may need to compress the image resource before putting it in the
+     * cache
+     */
+    T loadMediaBlocking(List<MediaRequest<T>> chainedTask) throws Exception;
+
+    /**
+     * Returns the media cache where this MediaRequest wants to store the loaded
+     * media resource.
+     */
+    MediaCache<T> getMediaCache();
+
+    /**
+     * Returns the id of the cache where this MediaRequest wants to store the loaded
+     * media resource.
+     */
+    int getCacheId();
+
+    /**
+     * Returns the request type of this media request, i.e. one of {@link #REQUEST_ENCODE_MEDIA},
+     * {@link #REQUEST_DECODE_MEDIA}, or {@link #REQUEST_LOAD_MEDIA}. The default is
+     * {@link #REQUEST_LOAD_MEDIA}
+     */
+    int getRequestType();
+
+    /**
+     * Returns the descriptor defining the request.
+     */
+    MediaRequestDescriptor<T> getDescriptor();
+}
diff --git a/src/com/android/messaging/datamodel/media/MediaRequestDescriptor.java b/src/com/android/messaging/datamodel/media/MediaRequestDescriptor.java
new file mode 100644
index 0000000..216b2a3
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaRequestDescriptor.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+
+/**
+ * The base data holder/builder class for constructing async/sync MediaRequest objects during
+ * runtime.
+ */
+public abstract class MediaRequestDescriptor<T extends RefCountedMediaResource> {
+    public abstract MediaRequest<T> buildSyncMediaRequest(Context context);
+
+    /**
+     * Builds an async media request to be used with
+     * {@link MediaResourceManager#requestMediaResourceAsync(MediaRequest)}
+     */
+    public BindableMediaRequest<T> buildAsyncMediaRequest(final Context context,
+            final MediaResourceLoadListener<T> listener) {
+        final MediaRequest<T> syncRequest = buildSyncMediaRequest(context);
+        return AsyncMediaRequestWrapper.createWith(syncRequest, listener);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/MediaResourceManager.java b/src/com/android/messaging/datamodel/media/MediaResourceManager.java
new file mode 100644
index 0000000..13f7291
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MediaResourceManager.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.os.AsyncTask;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnAnyThread;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * <p>Loads and maintains a set of in-memory LRU caches for different types of media resources.
+ * Right now we don't utilize any disk cache as all media urls are expected to be resolved to
+ * local content.<p/>
+ *
+ * <p>The MediaResourceManager takes media loading requests through one of two ways:</p>
+ *
+ * <ol>
+ * <li>{@link #requestMediaResourceAsync(MediaRequest)} that takes a MediaRequest, which may be a
+ *  regular request if the caller doesn't want to listen for events (fire-and-forget),
+ *  or an async request wrapper if event callback is needed.</li>
+ * <li>{@link #requestMediaResourceSync(MediaRequest)} which takes a MediaRequest and synchronously
+ *  returns the loaded result, or null if failed.</li>
+ * </ol>
+ *
+ * <p>For each media loading task, MediaResourceManager starts an AsyncTask that runs on a
+ * dedicated thread, which calls MediaRequest.loadMediaBlocking() to perform the actual media
+ * loading work. As the media resources are loaded, MediaResourceManager notifies the callers
+ * (which must implement the MediaResourceLoadListener interface) via onMediaResourceLoaded()
+ * callback. Meanwhile, MediaResourceManager also pushes the loaded resource onto its dedicated
+ * cache.</p>
+ *
+ * <p>The media resource caches ({@link MediaCache}) are maintained as a set of LRU caches. They are
+ * created on demand by the incoming MediaRequest's getCacheId() method. The implementations of
+ * MediaRequest (such as {@link ImageRequest}) get to determine the desired cache id. For Bugle,
+ * the list of available caches are in {@link BugleMediaCacheManager}</p>
+ *
+ * <p>Optionally, media loading can support on-demand media encoding and decoding.
+ * All {@link MediaRequest}'s can opt to chain additional {@link MediaRequest}'s to be executed
+ * after the completion of the main media loading task, by adding new tasks to the chained
+ * task list in {@link MediaRequest#loadMediaBlocking(List)}. One possible type of chained task is
+ * media encoding task. Loaded media will be encoded on a dedicated single threaded executor
+ * *after* the UI is notified of the loaded media. In this case, the encoded media resource will
+ * be eventually pushed to the cache, which will later be decoded before posting to the UI thread
+ * on cache hit.</p>
+ *
+ * <p><b>To add support for a new type of media resource,</b></p>
+ *
+ * <ol>
+ * <li>Create a new subclass of {@link RefCountedMediaResource} for the new resource type (example:
+ *    {@link ImageResource} class).</li>
+ *
+ * <li>Implement the {@link MediaRequest} interface (example: {@link ImageRequest}). Perform the
+ *    media loading work in loadMediaBlocking() and return a cache id in getCacheId().</li>
+ *
+ * <li>For the UI component that requests the media resource, let it implement
+ *    {@link MediaResourceLoadListener} interface to listen for resource load callback. Let the
+ *    UI component call MediaResourceManager.requestMediaResourceAsync() to request a media source.
+ *    (example: {@link com.android.messaging.ui.ContactIconView}</li>
+ * </ol>
+ */
+public class MediaResourceManager {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    public static MediaResourceManager get() {
+        return Factory.get().getMediaResourceManager();
+    }
+
+    /**
+     * Listener for asynchronous callback from media loading events.
+     */
+    public interface MediaResourceLoadListener<T extends RefCountedMediaResource> {
+        void onMediaResourceLoaded(MediaRequest<T> request, T resource, boolean cached);
+        void onMediaResourceLoadError(MediaRequest<T> request, Exception exception);
+    }
+
+    // We use a fixed thread pool for handling media loading tasks. Using a cached thread pool
+    // allows for unlimited thread creation which can lead to OOMs so we limit the threads here.
+    private static final Executor MEDIA_LOADING_EXECUTOR = Executors.newFixedThreadPool(10);
+
+    // A dedicated single thread executor for performing background task after loading the resource
+    // on the media loading executor. This includes work such as encoding loaded media to be cached.
+    // These tasks are run on a single worker thread with low priority so as not to contend with the
+    // media loading tasks.
+    private static final Executor MEDIA_BACKGROUND_EXECUTOR = Executors.newSingleThreadExecutor(
+            new ThreadFactory() {
+                @Override
+                public Thread newThread(final Runnable runnable) {
+                    final Thread encodingThread = new Thread(runnable);
+                    encodingThread.setPriority(Thread.MIN_PRIORITY);
+                    return encodingThread;
+                }
+            });
+
+    /**
+     * Requests a media resource asynchronously. Upon completion of the media loading task,
+     * the listener will be notified of success/failure iff it's still bound. A refcount on the
+     * resource is held and guaranteed for the caller for the duration of the
+     * {@link MediaResourceLoadListener#onMediaResourceLoaded(
+     * MediaRequest, RefCountedMediaResource, boolean)} callback.
+     * @param mediaRequest the media request. May be either an
+     * {@link AsyncMediaRequestWrapper} for listening for event callbacks, or a regular media
+     * request for fire-and-forget type of behavior.
+     */
+    public <T extends RefCountedMediaResource> void requestMediaResourceAsync(
+            final MediaRequest<T> mediaRequest) {
+        scheduleAsyncMediaRequest(mediaRequest, MEDIA_LOADING_EXECUTOR);
+    }
+
+    /**
+     * Requests a media resource synchronously.
+     * @return the loaded resource with a refcount reserved for the caller. The caller must call
+     * release() on the resource once it's done using it (like with Cursors).
+     */
+    public <T extends RefCountedMediaResource> T requestMediaResourceSync(
+            final MediaRequest<T> mediaRequest) {
+        Assert.isNotMainThread();
+        // Block and load media.
+        MediaLoadingResult<T> loadResult = null;
+        try {
+            loadResult = processMediaRequestInternal(mediaRequest);
+            // The loaded resource should have at least one refcount by now reserved for the caller.
+            Assert.isTrue(loadResult.loadedResource.getRefCount() > 0);
+            return loadResult.loadedResource;
+        } catch (final Exception e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Synchronous media loading failed, key=" +
+                    mediaRequest.getKey(), e);
+            return null;
+        } finally {
+            if (loadResult != null) {
+                // Schedule the background requests chained to the main request.
+                loadResult.scheduleChainedRequests();
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T extends RefCountedMediaResource> MediaLoadingResult<T> processMediaRequestInternal(
+            final MediaRequest<T> mediaRequest)
+                    throws Exception {
+        final List<MediaRequest<T>> chainedRequests = new ArrayList<>();
+        T loadedResource = null;
+        // Try fetching from cache first.
+        final T cachedResource = loadMediaFromCache(mediaRequest);
+        if (cachedResource != null) {
+            if (cachedResource.isEncoded()) {
+                // The resource is encoded, issue a decoding request.
+                final MediaRequest<T> decodeRequest = (MediaRequest<T>) cachedResource
+                        .getMediaDecodingRequest(mediaRequest);
+                Assert.notNull(decodeRequest);
+                cachedResource.release();
+                loadedResource = loadMediaFromRequest(decodeRequest, chainedRequests);
+            } else {
+                // The resource is ready-to-use.
+                loadedResource = cachedResource;
+            }
+        } else {
+            // Actually load the media after cache miss.
+            loadedResource = loadMediaFromRequest(mediaRequest, chainedRequests);
+        }
+        return new MediaLoadingResult<>(loadedResource, cachedResource != null /* fromCache */,
+                chainedRequests);
+    }
+
+    private <T extends RefCountedMediaResource> T loadMediaFromCache(
+            final MediaRequest<T> mediaRequest) {
+        if (mediaRequest.getRequestType() != MediaRequest.REQUEST_LOAD_MEDIA) {
+            // Only look up in the cache if we are loading media.
+            return null;
+        }
+        final MediaCache<T> mediaCache = mediaRequest.getMediaCache();
+        if (mediaCache != null) {
+            final T mediaResource = mediaCache.fetchResourceFromCache(mediaRequest.getKey());
+            if (mediaResource != null) {
+                return mediaResource;
+            }
+        }
+        return null;
+    }
+
+    private <T extends RefCountedMediaResource> T loadMediaFromRequest(
+            final MediaRequest<T> mediaRequest, final List<MediaRequest<T>> chainedRequests)
+                    throws Exception {
+        final T resource = mediaRequest.loadMediaBlocking(chainedRequests);
+        // mediaRequest.loadMediaBlocking() should never return null without
+        // throwing an exception.
+        Assert.notNull(resource);
+        // It's possible for the media to be evicted right after it's added to
+        // the cache (possibly because it's by itself too big for the cache).
+        // It's also possible that, after added to the cache, something else comes
+        // to the cache and evicts this media resource. To prevent this from
+        // recycling the underlying resource objects, make sure to add ref before
+        // adding to cache so that the caller is guaranteed a ref on the resource.
+        resource.addRef();
+        // Don't cache the media request if it is defined as non-cacheable.
+        if (resource.isCacheable()) {
+            addResourceToMemoryCache(mediaRequest, resource);
+        }
+        return resource;
+    }
+
+    /**
+     * Schedule an async media request on the given <code>executor</code>.
+     * @param mediaRequest the media request to be processed asynchronously. May be either an
+     * {@link AsyncMediaRequestWrapper} for listening for event callbacks, or a regular media
+     * request for fire-and-forget type of behavior.
+     */
+    private <T extends RefCountedMediaResource> void scheduleAsyncMediaRequest(
+            final MediaRequest<T> mediaRequest, final Executor executor) {
+        final BindableMediaRequest<T> bindableRequest =
+                (mediaRequest instanceof BindableMediaRequest<?>) ?
+                        (BindableMediaRequest<T>) mediaRequest : null;
+        if (bindableRequest != null && !bindableRequest.isBound()) {
+            return; // Request is obsolete
+        }
+        // We don't use SafeAsyncTask here since it enforces the shared thread pool executor
+        // whereas we want a dedicated thread pool executor.
+        AsyncTask<Void, Void, MediaLoadingResult<T>> mediaLoadingTask =
+                new AsyncTask<Void, Void, MediaLoadingResult<T>>() {
+            private Exception mException;
+
+            @Override
+            protected MediaLoadingResult<T> doInBackground(Void... params) {
+                // Double check the request is still valid by the time we start processing it
+                if (bindableRequest != null && !bindableRequest.isBound()) {
+                    return null; // Request is obsolete
+                }
+                try {
+                    return processMediaRequestInternal(mediaRequest);
+                } catch (Exception e) {
+                    mException = e;
+                    return null;
+                }
+            }
+
+            @Override
+            protected void onPostExecute(final MediaLoadingResult<T> result) {
+                if (result != null) {
+                    Assert.isNull(mException);
+                    Assert.isTrue(result.loadedResource.getRefCount() > 0);
+                    try {
+                        if (bindableRequest != null) {
+                            bindableRequest.onMediaResourceLoaded(
+                                    bindableRequest, result.loadedResource, result.fromCache);
+                        }
+                    } finally {
+                        result.loadedResource.release();
+                        result.scheduleChainedRequests();
+                    }
+                } else if (mException != null) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "Asynchronous media loading failed, key=" +
+                            mediaRequest.getKey(), mException);
+                    if (bindableRequest != null) {
+                        bindableRequest.onMediaResourceLoadError(bindableRequest, mException);
+                    }
+                } else {
+                    Assert.isTrue(bindableRequest == null || !bindableRequest.isBound());
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "media request not processed, no longer bound; key=" +
+                                LogUtil.sanitizePII(mediaRequest.getKey()) /* key with phone# */);
+                    }
+                }
+            }
+        };
+        mediaLoadingTask.executeOnExecutor(executor, (Void) null);
+    }
+
+    @VisibleForTesting
+    @RunsOnAnyThread
+    <T extends RefCountedMediaResource> void addResourceToMemoryCache(
+            final MediaRequest<T> mediaRequest, final T mediaResource) {
+        Assert.isTrue(mediaResource != null);
+        final MediaCache<T> mediaCache = mediaRequest.getMediaCache();
+        if (mediaCache != null) {
+            mediaCache.addResourceToCache(mediaRequest.getKey(), mediaResource);
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "added media resource to " + mediaCache.getName() + ". key=" +
+                        LogUtil.sanitizePII(mediaRequest.getKey()) /* key can contain phone# */);
+            }
+        }
+    }
+
+    private class MediaLoadingResult<T extends RefCountedMediaResource> {
+        public final T loadedResource;
+        public final boolean fromCache;
+        private final List<MediaRequest<T>> mChainedRequests;
+
+        MediaLoadingResult(final T loadedResource, final boolean fromCache,
+                final List<MediaRequest<T>> chainedRequests) {
+            this.loadedResource = loadedResource;
+            this.fromCache = fromCache;
+            mChainedRequests = chainedRequests;
+        }
+
+        /**
+         * Asynchronously schedule a list of chained requests on the background thread.
+         */
+        public void scheduleChainedRequests() {
+            for (final MediaRequest<T> mediaRequest : mChainedRequests) {
+                scheduleAsyncMediaRequest(mediaRequest, MEDIA_BACKGROUND_EXECUTOR);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/MessagePartImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/MessagePartImageRequestDescriptor.java
new file mode 100644
index 0000000..1871e66
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MessagePartImageRequestDescriptor.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.media;
+
+import android.net.Uri;
+
+import com.android.messaging.datamodel.action.UpdateMessagePartSizeAction;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.util.ImageUtils;
+
+/**
+ * Image descriptor attached to a message part.
+ * Once image size is determined during loading this descriptor will update the db if necessary.
+ */
+public class MessagePartImageRequestDescriptor extends UriImageRequestDescriptor {
+    private final String mMessagePartId;
+
+    /**
+     * Creates a new image request for a message part.
+     */
+    public MessagePartImageRequestDescriptor(final MessagePartData messagePart,
+            final int desiredWidth, final int desiredHeight, boolean isStatic) {
+        // Pull image parameters out of the MessagePart record
+        this(messagePart.getPartId(), messagePart.getContentUri(), desiredWidth, desiredHeight,
+                messagePart.getWidth(), messagePart.getHeight(), isStatic);
+    }
+
+    protected MessagePartImageRequestDescriptor(final String messagePartId, final Uri contentUri,
+            final int desiredWidth, final int desiredHeight, final int sourceWidth,
+            final int sourceHeight, boolean isStatic) {
+        super(contentUri, desiredWidth, desiredHeight, sourceWidth, sourceHeight,
+                true /* allowCompression */, isStatic, false /* cropToCircle */,
+                ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+        mMessagePartId = messagePartId;
+    }
+
+    @Override
+    public void updateSourceDimensions(final int updatedWidth, final int updatedHeight) {
+        // If the dimensions of the image do not match then queue a DB update with new size.
+        // Don't update if we don't have a part id, which happens if this part is loaded as
+        // draft through actions such as share intent/message forwarding.
+        if (mMessagePartId != null &&
+                updatedWidth != MessagePartData.UNSPECIFIED_SIZE &&
+                updatedHeight != MessagePartData.UNSPECIFIED_SIZE &&
+                updatedWidth != sourceWidth && updatedHeight != sourceHeight) {
+            UpdateMessagePartSizeAction.updateSize(mMessagePartId, updatedWidth, updatedHeight);
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/MessagePartVideoThumbnailRequestDescriptor.java b/src/com/android/messaging/datamodel/media/MessagePartVideoThumbnailRequestDescriptor.java
new file mode 100644
index 0000000..ff11e92
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/MessagePartVideoThumbnailRequestDescriptor.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.messaging.datamodel.data.MessagePartData;
+
+public class MessagePartVideoThumbnailRequestDescriptor extends MessagePartImageRequestDescriptor {
+    public MessagePartVideoThumbnailRequestDescriptor(MessagePartData messagePart) {
+        super(messagePart, ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE, false);
+    }
+
+    public MessagePartVideoThumbnailRequestDescriptor(Uri uri) {
+        super(null, uri, ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE,
+                ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE, false);
+    }
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(final Context context) {
+        return new VideoThumbnailRequest(context, this);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/NetworkUriImageRequest.java b/src/com/android/messaging/datamodel/media/NetworkUriImageRequest.java
new file mode 100644
index 0000000..642e947
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/NetworkUriImageRequest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Serves network content URI based image requests.
+ */
+public class NetworkUriImageRequest<D extends UriImageRequestDescriptor> extends
+        ImageRequest<D> {
+
+    public NetworkUriImageRequest(Context context, D descriptor) {
+        super(context, descriptor);
+        mOrientation = android.media.ExifInterface.ORIENTATION_UNDEFINED;
+    }
+
+    @Override
+    protected InputStream getInputStreamForResource() throws FileNotFoundException {
+        Assert.isNotMainThread();
+        // Since we need to have an open urlConnection to get the stream, but we don't want to keep
+        // that connection open. There is no good way to perform this method.
+        return null;
+    }
+
+    @Override
+    protected boolean isGif() throws FileNotFoundException {
+        Assert.isNotMainThread();
+
+        HttpURLConnection connection = null;
+        try {
+            final URL url = new URL(mDescriptor.uri.toString());
+            connection = (HttpURLConnection) url.openConnection();
+            connection.connect();
+            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                return ContentType.IMAGE_GIF.equalsIgnoreCase(connection.getContentType());
+            }
+        } catch (MalformedURLException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "MalformedUrl for image with url: "
+                            + mDescriptor.uri.toString(), e);
+        } catch (IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "IOException trying to get inputStream for image with url: "
+                            + mDescriptor.uri.toString(), e);
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+        return false;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public Bitmap loadBitmapInternal() throws IOException {
+        Assert.isNotMainThread();
+
+        InputStream inputStream = null;
+        Bitmap bitmap = null;
+        HttpURLConnection connection = null;
+        try {
+            final URL url = new URL(mDescriptor.uri.toString());
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setDoInput(true);
+            connection.connect();
+            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                bitmap = BitmapFactory.decodeStream(connection.getInputStream());
+            }
+        } catch (MalformedURLException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "MalformedUrl for image with url: "
+                            + mDescriptor.uri.toString(), e);
+        } catch (final OutOfMemoryError e) {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "OutOfMemoryError for image with url: "
+                            + mDescriptor.uri.toString(), e);
+            Factory.get().reclaimMemory();
+        } catch (IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "IOException trying to get inputStream for image with url: "
+                            + mDescriptor.uri.toString(), e);
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+        return bitmap;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/PoolableImageCache.java b/src/com/android/messaging/datamodel/media/PoolableImageCache.java
new file mode 100644
index 0000000..1d8ebc1
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/PoolableImageCache.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.SystemClock;
+import androidx.annotation.NonNull;
+import android.util.SparseArray;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+
+/**
+ * A media cache that holds image resources, which doubles as a bitmap pool that allows the
+ * consumer to optionally decode image resources using unused bitmaps stored in the cache.
+ */
+public class PoolableImageCache extends MediaCache<ImageResource> {
+    private static final int MIN_TIME_IN_POOL = 5000;
+
+    /** Encapsulates bitmap pool representation of the image cache */
+    private final ReusableImageResourcePool mReusablePoolAccessor = new ReusableImageResourcePool();
+
+    public PoolableImageCache(final int id, final String name) {
+        this(DEFAULT_MEDIA_RESOURCE_CACHE_SIZE_IN_KILOBYTES, id, name);
+    }
+
+    public PoolableImageCache(final int maxSize, final int id, final String name) {
+        super(maxSize, id, name);
+    }
+
+    /**
+     * Creates a new BitmapFactory.Options for using the self-contained bitmap pool.
+     */
+    public static BitmapFactory.Options getBitmapOptionsForPool(final boolean scaled,
+            final int inputDensity, final int targetDensity) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inScaled = scaled;
+        options.inDensity = inputDensity;
+        options.inTargetDensity = targetDensity;
+        options.inSampleSize = 1;
+        options.inJustDecodeBounds = false;
+        options.inMutable = true;
+        return options;
+    }
+
+    @Override
+    public synchronized ImageResource addResourceToCache(final String key,
+            final ImageResource imageResource) {
+        mReusablePoolAccessor.onResourceEnterCache(imageResource);
+        return super.addResourceToCache(key, imageResource);
+    }
+
+    @Override
+    protected synchronized void entryRemoved(final boolean evicted, final String key,
+            final ImageResource oldValue, final ImageResource newValue) {
+        mReusablePoolAccessor.onResourceLeaveCache(oldValue);
+        super.entryRemoved(evicted, key, oldValue, newValue);
+    }
+
+    /**
+     * Returns a representation of the image cache as a reusable bitmap pool.
+     */
+    public ReusableImageResourcePool asReusableBitmapPool() {
+        return mReusablePoolAccessor;
+    }
+
+    /**
+     * A bitmap pool representation built on top of the image cache. It treats the image resources
+     * stored in the image cache as a self-contained bitmap pool and is able to create or
+     * reclaim bitmap resource as needed.
+     */
+    public class ReusableImageResourcePool {
+        private static final int MAX_SUPPORTED_IMAGE_DIMENSION = 0xFFFF;
+        private static final int INVALID_POOL_KEY = 0;
+
+        /**
+         * Number of reuse failures to skip before reporting.
+         * For debugging purposes, change to a lower number for more frequent reporting.
+         */
+        private static final int FAILED_REPORTING_FREQUENCY = 100;
+
+        /**
+         * Count of reuse failures which have occurred.
+         */
+        private volatile int mFailedBitmapReuseCount = 0;
+
+        /**
+         * Count of reuse successes which have occurred.
+         */
+        private volatile int mSucceededBitmapReuseCount = 0;
+
+        /**
+         * A sparse array from bitmap size to a list of image cache entries that match the
+         * given size. This map is used to quickly retrieve a usable bitmap to be reused by an
+         * incoming ImageRequest. We need to ensure that this sparse array always contains only
+         * elements currently in the image cache with no other consumer.
+         */
+        private final SparseArray<LinkedList<ImageResource>> mImageListSparseArray;
+
+        public ReusableImageResourcePool() {
+            mImageListSparseArray = new SparseArray<LinkedList<ImageResource>>();
+        }
+
+        /**
+         * Load an input stream into a bitmap. Uses a bitmap from the pool if possible to reduce
+         * memory turnover.
+         * @param inputStream InputStream load. Cannot be null.
+         * @param optionsTmp Should be the same options returned from getBitmapOptionsForPool().
+         * Cannot be null.
+         * @param width The width of the bitmap.
+         * @param height The height of the bitmap.
+         * @return The decoded Bitmap with the resource drawn in it.
+         * @throws IOException
+         */
+        public Bitmap decodeSampledBitmapFromInputStream(@NonNull final InputStream inputStream,
+                @NonNull final BitmapFactory.Options optionsTmp,
+                final int width, final int height) throws IOException {
+            if (width <= 0 || height <= 0) {
+                // This is an invalid / corrupted image of zero size.
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "PoolableImageCache: Decoding bitmap with " +
+                        "invalid size");
+                throw new IOException("Invalid size / corrupted image");
+            }
+            Assert.notNull(inputStream);
+            assignPoolBitmap(optionsTmp, width, height);
+            Bitmap b = null;
+            try {
+                b = BitmapFactory.decodeStream(inputStream, null, optionsTmp);
+                mSucceededBitmapReuseCount++;
+            } catch (final IllegalArgumentException e) {
+                // BitmapFactory couldn't decode the file, try again without an inputBufferBitmap.
+                if (optionsTmp.inBitmap != null) {
+                    optionsTmp.inBitmap.recycle();
+                    optionsTmp.inBitmap = null;
+                    b = BitmapFactory.decodeStream(inputStream, null, optionsTmp);
+                    onFailedToReuse();
+                }
+            } catch (final OutOfMemoryError e) {
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "Oom decoding inputStream");
+                Factory.get().reclaimMemory();
+            }
+            return b;
+        }
+
+        /**
+         * Turn encoded bytes into a bitmap. Uses a bitmap from the pool if possible to reduce
+         * memory turnover.
+         * @param bytes Encoded bytes to draw on the bitmap. Cannot be null.
+         * @param optionsTmp The bitmap will set here and the input should be generated from
+         * getBitmapOptionsForPool(). Cannot be null.
+         * @param width The width of the bitmap.
+         * @param height The height of the bitmap.
+         * @return A Bitmap with the encoded bytes drawn in it.
+         * @throws IOException
+         */
+        public Bitmap decodeByteArray(@NonNull final byte[] bytes,
+                @NonNull final BitmapFactory.Options optionsTmp, final int width,
+                final int height) throws OutOfMemoryError, IOException {
+            if (width <= 0 || height <= 0) {
+                // This is an invalid / corrupted image of zero size.
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "PoolableImageCache: Decoding bitmap with " +
+                        "invalid size");
+                throw new IOException("Invalid size / corrupted image");
+            }
+            Assert.notNull(bytes);
+            Assert.notNull(optionsTmp);
+            assignPoolBitmap(optionsTmp, width, height);
+            Bitmap b = null;
+            try {
+                b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, optionsTmp);
+                mSucceededBitmapReuseCount++;
+            } catch (final IllegalArgumentException e) {
+                // BitmapFactory couldn't decode the file, try again without an inputBufferBitmap.
+                // (i.e. without the bitmap from the pool)
+                if (optionsTmp.inBitmap != null) {
+                    optionsTmp.inBitmap.recycle();
+                    optionsTmp.inBitmap = null;
+                    b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, optionsTmp);
+                    onFailedToReuse();
+                }
+            } catch (final OutOfMemoryError e) {
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "Oom decoding inputStream");
+                Factory.get().reclaimMemory();
+            }
+            return b;
+        }
+
+        /**
+         * Called when a new image resource is added to the cache. We add the resource to the
+         * pool so it's properly keyed into the pool structure.
+         */
+        void onResourceEnterCache(final ImageResource imageResource) {
+            if (getPoolKey(imageResource) != INVALID_POOL_KEY) {
+                addResourceToPool(imageResource);
+            }
+        }
+
+        /**
+         * Called when an image resource is evicted from the cache. Bitmap pool's entries are
+         * strictly tied to their presence in the image cache. Once an image is evicted from the
+         * cache, it should be removed from the pool.
+         */
+        void onResourceLeaveCache(final ImageResource imageResource) {
+            if (getPoolKey(imageResource) != INVALID_POOL_KEY) {
+                removeResourceFromPool(imageResource);
+            }
+        }
+
+        private void addResourceToPool(final ImageResource imageResource) {
+            synchronized (PoolableImageCache.this) {
+                final int poolKey = getPoolKey(imageResource);
+                Assert.isTrue(poolKey != INVALID_POOL_KEY);
+                LinkedList<ImageResource> imageList = mImageListSparseArray.get(poolKey);
+                if (imageList == null) {
+                    imageList = new LinkedList<ImageResource>();
+                    mImageListSparseArray.put(poolKey, imageList);
+                }
+                imageList.addLast(imageResource);
+            }
+        }
+
+        private void removeResourceFromPool(final ImageResource imageResource) {
+            synchronized (PoolableImageCache.this) {
+                final int poolKey = getPoolKey(imageResource);
+                Assert.isTrue(poolKey != INVALID_POOL_KEY);
+                final LinkedList<ImageResource> imageList = mImageListSparseArray.get(poolKey);
+                if (imageList != null) {
+                    imageList.remove(imageResource);
+                }
+            }
+        }
+
+        /**
+         * Try to get a reusable bitmap from the pool with the given width and height. As a
+         * result of this call, the caller will assume ownership of the returned bitmap.
+         */
+        private Bitmap getReusableBitmapFromPool(final int width, final int height) {
+            synchronized (PoolableImageCache.this) {
+                final int poolKey = getPoolKey(width, height);
+                if (poolKey != INVALID_POOL_KEY) {
+                    final LinkedList<ImageResource> images = mImageListSparseArray.get(poolKey);
+                    if (images != null && images.size() > 0) {
+                        // Try to reuse the first available bitmap from the pool list. We start from
+                        // the least recently added cache entry of the given size.
+                        ImageResource imageToUse = null;
+                        for (int i = 0; i < images.size(); i++) {
+                            final ImageResource image = images.get(i);
+                            if (image.getRefCount() == 1) {
+                                image.acquireLock();
+                                if (image.getRefCount() == 1) {
+                                    // The image is only used by the cache, so it's reusable.
+                                    imageToUse = images.remove(i);
+                                    break;
+                                } else {
+                                    // Logically, this shouldn't happen, because as soon as the
+                                    // cache is the only user of this resource, it will not be
+                                    // used by anyone else until the next cache access, but we
+                                    // currently hold on to the cache lock. But technically
+                                    // future changes may violate this assumption, so warn about
+                                    // this.
+                                    LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "Image refCount changed " +
+                                            "from 1 in getReusableBitmapFromPool()");
+                                    image.releaseLock();
+                                }
+                            }
+                        }
+
+                        if (imageToUse == null) {
+                            return null;
+                        }
+
+                        try {
+                            imageToUse.assertLockHeldByCurrentThread();
+
+                            // Only reuse the bitmap if the last time we use was greater than 5s.
+                            // This allows the cache a chance to reuse instead of always taking the
+                            // oldest.
+                            final long timeSinceLastRef = SystemClock.elapsedRealtime() -
+                                    imageToUse.getLastRefAddTimestamp();
+                            if (timeSinceLastRef < MIN_TIME_IN_POOL) {
+                                if (LogUtil.isLoggable(LogUtil.BUGLE_IMAGE_TAG, LogUtil.VERBOSE)) {
+                                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG, "Not reusing reusing " +
+                                            "first available bitmap from the pool because it " +
+                                            "has not been in the pool long enough. " +
+                                            "timeSinceLastRef=" + timeSinceLastRef);
+                                }
+                                // Put back the image and return no reuseable bitmap.
+                                images.addLast(imageToUse);
+                                return null;
+                            }
+
+                            // Add a temp ref on the image resource so it won't be GC'd after
+                            // being removed from the cache.
+                            imageToUse.addRef();
+
+                            // Remove the image resource from the image cache.
+                            final ImageResource removed = remove(imageToUse.getKey());
+                            Assert.isTrue(removed == imageToUse);
+
+                            // Try to reuse the bitmap from the image resource. This will transfer
+                            // ownership of the bitmap object to the caller of this method.
+                            final Bitmap reusableBitmap = imageToUse.reuseBitmap();
+
+                            imageToUse.release();
+                            return reusableBitmap;
+                        } finally {
+                            // We are either done with the reuse operation, or decided not to use
+                            // the image. Either way, release the lock.
+                            imageToUse.releaseLock();
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Try to locate and return a reusable bitmap from the pool, or create a new bitmap.
+         * @param width desired bitmap width
+         * @param height desired bitmap height
+         * @return the created or reused mutable bitmap that has its background cleared to
+         * {@value Color#TRANSPARENT}
+         */
+        public Bitmap createOrReuseBitmap(final int width, final int height) {
+            return createOrReuseBitmap(width, height, Color.TRANSPARENT);
+        }
+
+        /**
+         * Try to locate and return a reusable bitmap from the pool, or create a new bitmap.
+         * @param width desired bitmap width
+         * @param height desired bitmap height
+         * @param backgroundColor the background color for the returned bitmap
+         * @return the created or reused mutable bitmap with the requested background color
+         */
+        public Bitmap createOrReuseBitmap(final int width, final int height,
+                final int backgroundColor) {
+            Bitmap retBitmap = null;
+            try {
+                final Bitmap poolBitmap = getReusableBitmapFromPool(width, height);
+                retBitmap = (poolBitmap != null) ? poolBitmap :
+                        Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+                retBitmap.eraseColor(backgroundColor);
+            } catch (final OutOfMemoryError e) {
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, "PoolableImageCache:try to createOrReuseBitmap");
+                Factory.get().reclaimMemory();
+            }
+            return retBitmap;
+        }
+
+        private void assignPoolBitmap(final BitmapFactory.Options optionsTmp, final int width,
+                final int height) {
+            if (optionsTmp.inJustDecodeBounds) {
+                return;
+            }
+            optionsTmp.inBitmap = getReusableBitmapFromPool(width, height);
+        }
+
+        /**
+         * @return The pool key for the provided image dimensions or 0 if either width or height is
+         * greater than the max supported image dimension.
+         */
+        private int getPoolKey(final int width, final int height) {
+            if (width > MAX_SUPPORTED_IMAGE_DIMENSION || height > MAX_SUPPORTED_IMAGE_DIMENSION) {
+                return INVALID_POOL_KEY;
+            }
+            return (width << 16) | height;
+        }
+
+        /**
+         * @return the pool key for a given image resource.
+         */
+        private int getPoolKey(final ImageResource imageResource) {
+            if (imageResource.supportsBitmapReuse()) {
+                final Bitmap bitmap = imageResource.getBitmap();
+                if (bitmap != null && bitmap.isMutable()) {
+                    final int width = bitmap.getWidth();
+                    final int height = bitmap.getHeight();
+                    if (width > 0 && height > 0) {
+                        return getPoolKey(width, height);
+                    }
+                }
+            }
+            return INVALID_POOL_KEY;
+        }
+
+        /**
+         * Called when bitmap reuse fails. Conditionally report the failure with statistics.
+         */
+        private void onFailedToReuse() {
+            mFailedBitmapReuseCount++;
+            if (mFailedBitmapReuseCount % FAILED_REPORTING_FREQUENCY == 0) {
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG,
+                        "Pooled bitmap consistently not being reused. Failure count = " +
+                                mFailedBitmapReuseCount + ", success count = " +
+                                mSucceededBitmapReuseCount);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/RefCountedMediaResource.java b/src/com/android/messaging/datamodel/media/RefCountedMediaResource.java
new file mode 100644
index 0000000..c21f477
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/RefCountedMediaResource.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.os.SystemClock;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.google.common.base.Throwables;
+
+import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A ref-counted class that holds loaded media resource, be it bitmaps or media bytes.
+ * Subclasses must implement the close() method to release any resources (such as bitmaps)
+ * when it's no longer used.
+ *
+ * Instances of the subclasses are:
+ * 1. Loaded by their corresponding MediaRequest classes.
+ * 2. Maintained by MediaResourceManager in its MediaCache pool.
+ * 3. Used by the UI (such as ContactIconViews) to present the content.
+ *
+ * Note: all synchronized methods in this class (e.g. addRef()) should not attempt to make outgoing
+ * calls that could potentially acquire media cache locks due to the potential deadlock this can
+ * cause. To synchronize read/write access to shared resource, {@link #acquireLock()} and
+ * {@link #releaseLock()} must be used, instead of using synchronized keyword.
+ */
+public abstract class RefCountedMediaResource {
+    private final String mKey;
+    private int mRef = 0;
+    private long mLastRefAddTimestamp;
+
+    // Set DEBUG to true to enable detailed stack trace for each addRef() and release() operation
+    // to find out where each ref change happens.
+    private static final boolean DEBUG = false;
+    private static final String TAG = "bugle_media_ref_history";
+    private final ArrayList<String> mRefHistory = new ArrayList<String>();
+
+    // A lock that guards access to shared members in this class (and all its subclasses).
+    private final ReentrantLock mLock = new ReentrantLock();
+
+    public RefCountedMediaResource(final String key) {
+        mKey = key;
+    }
+
+    public String getKey() {
+        return mKey;
+    }
+
+    public void addRef() {
+        acquireLock();
+        try {
+            if (DEBUG) {
+                mRefHistory.add("Added ref current ref = " + mRef);
+                mRefHistory.add(Throwables.getStackTraceAsString(new Exception()));
+            }
+
+            mRef++;
+            mLastRefAddTimestamp = SystemClock.elapsedRealtime();
+        } finally {
+            releaseLock();
+        }
+    }
+
+    public void release() {
+        acquireLock();
+        try {
+            if (DEBUG) {
+                mRefHistory.add("Released ref current ref = " + mRef);
+                mRefHistory.add(Throwables.getStackTraceAsString(new Exception()));
+            }
+
+            mRef--;
+            if (mRef == 0) {
+                close();
+            } else if (mRef < 0) {
+                if (DEBUG) {
+                    LogUtil.i(TAG, "Unwinding ref count history for RefCountedMediaResource "
+                            + this);
+                    for (final String ref : mRefHistory) {
+                        LogUtil.i(TAG, ref);
+                    }
+                }
+                Assert.fail("RefCountedMediaResource has unbalanced ref. Refcount=" + mRef);
+            }
+        } finally {
+            releaseLock();
+        }
+    }
+
+    public int getRefCount() {
+        acquireLock();
+        try {
+            return mRef;
+        } finally {
+            releaseLock();
+        }
+    }
+
+    public long getLastRefAddTimestamp() {
+        acquireLock();
+        try {
+            return mLastRefAddTimestamp;
+        } finally {
+            releaseLock();
+        }
+    }
+
+    public void assertSingularRefCount() {
+        acquireLock();
+        try {
+            Assert.equals(1, mRef);
+        } finally {
+            releaseLock();
+        }
+    }
+
+    void acquireLock() {
+        mLock.lock();
+    }
+
+    void releaseLock() {
+        mLock.unlock();
+    }
+
+    void assertLockHeldByCurrentThread() {
+        Assert.isTrue(mLock.isHeldByCurrentThread());
+    }
+
+    boolean isEncoded() {
+        return false;
+    }
+
+    boolean isCacheable() {
+        return true;
+    }
+
+    MediaRequest<? extends RefCountedMediaResource> getMediaDecodingRequest(
+            final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
+        return null;
+    }
+
+    MediaRequest<? extends RefCountedMediaResource> getMediaEncodingRequest(
+            final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
+        return null;
+    }
+
+    public abstract int getMediaSize();
+    protected abstract void close();
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/datamodel/media/SimSelectorAvatarRequest.java b/src/com/android/messaging/datamodel/media/SimSelectorAvatarRequest.java
new file mode 100644
index 0000000..e4f0334
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/SimSelectorAvatarRequest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.media.ExifInterface;
+import android.text.TextUtils;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+
+import java.io.IOException;
+import java.util.List;
+
+public class SimSelectorAvatarRequest extends AvatarRequest {
+    private static Bitmap sRegularSimIcon;
+
+    public SimSelectorAvatarRequest(final Context context,
+            final AvatarRequestDescriptor descriptor) {
+        super(context, descriptor);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTasks)
+            throws IOException {
+        Assert.isNotMainThread();
+        final String avatarType = AvatarUriUtil.getAvatarType(mDescriptor.uri);
+        if (AvatarUriUtil.TYPE_SIM_SELECTOR_URI.equals(avatarType)){
+            final int width = mDescriptor.desiredWidth;
+            final int height = mDescriptor.desiredHeight;
+            final String identifier = AvatarUriUtil.getIdentifier(mDescriptor.uri);
+            final boolean simSelected = AvatarUriUtil.getSimSelected(mDescriptor.uri);
+            final int simColor = AvatarUriUtil.getSimColor(mDescriptor.uri);
+            final boolean incoming = AvatarUriUtil.getSimIncoming(mDescriptor.uri);
+            return renderSimAvatarInternal(identifier, width, height, simColor, simSelected,
+                    incoming);
+        }
+        return super.loadMediaInternal(chainedTasks);
+    }
+
+    private ImageResource renderSimAvatarInternal(final String identifier, final int width,
+            final int height, final int subColor, final boolean selected, final boolean incoming) {
+        final Resources resources = mContext.getResources();
+        final float halfWidth = width / 2;
+        final float halfHeight = height / 2;
+        final int minOfWidthAndHeight = Math.min(width, height);
+        final int backgroundColor = selected ? subColor : Color.WHITE;
+        final int textColor = selected ? subColor : Color.WHITE;
+        final int simColor = selected ? Color.WHITE : subColor;
+        final Bitmap bitmap = getBitmapPool().createOrReuseBitmap(width, height, backgroundColor);
+        final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        final Canvas canvas = new Canvas(bitmap);
+
+        if (sRegularSimIcon == null) {
+            final BitmapDrawable regularSim = (BitmapDrawable) mContext.getResources()
+                    .getDrawable(R.drawable.ic_sim_card_send);
+            sRegularSimIcon = regularSim.getBitmap();
+        }
+
+        paint.setColorFilter(new PorterDuffColorFilter(simColor, PorterDuff.Mode.SRC_ATOP));
+        paint.setAlpha(0xff);
+        canvas.drawBitmap(sRegularSimIcon, halfWidth - sRegularSimIcon.getWidth() / 2,
+                halfHeight - sRegularSimIcon.getHeight() / 2, paint);
+        paint.setColorFilter(null);
+        paint.setAlpha(0xff);
+
+        if (!TextUtils.isEmpty(identifier)) {
+            paint.setTypeface(Typeface.create("sans-serif", Typeface.NORMAL));
+            paint.setColor(textColor);
+            final float letterToTileRatio =
+                    resources.getFraction(R.dimen.sim_identifier_to_tile_ratio, 1, 1);
+            paint.setTextSize(letterToTileRatio * minOfWidthAndHeight);
+
+            final String firstCharString = identifier.substring(0, 1).toUpperCase();
+            final Rect textBound = new Rect();
+            paint.getTextBounds(firstCharString, 0, 1, textBound);
+
+            final float xOffset = halfWidth - textBound.centerX();
+            final float yOffset = halfHeight - textBound.centerY();
+            canvas.drawText(firstCharString, xOffset, yOffset, paint);
+        }
+
+        return new DecodedImageResource(getKey(), bitmap, ExifInterface.ORIENTATION_NORMAL);
+    }
+
+    @Override
+    public int getCacheId() {
+        return BugleMediaCacheManager.AVATAR_IMAGE_CACHE;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/UriImageRequest.java b/src/com/android/messaging/datamodel/media/UriImageRequest.java
new file mode 100644
index 0000000..b4934ca
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/UriImageRequest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Serves local content URI based image requests.
+ */
+public class UriImageRequest<D extends UriImageRequestDescriptor> extends ImageRequest<D> {
+    public UriImageRequest(final Context context, final D descriptor) {
+        super(context, descriptor);
+    }
+
+    @Override
+    protected InputStream getInputStreamForResource() throws FileNotFoundException {
+        return mContext.getContentResolver().openInputStream(mDescriptor.uri);
+    }
+
+    @Override
+    protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTasks)
+            throws IOException {
+        final ImageResource resource = super.loadMediaInternal(chainedTasks);
+        // Check if the caller asked for compression. If so, chain an encoding task if possible.
+        if (mDescriptor.allowCompression && chainedTasks != null) {
+            @SuppressWarnings("unchecked")
+            final MediaRequest<ImageResource> chainedTask = (MediaRequest<ImageResource>)
+                    resource.getMediaEncodingRequest(this);
+            if (chainedTask != null) {
+                chainedTasks.add(chainedTask);
+                // Don't cache decoded image resource since we'll perform compression and cache
+                // the compressed resource.
+                if (resource instanceof DecodedImageResource) {
+                    ((DecodedImageResource) resource).setCacheable(false);
+                }
+            }
+        }
+        return resource;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java
new file mode 100644
index 0000000..dae293a
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.messaging.util.UriUtil;
+
+public class UriImageRequestDescriptor extends ImageRequestDescriptor {
+    public final Uri uri;
+    public final boolean allowCompression;
+
+    public UriImageRequestDescriptor(final Uri uri) {
+        this(uri, UriImageRequest.UNSPECIFIED_SIZE, UriImageRequest.UNSPECIFIED_SIZE, false, false,
+                false, 0, 0);
+    }
+
+    public UriImageRequestDescriptor(final Uri uri, final int desiredWidth, final int desiredHeight)
+    {
+        this(uri, desiredWidth, desiredHeight, false, false, false, 0, 0);
+    }
+
+    public UriImageRequestDescriptor(final Uri uri, final int desiredWidth, final int desiredHeight,
+            final boolean cropToCircle, final int circleBackgroundColor, int circleStrokeColor)
+    {
+        this(uri, desiredWidth, desiredHeight, false,
+                false, cropToCircle, circleBackgroundColor, circleStrokeColor);
+    }
+
+    public UriImageRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight, final boolean allowCompression, boolean isStatic,
+            boolean cropToCircle, int circleBackgroundColor, int circleStrokeColor) {
+        this(uri, desiredWidth, desiredHeight, UriImageRequest.UNSPECIFIED_SIZE,
+                UriImageRequest.UNSPECIFIED_SIZE, allowCompression, isStatic, cropToCircle,
+                circleBackgroundColor, circleStrokeColor);
+    }
+
+    /**
+     * Creates a new Uri-based image request.
+     * @param uri the content Uri. Currently Bugle only supports local resources Uri (i.e. it has
+     * to begin with content: or android.resource:
+     * @param circleStrokeColor
+     */
+    public UriImageRequestDescriptor(final Uri uri, final int desiredWidth,
+            final int desiredHeight, final int sourceWidth, final int sourceHeight,
+            final boolean allowCompression, final boolean isStatic, final boolean cropToCircle,
+            final int circleBackgroundColor, int circleStrokeColor) {
+        super(desiredWidth, desiredHeight, sourceWidth, sourceHeight, isStatic,
+                cropToCircle, circleBackgroundColor, circleStrokeColor);
+        this.uri = uri;
+        this.allowCompression = allowCompression;
+    }
+
+    @Override
+    public String getKey() {
+        if (uri != null) {
+            final String key = super.getKey();
+            if (key != null) {
+                return new StringBuilder()
+                    .append(uri).append(KEY_PART_DELIMITER)
+                    .append(String.valueOf(allowCompression)).append(KEY_PART_DELIMITER)
+                    .append(key).toString();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(final Context context) {
+        if (uri == null || UriUtil.isLocalUri(uri)) {
+            return new UriImageRequest<UriImageRequestDescriptor>(context, this);
+        } else {
+            return new NetworkUriImageRequest<UriImageRequestDescriptor>(context, this);
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VCardRequest.java b/src/com/android/messaging/datamodel/media/VCardRequest.java
new file mode 100644
index 0000000..d6e992c
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VCardRequest.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.UriUtil;
+import com.android.vcard.VCardConfig;
+import com.android.vcard.VCardEntry;
+import com.android.vcard.VCardEntryCounter;
+import com.android.vcard.VCardInterpreter;
+import com.android.vcard.VCardParser;
+import com.android.vcard.VCardParser_V21;
+import com.android.vcard.VCardParser_V30;
+import com.android.vcard.VCardSourceDetector;
+import com.android.vcard.exception.VCardException;
+import com.android.vcard.exception.VCardNestedException;
+import com.android.vcard.exception.VCardNotSupportedException;
+import com.android.vcard.exception.VCardVersionException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Requests and parses VCard data. In Bugle, we need to display VCard details in the conversation
+ * view such as avatar icon and name, which can be expensive if we parse VCard every time.
+ * Therefore, we'd like to load the vcard once and cache it in our media cache using the
+ * MediaResourceManager component. To load the VCard, we use framework's VCard support to
+ * interpret the VCard content, which gives us information such as phone and email list, which
+ * we'll put in VCardResource object to be cached.
+ *
+ * Some particular attention is needed for the avatar icon. If the VCard contains avatar icon,
+ * it's in byte array form that can't easily be cached/persisted. Therefore, we persist the
+ * image bytes to the scratch directory and generate a content Uri for it, so that ContactIconView
+ * may use this Uri to display and cache the image if needed.
+ */
+public class VCardRequest implements MediaRequest<VCardResource> {
+    private final Context mContext;
+    private final VCardRequestDescriptor mDescriptor;
+    private final List<VCardResourceEntry> mLoadedVCards;
+    private VCardResource mLoadedResource;
+    private static final int VCARD_LOADING_TIMEOUT_MILLIS = 10000;  // 10s
+    private static final String DEFAULT_VCARD_TYPE = "default";
+
+    VCardRequest(final Context context, final VCardRequestDescriptor descriptor) {
+        mDescriptor = descriptor;
+        mContext = context;
+        mLoadedVCards = new ArrayList<VCardResourceEntry>();
+    }
+
+    @Override
+    public String getKey() {
+        return mDescriptor.vCardUri.toString();
+    }
+
+    @Override
+    @DoesNotRunOnMainThread
+    public VCardResource loadMediaBlocking(List<MediaRequest<VCardResource>> chainedTask)
+            throws Exception {
+        Assert.isNotMainThread();
+        Assert.isTrue(mLoadedResource == null);
+        Assert.equals(0, mLoadedVCards.size());
+
+        // The VCard library doesn't support synchronously loading the media resource. Therefore,
+        // We have to burn the thread waiting for the result to come back.
+        final CountDownLatch signal = new CountDownLatch(1);
+        if (!parseVCard(mDescriptor.vCardUri, signal)) {
+            // Directly fail without actually going through the interpreter, return immediately.
+            throw new VCardException("Invalid vcard");
+        }
+
+        signal.await(VCARD_LOADING_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        if (mLoadedResource == null) {
+            // Maybe null if failed or timeout.
+            throw new VCardException("Failure or timeout loading vcard");
+        }
+        return mLoadedResource;
+    }
+
+    @Override
+    public int getCacheId() {
+        return BugleMediaCacheManager.VCARD_CACHE;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public MediaCache<VCardResource> getMediaCache() {
+        return (MediaCache<VCardResource>) MediaCacheManager.get().getOrCreateMediaCacheById(
+                getCacheId());
+    }
+
+    @DoesNotRunOnMainThread
+    private boolean parseVCard(final Uri targetUri, final CountDownLatch signal) {
+        Assert.isNotMainThread();
+        final VCardEntryCounter counter = new VCardEntryCounter();
+        final VCardSourceDetector detector = new VCardSourceDetector();
+        boolean result;
+        try {
+            // We don't know which type should be used to parse the Uri.
+            // It is possible to misinterpret the vCard, but we expect the parser
+            // lets VCardSourceDetector detect the type before the misinterpretation.
+            result = readOneVCardFile(targetUri, VCardConfig.VCARD_TYPE_UNKNOWN,
+                    detector, true, null);
+        } catch (final VCardNestedException e) {
+            try {
+                final int estimatedVCardType = detector.getEstimatedType();
+                // Assume that VCardSourceDetector was able to detect the source.
+                // Try again with the detector.
+                result = readOneVCardFile(targetUri, estimatedVCardType,
+                        counter, false, null);
+            } catch (final VCardNestedException e2) {
+                result = false;
+                LogUtil.e(LogUtil.BUGLE_TAG, "Must not reach here. " + e2);
+            }
+        }
+
+        if (!result) {
+            // Load failure.
+            return false;
+        }
+
+        return doActuallyReadOneVCard(targetUri, true, detector, null, signal);
+    }
+
+    @DoesNotRunOnMainThread
+    private boolean doActuallyReadOneVCard(final Uri uri, final boolean showEntryParseProgress,
+            final VCardSourceDetector detector, final List<String> errorFileNameList,
+            final CountDownLatch signal) {
+        Assert.isNotMainThread();
+        int vcardType = detector.getEstimatedType();
+        if (vcardType == VCardConfig.VCARD_TYPE_UNKNOWN) {
+            vcardType = VCardConfig.getVCardTypeFromString(DEFAULT_VCARD_TYPE);
+        }
+        final CustomVCardEntryConstructor builder =
+                new CustomVCardEntryConstructor(vcardType, null);
+        builder.addEntryHandler(new ContactVCardEntryHandler(signal));
+
+        try {
+            if (!readOneVCardFile(uri, vcardType, builder, false, null)) {
+                return false;
+            }
+        } catch (final VCardNestedException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Must not reach here. " + e);
+            return false;
+        }
+        return true;
+    }
+
+    @DoesNotRunOnMainThread
+    private boolean readOneVCardFile(final Uri uri, final int vcardType,
+            final VCardInterpreter interpreter,
+            final boolean throwNestedException, final List<String> errorFileNameList)
+                    throws VCardNestedException {
+        Assert.isNotMainThread();
+        final ContentResolver resolver = mContext.getContentResolver();
+        VCardParser vCardParser;
+        InputStream is;
+        try {
+            is = resolver.openInputStream(uri);
+            vCardParser = new VCardParser_V21(vcardType);
+            vCardParser.addInterpreter(interpreter);
+
+            try {
+                vCardParser.parse(is);
+            } catch (final VCardVersionException e1) {
+                try {
+                    is.close();
+                } catch (final IOException e) {
+                    // Do nothing.
+                }
+                if (interpreter instanceof CustomVCardEntryConstructor) {
+                    // Let the object clean up internal temporal objects,
+                    ((CustomVCardEntryConstructor) interpreter).clear();
+                }
+
+                is = resolver.openInputStream(uri);
+
+                try {
+                    vCardParser = new VCardParser_V30(vcardType);
+                    vCardParser.addInterpreter(interpreter);
+                    vCardParser.parse(is);
+                } catch (final VCardVersionException e2) {
+                    throw new VCardException("vCard with unspported version.");
+                }
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (final IOException e) {
+                        // Do nothing.
+                    }
+                }
+            }
+        } catch (final IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "IOException was emitted: " + e.getMessage());
+
+            if (errorFileNameList != null) {
+                errorFileNameList.add(uri.toString());
+            }
+            return false;
+        } catch (final VCardNotSupportedException e) {
+            if ((e instanceof VCardNestedException) && throwNestedException) {
+                throw (VCardNestedException) e;
+            }
+            if (errorFileNameList != null) {
+                errorFileNameList.add(uri.toString());
+            }
+            return false;
+        } catch (final VCardException e) {
+            if (errorFileNameList != null) {
+                errorFileNameList.add(uri.toString());
+            }
+            return false;
+        }
+        return true;
+    }
+
+    class ContactVCardEntryHandler implements CustomVCardEntryConstructor.EntryHandler {
+        final CountDownLatch mSignal;
+
+        public ContactVCardEntryHandler(final CountDownLatch signal) {
+            mSignal = signal;
+        }
+
+        @Override
+        public void onStart() {
+        }
+
+        @Override
+        @DoesNotRunOnMainThread
+        public void onEntryCreated(final CustomVCardEntry entry) {
+            Assert.isNotMainThread();
+            final String displayName = entry.getDisplayName();
+            final List<VCardEntry.PhotoData> photos = entry.getPhotoList();
+            Uri avatarUri = null;
+            if (photos != null && photos.size() > 0) {
+                // The photo data is in bytes form, so we need to persist it in our temp directory
+                // so that ContactIconView can load it and display it later
+                // (and cache it, of course).
+                for (final VCardEntry.PhotoData photo : photos) {
+                    final byte[] photoBytes = photo.getBytes();
+                    if (photoBytes != null) {
+                        final InputStream inputStream = new ByteArrayInputStream(photoBytes);
+                        try {
+                            avatarUri = UriUtil.persistContentToScratchSpace(inputStream);
+                            if (avatarUri != null) {
+                                // Just load the first avatar and be done. Want more? wait for V2.
+                                break;
+                            }
+                        } finally {
+                            try {
+                                inputStream.close();
+                            } catch (final IOException e) {
+                                // Do nothing.
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Fall back to generated avatar.
+            if (avatarUri == null) {
+                String destination = null;
+                final List<VCardEntry.PhoneData> phones = entry.getPhoneList();
+                if (phones != null && phones.size() > 0) {
+                    destination = PhoneUtils.getDefault().getCanonicalBySystemLocale(
+                            phones.get(0).getNumber());
+                }
+
+                if (destination == null) {
+                    final List<VCardEntry.EmailData> emails = entry.getEmailList();
+                    if (emails != null && emails.size() > 0) {
+                        destination = emails.get(0).getAddress();
+                    }
+                }
+                avatarUri = AvatarUriUtil.createAvatarUri(null, displayName, destination, null);
+            }
+
+            // Add the loaded vcard to the list.
+            mLoadedVCards.add(new VCardResourceEntry(entry, avatarUri));
+        }
+
+        @Override
+        public void onEnd() {
+            // Finished loading all vCard entries, signal the loading thread to proceed with the
+            // result.
+            if (mLoadedVCards.size() > 0) {
+                mLoadedResource = new VCardResource(getKey(), mLoadedVCards);
+            }
+            mSignal.countDown();
+        }
+    }
+
+    @Override
+    public int getRequestType() {
+        return MediaRequest.REQUEST_LOAD_MEDIA;
+    }
+
+    @Override
+    public MediaRequestDescriptor<VCardResource> getDescriptor() {
+        return mDescriptor;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VCardRequestDescriptor.java b/src/com/android/messaging/datamodel/media/VCardRequestDescriptor.java
new file mode 100644
index 0000000..4084851
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VCardRequestDescriptor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.messaging.util.Assert;
+
+public class VCardRequestDescriptor extends MediaRequestDescriptor<VCardResource> {
+    public final Uri vCardUri;
+
+    public VCardRequestDescriptor(final Uri vCardUri) {
+        Assert.notNull(vCardUri);
+        this.vCardUri = vCardUri;
+    }
+
+    @Override
+    public MediaRequest<VCardResource> buildSyncMediaRequest(Context context) {
+        return new VCardRequest(context, this);
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VCardResource.java b/src/com/android/messaging/datamodel/media/VCardResource.java
new file mode 100644
index 0000000..edf5e88
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VCardResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import java.util.List;
+
+/**
+ * Holds cached information of VCard contact info.
+ * The temporarily persisted avatar icon Uri is tied to the VCardResource. As a result, whenever
+ * the VCardResource is no longer used (i.e. close() is called), we need to asynchronously
+ * delete the avatar image from temp storage since no one will have reference to the avatar Uri
+ * again. The next time the same VCard is displayed, since the old resource has been evicted from
+ * the memory cache, we'll load and persist the avatar icon again.
+ */
+public class VCardResource extends RefCountedMediaResource {
+    private final List<VCardResourceEntry> mVCards;
+
+    public VCardResource(final String key, final List<VCardResourceEntry> vcards) {
+        super(key);
+        mVCards = vcards;
+    }
+
+    public List<VCardResourceEntry> getVCards() {
+        return mVCards;
+    }
+
+    @Override
+    public int getMediaSize() {
+        // Instead of track VCards by size in kilobytes, we track them by count.
+        return 0;
+    }
+
+    @Override
+    protected void close() {
+        for (final VCardResourceEntry vcard : mVCards) {
+            vcard.close();
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VCardResourceEntry.java b/src/com/android/messaging/datamodel/media/VCardResourceEntry.java
new file mode 100644
index 0000000..f0f7591
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VCardResourceEntry.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import androidx.collection.ArrayMap;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.vcard.VCardEntry;
+import com.android.vcard.VCardEntry.EmailData;
+import com.android.vcard.VCardEntry.ImData;
+import com.android.vcard.VCardEntry.NoteData;
+import com.android.vcard.VCardEntry.OrganizationData;
+import com.android.vcard.VCardEntry.PhoneData;
+import com.android.vcard.VCardEntry.PostalData;
+import com.android.vcard.VCardEntry.WebsiteData;
+import com.android.vcard.VCardProperty;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Holds one entry item (i.e. a single contact) within a VCard resource. It is able to take
+ * a VCardEntry and extract relevant information from it.
+ */
+public class VCardResourceEntry {
+    public static final String PROPERTY_KIND = "KIND";
+
+    public static final String KIND_LOCATION = "location";
+
+    private final List<VCardResourceEntry.VCardResourceEntryDestinationItem> mContactInfo;
+    private final Uri mAvatarUri;
+    private final String mDisplayName;
+    private final CustomVCardEntry mVCard;
+
+    public VCardResourceEntry(final CustomVCardEntry vcard, final Uri avatarUri) {
+        mContactInfo = getContactInfoFromVCardEntry(vcard);
+        mDisplayName = getDisplayNameFromVCardEntry(vcard);
+        mAvatarUri = avatarUri;
+        mVCard = vcard;
+    }
+
+    void close() {
+        // If the avatar image was temporarily saved in the scratch folder, remove that.
+        if (MediaScratchFileProvider.isMediaScratchSpaceUri(mAvatarUri)) {
+            SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                @Override
+                public void run() {
+                    Factory.get().getApplicationContext().getContentResolver().delete(
+                            mAvatarUri, null, null);
+                }
+            });
+        }
+    }
+
+    public String getKind() {
+        VCardProperty kindProperty = mVCard.getProperty(PROPERTY_KIND);
+        return kindProperty == null ? null : kindProperty.getRawValue();
+    }
+
+    public Uri getAvatarUri() {
+        return mAvatarUri;
+    }
+
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    public String getDisplayAddress() {
+        List<PostalData> postalList = mVCard.getPostalList();
+        if (postalList == null || postalList.size() < 1) {
+            return null;
+        }
+
+        return formatAddress(postalList.get(0));
+    }
+
+    public String getNotes() {
+        List<NoteData> notes = mVCard.getNotes();
+        if (notes == null || notes.size() == 0) {
+            return null;
+        }
+        StringBuilder noteBuilder = new StringBuilder();
+        for (NoteData note : notes) {
+            noteBuilder.append(note.getNote());
+        }
+        return noteBuilder.toString();
+    }
+
+    /**
+     * Returns a UI-facing representation that can be bound and consumed by the UI layer to display
+     * this VCard resource entry.
+     */
+    public PersonItemData getDisplayItem() {
+        return new PersonItemData() {
+            @Override
+            public Uri getAvatarUri() {
+                return VCardResourceEntry.this.getAvatarUri();
+            }
+
+            @Override
+            public String getDisplayName() {
+                return VCardResourceEntry.this.getDisplayName();
+            }
+
+            @Override
+            public String getDetails() {
+                return null;
+            }
+
+            @Override
+            public Intent getClickIntent() {
+                return null;
+            }
+
+            @Override
+            public long getContactId() {
+                return ContactUtil.INVALID_CONTACT_ID;
+            }
+
+            @Override
+            public String getLookupKey() {
+                return null;
+            }
+
+            @Override
+            public String getNormalizedDestination() {
+                return null;
+            }
+        };
+    }
+
+    public List<VCardResourceEntry.VCardResourceEntryDestinationItem> getContactInfo() {
+        return mContactInfo;
+    }
+
+    private static List<VCardResourceEntryDestinationItem> getContactInfoFromVCardEntry(
+            final VCardEntry vcard) {
+        final Resources resources = Factory.get().getApplicationContext().getResources();
+        final List<VCardResourceEntry.VCardResourceEntryDestinationItem> retList =
+                new ArrayList<VCardResourceEntry.VCardResourceEntryDestinationItem>();
+        if (vcard.getPhoneList() != null) {
+            for (final PhoneData phone : vcard.getPhoneList()) {
+                final Intent intent = new Intent(Intent.ACTION_DIAL);
+                intent.setData(Uri.parse("tel:" + phone.getNumber()));
+                retList.add(new VCardResourceEntryDestinationItem(phone.getNumber(),
+                        Phone.getTypeLabel(resources, phone.getType(), phone.getLabel()).toString(),
+                        intent));
+            }
+        }
+
+        if (vcard.getEmailList() != null) {
+            for (final EmailData email : vcard.getEmailList()) {
+                final Intent intent = new Intent(Intent.ACTION_SENDTO);
+                intent.setData(Uri.parse("mailto:"));
+                intent.putExtra(Intent.EXTRA_EMAIL, new String[] { email.getAddress() });
+                retList.add(new VCardResourceEntryDestinationItem(email.getAddress(),
+                        Phone.getTypeLabel(resources, email.getType(),
+                                email.getLabel()).toString(), intent));
+            }
+        }
+
+        if (vcard.getPostalList() != null) {
+            for (final PostalData postalData : vcard.getPostalList()) {
+                String type;
+                try {
+                    type = resources.
+                            getStringArray(android.R.array.postalAddressTypes)
+                            [postalData.getType() - 1];
+                } catch (final NotFoundException ex) {
+                    type = resources.getStringArray(android.R.array.postalAddressTypes)[2];
+                } catch (final Exception e) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "createContactItem postal Exception:" + e);
+                    type = resources.getStringArray(android.R.array.postalAddressTypes)[2];
+                }
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                final String address = formatAddress(postalData);
+                try {
+                    intent.setData(Uri.parse("geo:0,0?q=" + URLEncoder.encode(address, "UTF-8")));
+                } catch (UnsupportedEncodingException e) {
+                    intent = null;
+                }
+
+                retList.add(new VCardResourceEntryDestinationItem(address, type, intent));
+            }
+        }
+
+        if (vcard.getImList() != null) {
+            for (final ImData imData : vcard.getImList()) {
+                String type = null;
+                try {
+                    type = resources.
+                            getString(Im.getProtocolLabelResource(imData.getProtocol()));
+                } catch (final NotFoundException ex) {
+                    // Do nothing since this implies an empty label.
+                }
+                retList.add(new VCardResourceEntryDestinationItem(imData.getAddress(), type, null));
+            }
+        }
+
+        if (vcard.getOrganizationList() != null) {
+            for (final OrganizationData organtization : vcard.getOrganizationList()) {
+                String type = null;
+                try {
+                     type = resources.getString(Organization.getTypeLabelResource(
+                                    organtization.getType()));
+                } catch (final NotFoundException ex) {
+                    //set other kind as "other"
+                    type = resources.getStringArray(android.R.array.organizationTypes)[1];
+                } catch (final Exception e) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "createContactItem org Exception:" + e);
+                    type = resources.getStringArray(android.R.array.organizationTypes)[1];
+                }
+                retList.add(new VCardResourceEntryDestinationItem(
+                        organtization.getOrganizationName(), type, null));
+            }
+        }
+
+        if (vcard.getWebsiteList() != null) {
+            for (final WebsiteData web : vcard.getWebsiteList()) {
+                if (web != null && TextUtils.isGraphic(web.getWebsite())){
+                    String website = web.getWebsite();
+                    if (!website.startsWith("http://") && !website.startsWith("https://")) {
+                        // Prefix required for parsing to end up with a scheme and result in
+                        // navigation
+                        website = "http://" + website;
+                    }
+                    final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(website));
+                    retList.add(new VCardResourceEntryDestinationItem(web.getWebsite(), null,
+                            intent));
+                }
+            }
+        }
+
+        if (vcard.getBirthday() != null) {
+             final String birthday = vcard.getBirthday();
+             if (TextUtils.isGraphic(birthday)){
+                 retList.add(new VCardResourceEntryDestinationItem(birthday,
+                         resources.getString(R.string.vcard_detail_birthday_label), null));
+             }
+        }
+
+        if (vcard.getNotes() != null) {
+            for (final NoteData note : vcard.getNotes()) {
+                 final ArrayMap<String, String> curChildMap = new ArrayMap<String, String>();
+                 if (TextUtils.isGraphic(note.getNote())){
+                     retList.add(new VCardResourceEntryDestinationItem(note.getNote(),
+                             resources.getString(R.string.vcard_detail_notes_label), null));
+                 }
+             }
+        }
+        return retList;
+    }
+
+    private static String formatAddress(final PostalData postalData) {
+        final StringBuilder sb = new StringBuilder();
+        final String poBox = postalData.getPobox();
+        if (!TextUtils.isEmpty(poBox)) {
+            sb.append(poBox);
+            sb.append(" ");
+        }
+        final String extendedAddress = postalData.getExtendedAddress();
+        if (!TextUtils.isEmpty(extendedAddress)) {
+            sb.append(extendedAddress);
+            sb.append(" ");
+        }
+        final String street = postalData.getStreet();
+        if (!TextUtils.isEmpty(street)) {
+            sb.append(street);
+            sb.append(" ");
+        }
+        final String localty = postalData.getLocalty();
+        if (!TextUtils.isEmpty(localty)) {
+            sb.append(localty);
+            sb.append(" ");
+        }
+        final String region = postalData.getRegion();
+        if (!TextUtils.isEmpty(region)) {
+            sb.append(region);
+            sb.append(" ");
+        }
+        final String postalCode = postalData.getPostalCode();
+        if (!TextUtils.isEmpty(postalCode)) {
+            sb.append(postalCode);
+            sb.append(" ");
+        }
+        final String country = postalData.getCountry();
+        if (!TextUtils.isEmpty(country)) {
+            sb.append(country);
+        }
+        return sb.toString();
+    }
+
+    private static String getDisplayNameFromVCardEntry(final VCardEntry vcard) {
+        String name = vcard.getDisplayName();
+        if (name == null) {
+            vcard.consolidateFields();
+            name = vcard.getDisplayName();
+        }
+        return name;
+    }
+
+    /**
+     * Represents one entry line (e.g. phone number and phone label) for a single contact. Each
+     * VCardResourceEntry may hold one or more VCardResourceEntryDestinationItem's.
+     */
+    public static class VCardResourceEntryDestinationItem {
+        private final String mDisplayDestination;
+        private final String mDestinationType;
+        private final Intent mClickIntent;
+        public VCardResourceEntryDestinationItem(final String displayDestination,
+                final String destinationType, final Intent clickIntent) {
+            mDisplayDestination = displayDestination;
+            mDestinationType = destinationType;
+            mClickIntent = clickIntent;
+        }
+
+        /**
+         * Returns a UI-facing representation that can be bound and consumed by the UI layer to
+         * display this VCard resource destination entry.
+         */
+        public PersonItemData getDisplayItem() {
+            return new PersonItemData() {
+                @Override
+                public Uri getAvatarUri() {
+                    return null;
+                }
+
+                @Override
+                public String getDisplayName() {
+                    return mDisplayDestination;
+                }
+
+                @Override
+                public String getDetails() {
+                    return mDestinationType;
+                }
+
+                @Override
+                public Intent getClickIntent() {
+                    return mClickIntent;
+                }
+
+                @Override
+                public long getContactId() {
+                    return ContactUtil.INVALID_CONTACT_ID;
+                }
+
+                @Override
+                public String getLookupKey() {
+                    return null;
+                }
+
+                @Override
+                public String getNormalizedDestination() {
+                    return null;
+                }
+            };
+        }
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java
new file mode 100644
index 0000000..73ce5e0
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import com.android.messaging.util.MediaMetadataRetrieverWrapper;
+import com.android.messaging.util.MediaUtil;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Class to request a video thumbnail.
+ * Users of this class as responsible for checking {@link #shouldShowIncomingVideoThumbnails}
+ */
+public class VideoThumbnailRequest extends ImageRequest<UriImageRequestDescriptor> {
+
+    public VideoThumbnailRequest(final Context context,
+            final UriImageRequestDescriptor descriptor) {
+        super(context, descriptor);
+    }
+
+    public static boolean shouldShowIncomingVideoThumbnails() {
+        return MediaUtil.canAutoAccessIncomingMedia();
+    }
+
+    @Override
+    protected InputStream getInputStreamForResource() throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    protected boolean hasBitmapObject() {
+        return true;
+    }
+
+    @Override
+    protected Bitmap getBitmapForResource() throws IOException {
+        Bitmap bitmap = null;
+        // Get a thumbnail through MediaMetadataRetriever to get a representative frame at any time
+        // position instead.
+        final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
+        try {
+            retriever.setDataSource(mDescriptor.uri);
+            bitmap = retriever.getFrameAtTime();
+        } finally {
+            retriever.release();
+        }
+        if (bitmap != null) {
+            mDescriptor.updateSourceDimensions(bitmap.getWidth(), bitmap.getHeight());
+        }
+        return bitmap;
+    }
+}
diff --git a/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java b/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java
new file mode 100644
index 0000000..22f1871
--- /dev/null
+++ b/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.Context;
+
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.UriUtil;
+
+public class VideoThumbnailRequestDescriptor extends UriImageRequestDescriptor {
+    public VideoThumbnailRequestDescriptor(final long id, int desiredWidth, int desiredHeight,
+            int sourceWidth, int sourceHeight) {
+        super(UriUtil.getContentUriForMediaStoreId(id), desiredWidth, desiredHeight, sourceWidth,
+                sourceHeight, false /* canCompress */, false /* isStatic */,
+                false /* cropToCircle */,
+                ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+    }
+
+    @Override
+    public MediaRequest<ImageResource> buildSyncMediaRequest(Context context) {
+        return new VideoThumbnailRequest(context, this);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/Downloads.java b/src/com/android/messaging/mmslib/Downloads.java
new file mode 100644
index 0000000..9afc48c
--- /dev/null
+++ b/src/com/android/messaging/mmslib/Downloads.java
@@ -0,0 +1,807 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib;
+
+import android.app.DownloadManager;
+import android.content.Context;
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * The Download Manager
+ *
+ * @pending
+ */
+public final class Downloads {
+    private Downloads() {}
+
+    /**
+     * Implementation details
+     *
+     * Exposes constants used to interact with the download manager's
+     * content provider.
+     * The constants URI ... STATUS are the names of columns in the downloads table.
+     *
+     * @hide
+     */
+    public static final class Impl implements BaseColumns {
+        private Impl() {}
+
+        /**
+         * The permission to access the download manager
+         */
+        public static final String PERMISSION_ACCESS = "android.permission.ACCESS_DOWNLOAD_MANAGER";
+
+        /**
+         * The permission to access the download manager's advanced functions
+         */
+        public static final String PERMISSION_ACCESS_ADVANCED =
+                "android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED";
+
+        /**
+         * The permission to access the all the downloads in the manager.
+         */
+        public static final String PERMISSION_ACCESS_ALL =
+                "android.permission.ACCESS_ALL_DOWNLOADS";
+
+        /**
+         * The permission to directly access the download manager's cache
+         * directory
+         */
+        public static final String PERMISSION_CACHE = "android.permission.ACCESS_CACHE_FILESYSTEM";
+
+        /**
+         * The permission to send broadcasts on download completion
+         */
+        public static final String PERMISSION_SEND_INTENTS =
+                "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS";
+
+        /**
+         * The permission to download files to the cache partition that won't be automatically
+         * purged when space is needed.
+         */
+        public static final String PERMISSION_CACHE_NON_PURGEABLE =
+                "android.permission.DOWNLOAD_CACHE_NON_PURGEABLE";
+
+        /**
+         * The permission to download files without any system notification being shown.
+         */
+        public static final String PERMISSION_NO_NOTIFICATION =
+                "android.permission.DOWNLOAD_WITHOUT_NOTIFICATION";
+
+        /**
+         * The content:// URI to access downloads owned by the caller's UID.
+         */
+        public static final Uri CONTENT_URI =
+                Uri.parse("content://downloads/my_downloads");
+
+        /**
+         * The content URI for accessing all downloads across all UIDs (requires the
+         * ACCESS_ALL_DOWNLOADS permission).
+         */
+        public static final Uri ALL_DOWNLOADS_CONTENT_URI =
+                Uri.parse("content://downloads/all_downloads");
+
+        /** URI segment to access a publicly accessible downloaded file */
+        public static final String PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT = "public_downloads";
+
+        /**
+         * The content URI for accessing publicly accessible downloads (i.e., it requires no
+         * permissions to access this downloaded file)
+         */
+        public static final Uri PUBLICLY_ACCESSIBLE_DOWNLOADS_URI =
+                Uri.parse("content://downloads/" + PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT);
+
+        /**
+         * Broadcast Action: this is sent by the download manager to the app
+         * that had initiated a download when that download completes. The
+         * download's content: uri is specified in the intent's data.
+         */
+        public static final String ACTION_DOWNLOAD_COMPLETED =
+                "android.intent.action.DOWNLOAD_COMPLETED";
+
+        /**
+         * Broadcast Action: this is sent by the download manager to the app
+         * that had initiated a download when the user selects the notification
+         * associated with that download. The download's content: uri is specified
+         * in the intent's data if the click is associated with a single download,
+         * or Downloads.CONTENT_URI if the notification is associated with
+         * multiple downloads.
+         * Note: this is not currently sent for downloads that have completed
+         * successfully.
+         */
+        public static final String ACTION_NOTIFICATION_CLICKED =
+                "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
+
+        /**
+         * The name of the column containing the URI of the data being downloaded.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_URI = "uri";
+
+        /**
+         * The name of the column containing application-specific data.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read/Write</P>
+         */
+        public static final String COLUMN_APP_DATA = "entity";
+
+        /**
+         * The name of the column containing the flags that indicates whether
+         * the initiating application is capable of verifying the integrity of
+         * the downloaded file. When this flag is set, the download manager
+         * performs downloads and reports success even in some situations where
+         * it can't guarantee that the download has completed (e.g. when doing
+         * a byte-range request without an ETag, or when it can't determine
+         * whether a download fully completed).
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_NO_INTEGRITY = "no_integrity";
+
+        /**
+         * The name of the column containing the filename that the initiating
+         * application recommends. When possible, the download manager will attempt
+         * to use this filename, or a variation, as the actual name for the file.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_FILE_NAME_HINT = "hint";
+
+        /**
+         * The name of the column containing the filename where the downloaded data
+         * was actually stored.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String _DATA = "_data";
+
+        /**
+         * The name of the column containing the MIME type of the downloaded data.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_MIME_TYPE = "mimetype";
+
+        /**
+         * The name of the column containing the flag that controls the destination
+         * of the download. See the DESTINATION_* constants for a list of legal values.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_DESTINATION = "destination";
+
+        /**
+         * The name of the column containing the flags that controls whether the
+         * download is displayed by the UI. See the VISIBILITY_* constants for
+         * a list of legal values.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Init/Read/Write</P>
+         */
+        public static final String COLUMN_VISIBILITY = "visibility";
+
+        /**
+         * The name of the column containing the current control state  of the download.
+         * Applications can write to this to control (pause/resume) the download.
+         * the CONTROL_* constants for a list of legal values.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_CONTROL = "control";
+
+        /**
+         * The name of the column containing the current status of the download.
+         * Applications can read this to follow the progress of each download. See
+         * the STATUS_* constants for a list of legal values.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_STATUS = "status";
+
+        /**
+         * The name of the column containing the date at which some interesting
+         * status changed in the download. Stored as a System.currentTimeMillis()
+         * value.
+         * <P>Type: BIGINT</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_LAST_MODIFICATION = "lastmod";
+
+        /**
+         * The name of the column containing the package name of the application
+         * that initiating the download. The download manager will send
+         * notifications to a component in this package when the download completes.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_NOTIFICATION_PACKAGE = "notificationpackage";
+
+        /**
+         * The name of the column containing the component name of the class that
+         * will receive notifications associated with the download. The
+         * package/class combination is passed to
+         * Intent.setClassName(String,String).
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_NOTIFICATION_CLASS = "notificationclass";
+
+        /**
+         * If extras are specified when requesting a download they will be provided in the intent
+         * that is sent to the specified class and package when a download has finished.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras";
+
+        /**
+         * The name of the column contain the values of the cookie to be used for
+         * the download. This is used directly as the value for the Cookie: HTTP
+         * header that gets sent with the request.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_COOKIE_DATA = "cookiedata";
+
+        /**
+         * The name of the column containing the user agent that the initiating
+         * application wants the download manager to use for this download.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_USER_AGENT = "useragent";
+
+        /**
+         * The name of the column containing the referer (sic) that the initiating
+         * application wants the download manager to use for this download.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_REFERER = "referer";
+
+        /**
+         * The name of the column containing the total size of the file being
+         * downloaded.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_TOTAL_BYTES = "total_bytes";
+
+        /**
+         * The name of the column containing the size of the part of the file that
+         * has been downloaded so far.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_CURRENT_BYTES = "current_bytes";
+
+        /**
+         * The name of the column where the initiating application can provide the
+         * UID of another application that is allowed to access this download. If
+         * multiple applications share the same UID, all those applications will be
+         * allowed to access this download. This column can be updated after the
+         * download is initiated. This requires the permission
+         * android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Init</P>
+         */
+        public static final String COLUMN_OTHER_UID = "otheruid";
+
+        /**
+         * The name of the column where the initiating application can provided the
+         * title of this download. The title will be displayed ito the user in the
+         * list of downloads.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read/Write</P>
+         */
+        public static final String COLUMN_TITLE = "title";
+
+        /**
+         * The name of the column where the initiating application can provide the
+         * description of this download. The description will be displayed to the
+         * user in the list of downloads.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Init/Read/Write</P>
+         */
+        public static final String COLUMN_DESCRIPTION = "description";
+
+        /**
+         * The name of the column indicating whether the download was requesting through the public
+         * API.  This controls some differences in behavior.
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_IS_PUBLIC_API = "is_public_api";
+
+        /**
+         * The name of the column holding a bitmask of allowed network types.  This is only used for
+         * public API downloads.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types";
+
+        /**
+         * The name of the column indicating whether roaming connections can be used.  This is only
+         * used for public API downloads.
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_ALLOW_ROAMING = "allow_roaming";
+
+        /**
+         * The name of the column indicating whether metered connections can be used.  This is only
+         * used for public API downloads.
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_ALLOW_METERED = "allow_metered";
+
+        /**
+         * Whether or not this download should be displayed in the system's Downloads UI.  Defaults
+         * to true.
+         * <P>Type: INTEGER</P>
+         * <P>Owner can Init/Read</P>
+         */
+        public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui";
+
+        /**
+         * If true, the user has confirmed that this download can proceed over the mobile network
+         * even though it exceeds the recommended maximum size.
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT =
+            "bypass_recommended_size_limit";
+
+        /**
+         * Set to true if this download is deleted. It is completely removed from the database
+         * when MediaProvider database also deletes the metadata asociated with this downloaded
+         * file.
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_DELETED = "deleted";
+
+        /**
+         * The URI to the corresponding entry in MediaProvider for this downloaded entry. It is
+         * used to delete the entries from MediaProvider database when it is deleted from the
+         * downloaded list.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
+
+        /**
+         * The column that is used to remember whether the media scanner was invoked.
+         * It can take the values: null or 0(not scanned), 1(scanned), 2 (not scannable).
+         * <P>Type: TEXT</P>
+         */
+        public static final String COLUMN_MEDIA_SCANNED = "scanned";
+
+        /**
+         * The column with errorMsg for a failed downloaded.
+         * Used only for debugging purposes.
+         * <P>Type: TEXT</P>
+         */
+        public static final String COLUMN_ERROR_MSG = "errorMsg";
+
+        /**
+         *  This column stores the source of the last update to this row.
+         *  This column is only for internal use.
+         *  Valid values are indicated by LAST_UPDATESRC_* constants.
+         * <P>Type: INT</P>
+         */
+        public static final String COLUMN_LAST_UPDATESRC = "lastUpdateSrc";
+
+        /** The column that is used to count retries */
+        public static final String COLUMN_FAILED_CONNECTIONS = "numfailed";
+
+        /**
+         * default value for {@link #COLUMN_LAST_UPDATESRC}.
+         * This value is used when this column's value is not relevant.
+         */
+        public static final int LAST_UPDATESRC_NOT_RELEVANT = 0;
+
+        /**
+         * One of the values taken by {@link #COLUMN_LAST_UPDATESRC}.
+         * This value is used when the update is NOT to be relayed to the DownloadService
+         * (and thus spare DownloadService from scanning the database when this change occurs)
+         */
+        public static final int LAST_UPDATESRC_DONT_NOTIFY_DOWNLOADSVC = 1;
+
+        /*
+         * Lists the destinations that an application can specify for a download.
+         */
+
+        /**
+         * This download will be saved to the external storage. This is the
+         * default behavior, and should be used for any file that the user
+         * can freely access, copy, delete. Even with that destination,
+         * unencrypted DRM files are saved in secure internal storage.
+         * Downloads to the external destination only write files for which
+         * there is a registered handler. The resulting files are accessible
+         * by filename to all applications.
+         */
+        public static final int DESTINATION_EXTERNAL = 0;
+
+        /**
+         * This download will be saved to the download manager's private
+         * partition. This is the behavior used by applications that want to
+         * download private files that are used and deleted soon after they
+         * get downloaded. All file types are allowed, and only the initiating
+         * application can access the file (indirectly through a content
+         * provider). This requires the
+         * android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED permission.
+         */
+        public static final int DESTINATION_CACHE_PARTITION = 1;
+
+        /**
+         * This download will be saved to the download manager's private
+         * partition and will be purged as necessary to make space. This is
+         * for private files (similar to CACHE_PARTITION) that aren't deleted
+         * immediately after they are used, and are kept around by the download
+         * manager as long as space is available.
+         */
+        public static final int DESTINATION_CACHE_PARTITION_PURGEABLE = 2;
+
+        /**
+         * This download will be saved to the download manager's private
+         * partition, as with DESTINATION_CACHE_PARTITION, but the download
+         * will not proceed if the user is on a roaming data connection.
+         */
+        public static final int DESTINATION_CACHE_PARTITION_NOROAMING = 3;
+
+        /**
+         * This download will be saved to the location given by the file URI in
+         * {@link #COLUMN_FILE_NAME_HINT}.
+         */
+        public static final int DESTINATION_FILE_URI = 4;
+
+        /**
+         * This download will be saved to the system cache ("/cache")
+         * partition. This option is only used by system apps and so it requires
+         * android.permission.ACCESS_CACHE_FILESYSTEM permission.
+         */
+        public static final int DESTINATION_SYSTEMCACHE_PARTITION = 5;
+
+        /**
+         * This download was completed by the caller (i.e., NOT downloadmanager)
+         * and caller wants to have this download displayed in Downloads App.
+         */
+        public static final int DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD = 6;
+
+        /**
+         * This download is allowed to run.
+         */
+        public static final int CONTROL_RUN = 0;
+
+        /**
+         * This download must pause at the first opportunity.
+         */
+        public static final int CONTROL_PAUSED = 1;
+
+        /*
+         * Lists the states that the download manager can set on a download
+         * to notify applications of the download progress.
+         * The codes follow the HTTP families:<br>
+         * 1xx: informational<br>
+         * 2xx: success<br>
+         * 3xx: redirects (not used by the download manager)<br>
+         * 4xx: client errors<br>
+         * 5xx: server errors
+         */
+
+        /**
+         * Returns whether the status is informational (i.e. 1xx).
+         */
+        public static boolean isStatusInformational(int status) {
+            return (status >= 100 && status < 200);
+        }
+
+        /**
+         * Returns whether the status is a success (i.e. 2xx).
+         */
+        public static boolean isStatusSuccess(int status) {
+            return (status >= 200 && status < 300);
+        }
+
+        /**
+         * Returns whether the status is an error (i.e. 4xx or 5xx).
+         */
+        public static boolean isStatusError(int status) {
+            return (status >= 400 && status < 600);
+        }
+
+        /**
+         * Returns whether the status is a client error (i.e. 4xx).
+         */
+        public static boolean isStatusClientError(int status) {
+            return (status >= 400 && status < 500);
+        }
+
+        /**
+         * Returns whether the status is a server error (i.e. 5xx).
+         */
+        public static boolean isStatusServerError(int status) {
+            return (status >= 500 && status < 600);
+        }
+
+        /**
+         * this method determines if a notification should be displayed for a
+         * given {@link #COLUMN_VISIBILITY} value
+         * @param visibility the value of {@link #COLUMN_VISIBILITY}.
+         * @return true if the notification should be displayed. false otherwise.
+         */
+        public static boolean isNotificationToBeDisplayed(int visibility) {
+            return visibility == DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED ||
+                    visibility == DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION;
+        }
+
+        /**
+         * Returns whether the download has completed (either with success or
+         * error).
+         */
+        public static boolean isStatusCompleted(int status) {
+            return (status >= 200 && status < 300) || (status >= 400 && status < 600);
+        }
+
+        /**
+         * This download hasn't stated yet
+         */
+        public static final int STATUS_PENDING = 190;
+
+        /**
+         * This download has started
+         */
+        public static final int STATUS_RUNNING = 192;
+
+        /**
+         * This download has been paused by the owning app.
+         */
+        public static final int STATUS_PAUSED_BY_APP = 193;
+
+        /**
+         * This download encountered some network error and is waiting before retrying the request.
+         */
+        public static final int STATUS_WAITING_TO_RETRY = 194;
+
+        /**
+         * This download is waiting for network connectivity to proceed.
+         */
+        public static final int STATUS_WAITING_FOR_NETWORK = 195;
+
+        /**
+         * This download exceeded a size limit for mobile networks and is waiting for a Wi-Fi
+         * connection to proceed.
+         */
+        public static final int STATUS_QUEUED_FOR_WIFI = 196;
+
+        /**
+         * This download couldn't be completed due to insufficient storage
+         * space.  Typically, this is because the SD card is full.
+         */
+        public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 198;
+
+        /**
+         * This download couldn't be completed because no external storage
+         * device was found.  Typically, this is because the SD card is not
+         * mounted.
+         */
+        public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 199;
+
+        /**
+         * This download has successfully completed.
+         * Warning: there might be other status values that indicate success
+         * in the future.
+         * Use isSucccess() to capture the entire category.
+         */
+        public static final int STATUS_SUCCESS = 200;
+
+        /**
+         * This request couldn't be parsed. This is also used when processing
+         * requests with unknown/unsupported URI schemes.
+         */
+        public static final int STATUS_BAD_REQUEST = 400;
+
+        /**
+         * This download can't be performed because the content type cannot be
+         * handled.
+         */
+        public static final int STATUS_NOT_ACCEPTABLE = 406;
+
+        /**
+         * This download cannot be performed because the length cannot be
+         * determined accurately. This is the code for the HTTP error "Length
+         * Required", which is typically used when making requests that require
+         * a content length but don't have one, and it is also used in the
+         * client when a response is received whose length cannot be determined
+         * accurately (therefore making it impossible to know when a download
+         * completes).
+         */
+        public static final int STATUS_LENGTH_REQUIRED = 411;
+
+        /**
+         * This download was interrupted and cannot be resumed.
+         * This is the code for the HTTP error "Precondition Failed", and it is
+         * also used in situations where the client doesn't have an ETag at all.
+         */
+        public static final int STATUS_PRECONDITION_FAILED = 412;
+
+        /**
+         * The lowest-valued error status that is not an actual HTTP status code.
+         */
+        public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488;
+
+        /**
+         * The requested destination file already exists.
+         */
+        public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
+
+        /**
+         * Some possibly transient error occurred, but we can't resume the download.
+         */
+        public static final int STATUS_CANNOT_RESUME = 489;
+
+        /**
+         * This download was canceled
+         */
+        public static final int STATUS_CANCELED = 490;
+
+        /**
+         * This download has completed with an error.
+         * Warning: there will be other status values that indicate errors in
+         * the future. Use isStatusError() to capture the entire category.
+         */
+        public static final int STATUS_UNKNOWN_ERROR = 491;
+
+        /**
+         * This download couldn't be completed because of a storage issue.
+         * Typically, that's because the filesystem is missing or full.
+         * Use the more specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR}
+         * and {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate.
+         */
+        public static final int STATUS_FILE_ERROR = 492;
+
+        /**
+         * This download couldn't be completed because of an HTTP
+         * redirect response that the download manager couldn't
+         * handle.
+         */
+        public static final int STATUS_UNHANDLED_REDIRECT = 493;
+
+        /**
+         * This download couldn't be completed because of an
+         * unspecified unhandled HTTP code.
+         */
+        public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
+
+        /**
+         * This download couldn't be completed because of an
+         * error receiving or processing data at the HTTP level.
+         */
+        public static final int STATUS_HTTP_DATA_ERROR = 495;
+
+        /**
+         * This download couldn't be completed because of an
+         * HttpException while setting up the request.
+         */
+        public static final int STATUS_HTTP_EXCEPTION = 496;
+
+        /**
+         * This download couldn't be completed because there were
+         * too many redirects.
+         */
+        public static final int STATUS_TOO_MANY_REDIRECTS = 497;
+
+        /**
+         * This download has failed because requesting application has been
+         * blocked by {@link NetworkPolicyManager}.
+         *
+         * @hide
+         * @deprecated since behavior now uses
+         *             {@link #STATUS_WAITING_FOR_NETWORK}
+         */
+        @Deprecated
+        public static final int STATUS_BLOCKED = 498;
+
+        /** {@hide} */
+        public static String statusToString(int status) {
+            switch (status) {
+                case STATUS_PENDING: return "PENDING";
+                case STATUS_RUNNING: return "RUNNING";
+                case STATUS_PAUSED_BY_APP: return "PAUSED_BY_APP";
+                case STATUS_WAITING_TO_RETRY: return "WAITING_TO_RETRY";
+                case STATUS_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
+                case STATUS_QUEUED_FOR_WIFI: return "QUEUED_FOR_WIFI";
+                case STATUS_INSUFFICIENT_SPACE_ERROR: return "INSUFFICIENT_SPACE_ERROR";
+                case STATUS_DEVICE_NOT_FOUND_ERROR: return "DEVICE_NOT_FOUND_ERROR";
+                case STATUS_SUCCESS: return "SUCCESS";
+                case STATUS_BAD_REQUEST: return "BAD_REQUEST";
+                case STATUS_NOT_ACCEPTABLE: return "NOT_ACCEPTABLE";
+                case STATUS_LENGTH_REQUIRED: return "LENGTH_REQUIRED";
+                case STATUS_PRECONDITION_FAILED: return "PRECONDITION_FAILED";
+                case STATUS_FILE_ALREADY_EXISTS_ERROR: return "FILE_ALREADY_EXISTS_ERROR";
+                case STATUS_CANNOT_RESUME: return "CANNOT_RESUME";
+                case STATUS_CANCELED: return "CANCELED";
+                case STATUS_UNKNOWN_ERROR: return "UNKNOWN_ERROR";
+                case STATUS_FILE_ERROR: return "FILE_ERROR";
+                case STATUS_UNHANDLED_REDIRECT: return "UNHANDLED_REDIRECT";
+                case STATUS_UNHANDLED_HTTP_CODE: return "UNHANDLED_HTTP_CODE";
+                case STATUS_HTTP_DATA_ERROR: return "HTTP_DATA_ERROR";
+                case STATUS_HTTP_EXCEPTION: return "HTTP_EXCEPTION";
+                case STATUS_TOO_MANY_REDIRECTS: return "TOO_MANY_REDIRECTS";
+                case STATUS_BLOCKED: return "BLOCKED";
+                default: return Integer.toString(status);
+            }
+        }
+
+        /**
+         * This download is visible but only shows in the notifications
+         * while it's in progress.
+         */
+        public static final int VISIBILITY_VISIBLE = DownloadManager.Request.VISIBILITY_VISIBLE;
+
+        /**
+         * This download is visible and shows in the notifications while
+         * in progress and after completion.
+         */
+        public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED =
+                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
+
+        /**
+         * This download doesn't show in the UI or in the notifications.
+         */
+        public static final int VISIBILITY_HIDDEN = DownloadManager.Request.VISIBILITY_HIDDEN;
+
+        /**
+         * Constants related to HTTP request headers associated with each download.
+         */
+        public static class RequestHeaders {
+            public static final String HEADERS_DB_TABLE = "request_headers";
+            public static final String COLUMN_DOWNLOAD_ID = "download_id";
+            public static final String COLUMN_HEADER = "header";
+            public static final String COLUMN_VALUE = "value";
+
+            /**
+             * Path segment to add to a download URI to retrieve request headers
+             */
+            public static final String URI_SEGMENT = "headers";
+
+            /**
+             * Prefix for ContentValues keys that contain HTTP header lines, to be passed to
+             * DownloadProvider.insert().
+             */
+            public static final String INSERT_KEY_PREFIX = "http_header_";
+        }
+    }
+
+    /**
+     * Query where clause for general querying.
+     */
+    private static final String QUERY_WHERE_CLAUSE = Impl.COLUMN_NOTIFICATION_PACKAGE + "=? AND "
+            + Impl.COLUMN_NOTIFICATION_CLASS + "=?";
+
+    /**
+     * Delete all the downloads for a package/class pair.
+     */
+    public static final void removeAllDownloadsByPackage(
+            Context context, String notificationPackage, String notificationClass) {
+        context.getContentResolver().delete(Impl.CONTENT_URI, QUERY_WHERE_CLAUSE,
+                new String[] { notificationPackage, notificationClass });
+    }
+}
diff --git a/src/com/android/messaging/mmslib/InvalidHeaderValueException.java b/src/com/android/messaging/mmslib/InvalidHeaderValueException.java
new file mode 100644
index 0000000..c141591
--- /dev/null
+++ b/src/com/android/messaging/mmslib/InvalidHeaderValueException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib;
+
+/**
+ * Thrown when an invalid header value was set.
+ */
+public class InvalidHeaderValueException extends MmsException {
+    private static final long serialVersionUID = -2053384496042052262L;
+
+    /**
+     * Constructs an InvalidHeaderValueException with no detailed message.
+     */
+    public InvalidHeaderValueException() {
+        super();
+    }
+
+    /**
+     * Constructs an InvalidHeaderValueException with the specified detailed message.
+     *
+     * @param message the detailed message.
+     */
+    public InvalidHeaderValueException(String message) {
+        super(message);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/MmsException.java b/src/com/android/messaging/mmslib/MmsException.java
new file mode 100644
index 0000000..173511d
--- /dev/null
+++ b/src/com/android/messaging/mmslib/MmsException.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib;
+
+/**
+ * A generic exception that is thrown by the Mms client.
+ */
+public class MmsException extends Exception {
+    private static final long serialVersionUID = -7323249827281485390L;
+
+    /**
+     * Creates a new MmsException.
+     */
+    public MmsException() {
+        super();
+    }
+
+    /**
+     * Creates a new MmsException with the specified detail message.
+     *
+     * @param message the detail message.
+     */
+    public MmsException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new MmsException with the specified cause.
+     *
+     * @param cause the cause.
+     */
+    public MmsException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Creates a new MmsException with the specified detail message and cause.
+     *
+     * @param message the detail message.
+     * @param cause the cause.
+     */
+    public MmsException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/SqliteWrapper.java b/src/com/android/messaging/mmslib/SqliteWrapper.java
new file mode 100644
index 0000000..8ef0e6f
--- /dev/null
+++ b/src/com/android/messaging/mmslib/SqliteWrapper.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 Esmertec AG.
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+
+import com.android.messaging.util.LogUtil;
+
+// Wrapper around content resolver methods to catch exceptions
+public final class SqliteWrapper {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private SqliteWrapper() {
+        // Forbidden being instantiated.
+    }
+
+    public static Cursor query(Context context, ContentResolver resolver, Uri uri,
+            String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+        try {
+            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
+        } catch (SQLiteException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when query", e);
+            return null;
+        } catch (IllegalArgumentException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when query", e);
+            return null;
+        }
+    }
+
+    public static int update(Context context, ContentResolver resolver, Uri uri,
+            ContentValues values, String where, String[] selectionArgs) {
+        try {
+            return resolver.update(uri, values, where, selectionArgs);
+        } catch (SQLiteException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when update", e);
+            return -1;
+        } catch (IllegalArgumentException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when update", e);
+            return -1;
+        }
+    }
+
+    public static int delete(Context context, ContentResolver resolver, Uri uri,
+            String where, String[] selectionArgs) {
+        try {
+            return resolver.delete(uri, where, selectionArgs);
+        } catch (SQLiteException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when delete", e);
+            return -1;
+        } catch (IllegalArgumentException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when delete", e);
+            return -1;
+        }
+    }
+
+    public static Uri insert(Context context, ContentResolver resolver,
+            Uri uri, ContentValues values) {
+        try {
+            return resolver.insert(uri, values);
+        } catch (SQLiteException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when insert", e);
+            return null;
+        } catch (IllegalArgumentException e) {
+            LogUtil.e(TAG, "SqliteWrapper: catch an exception when insert", e);
+            return null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/AcknowledgeInd.java b/src/com/android/messaging/mmslib/pdu/AcknowledgeInd.java
new file mode 100644
index 0000000..05494c0
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/AcknowledgeInd.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * M-Acknowledge.ind PDU.
+ */
+public class AcknowledgeInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-Acknowledge.ind pdu.
+     *
+     * @param mmsVersion    current viersion of mms
+     * @param transactionId the transaction-id value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     * @throws NullPointerException if transactionId is null.
+     */
+    public AcknowledgeInd(int mmsVersion, byte[] transactionId)
+            throws InvalidHeaderValueException {
+        super();
+
+        setMessageType(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    AcknowledgeInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Report-Allowed field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getReportAllowed() {
+        return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Report-Allowed field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReportAllowed(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/Base64.java b/src/com/android/messaging/mmslib/pdu/Base64.java
new file mode 100644
index 0000000..2f27117
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/Base64.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+public class Base64 {
+    /**
+     * Used to get the number of Quadruples.
+     */
+    static final int FOURBYTE = 4;
+
+    /**
+     * Byte used to pad output.
+     */
+    static final byte PAD = (byte) '=';
+
+    /**
+     * The base length.
+     */
+    static final int BASELENGTH = 255;
+
+    // Create arrays to hold the base64 characters
+    private static byte[] base64Alphabet = new byte[BASELENGTH];
+
+    // Populating the character arrays
+    static {
+        for (int i = 0; i < BASELENGTH; i++) {
+            base64Alphabet[i] = (byte) -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--) {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--) {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+        for (int i = '9'; i >= '0'; i--) {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param base64Data Byte array containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decodeBase64(byte[] base64Data) {
+        // RFC 2045 requires that we discard ALL non-Base64 characters
+        base64Data = discardNonBase64(base64Data);
+
+        // handle the edge case, so we don't have to worry about it later
+        if (base64Data.length == 0) {
+            return new byte[0];
+        }
+
+        int numberQuadruple = base64Data.length / FOURBYTE;
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
+
+        // Throw away anything not in base64Data
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        {
+            // this sizes the output array properly - rlw
+            int lastData = base64Data.length;
+            // ignore the '=' padding
+            while (base64Data[lastData - 1] == PAD) {
+                if (--lastData == 0) {
+                    return new byte[0];
+                }
+            }
+            decodedData = new byte[lastData - numberQuadruple];
+        }
+
+        for (int i = 0; i < numberQuadruple; i++) {
+            dataIndex = i * 4;
+            marker0 = base64Data[dataIndex + 2];
+            marker1 = base64Data[dataIndex + 3];
+
+            b1 = base64Alphabet[base64Data[dataIndex]];
+            b2 = base64Alphabet[base64Data[dataIndex + 1]];
+
+            if (marker0 != PAD && marker1 != PAD) {
+                //No PAD e.g 3cQl
+                b3 = base64Alphabet[marker0];
+                b4 = base64Alphabet[marker1];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                        (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
+            } else if (marker0 == PAD) {
+                //Two PAD e.g. 3c[Pad][Pad]
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+            } else if (marker1 == PAD) {
+                //One PAD e.g. 3cQ[Pad]
+                b3 = base64Alphabet[marker0];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                        (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            }
+            encodedIndex += 3;
+        }
+        return decodedData;
+    }
+
+    /**
+     * Check octect wheter it is a base64 encoding.
+     *
+     * @param octect to be checked byte
+     * @return ture if it is base64 encoding, false otherwise.
+     */
+    private static boolean isBase64(byte octect) {
+        if (octect == PAD) {
+            return true;
+        } else if (base64Alphabet[octect] == -1) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Discards any characters outside of the base64 alphabet, per
+     * the requirements on page 25 of RFC 2045 - "Any characters
+     * outside of the base64 alphabet are to be ignored in base64
+     * encoded data."
+     *
+     * @param data The base-64 encoded data to groom
+     * @return The data, less non-base64 characters (see RFC 2045).
+     */
+    static byte[] discardNonBase64(byte[] data) {
+        byte groomedData[] = new byte[data.length];
+        int bytesCopied = 0;
+
+        for (int i = 0; i < data.length; i++) {
+            if (isBase64(data[i])) {
+                groomedData[bytesCopied++] = data[i];
+            }
+        }
+
+        byte packedData[] = new byte[bytesCopied];
+
+        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+
+        return packedData;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/CharacterSets.java b/src/com/android/messaging/mmslib/pdu/CharacterSets.java
new file mode 100644
index 0000000..3a49e37
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/CharacterSets.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import androidx.collection.SimpleArrayMap;
+import android.util.SparseArray;
+
+import java.io.UnsupportedEncodingException;
+
+public class CharacterSets {
+    /**
+     * IANA assigned MIB enum numbers.
+     *
+     * From wap-230-wsp-20010705-a.pdf
+     * Any-charset = <Octet 128>
+     * Equivalent to the special RFC2616 charset value "*"
+     *
+     * Link to all the charsets: http://www.iana.org/assignments/character-sets/character-sets.xhtml
+     * Use Charset.availableCharsets() to see if a potential charset is supported in java:
+     *     private void dumpCharsets() {
+     *         logvv("dumpCharsets");
+     *         SortedMap<String, Charset> charsets = Charset.availableCharsets();
+     *         for (Entry<String, Charset> entry : charsets.entrySet()) {
+     *             String key = entry.getKey();
+     *             Charset value = entry.getValue();
+     *             logvv("charset key: " + key + " value: " + value);
+     *         }
+     *     }
+     *
+     * As of March 21, 2014, here is the list from dumpCharsets:
+     * Adobe-Standard-Encoding value: java.nio.charset.CharsetICU[Adobe-Standard-Encoding]
+     * Big5 value: java.nio.charset.CharsetICU[Big5]
+     * Big5-HKSCS value: java.nio.charset.CharsetICU[Big5-HKSCS]
+     * BOCU-1 value: java.nio.charset.CharsetICU[BOCU-1]
+     * CESU-8 value: java.nio.charset.CharsetICU[CESU-8]
+     * cp1363 value: java.nio.charset.CharsetICU[cp1363]
+     * cp851 value: java.nio.charset.CharsetICU[cp851]
+     * cp864 value: java.nio.charset.CharsetICU[cp864]
+     * EUC-JP value: java.nio.charset.CharsetICU[EUC-JP]
+     * EUC-KR value: java.nio.charset.CharsetICU[EUC-KR]
+     * GB18030 value: java.nio.charset.CharsetICU[GB18030]
+     * GBK value: java.nio.charset.CharsetICU[GBK]
+     * hp-roman8 value: java.nio.charset.CharsetICU[hp-roman8]
+     * HZ-GB-2312 value: java.nio.charset.CharsetICU[HZ-GB-2312]
+     * IBM-Thai value: java.nio.charset.CharsetICU[IBM-Thai]
+     * IBM00858 value: java.nio.charset.CharsetICU[IBM00858]
+     * IBM01140 value: java.nio.charset.CharsetICU[IBM01140]
+     * IBM01141 value: java.nio.charset.CharsetICU[IBM01141]
+     * IBM01142 value: java.nio.charset.CharsetICU[IBM01142]
+     * IBM01143 value: java.nio.charset.CharsetICU[IBM01143]
+     * IBM01144 value: java.nio.charset.CharsetICU[IBM01144]
+     * IBM01145 value: java.nio.charset.CharsetICU[IBM01145]
+     * IBM01146 value: java.nio.charset.CharsetICU[IBM01146]
+     * IBM01147 value: java.nio.charset.CharsetICU[IBM01147]
+     * IBM01148 value: java.nio.charset.CharsetICU[IBM01148]
+     * IBM01149 value: java.nio.charset.CharsetICU[IBM01149]
+     * IBM037 value: java.nio.charset.CharsetICU[IBM037]
+     * IBM1026 value: java.nio.charset.CharsetICU[IBM1026]
+     * IBM1047 value: java.nio.charset.CharsetICU[IBM1047]
+     * IBM273 value: java.nio.charset.CharsetICU[IBM273]
+     * IBM277 value: java.nio.charset.CharsetICU[IBM277]
+     * IBM278 value: java.nio.charset.CharsetICU[IBM278]
+     * IBM280 value: java.nio.charset.CharsetICU[IBM280]
+     * IBM284 value: java.nio.charset.CharsetICU[IBM284]
+     * IBM285 value: java.nio.charset.CharsetICU[IBM285]
+     * IBM290 value: java.nio.charset.CharsetICU[IBM290]
+     * IBM297 value: java.nio.charset.CharsetICU[IBM297]
+     * IBM420 value: java.nio.charset.CharsetICU[IBM420]
+     * IBM424 value: java.nio.charset.CharsetICU[IBM424]
+     * IBM437 value: java.nio.charset.CharsetICU[IBM437]
+     * IBM500 value: java.nio.charset.CharsetICU[IBM500]
+     * IBM775 value: java.nio.charset.CharsetICU[IBM775]
+     * IBM850 value: java.nio.charset.CharsetICU[IBM850]
+     * IBM852 value: java.nio.charset.CharsetICU[IBM852]
+     * IBM855 value: java.nio.charset.CharsetICU[IBM855]
+     * IBM857 value: java.nio.charset.CharsetICU[IBM857]
+     * IBM860 value: java.nio.charset.CharsetICU[IBM860]
+     * IBM861 value: java.nio.charset.CharsetICU[IBM861]
+     * IBM862 value: java.nio.charset.CharsetICU[IBM862]
+     * IBM863 value: java.nio.charset.CharsetICU[IBM863]
+     * IBM865 value: java.nio.charset.CharsetICU[IBM865]
+     * IBM866 value: java.nio.charset.CharsetICU[IBM866]
+     * IBM868 value: java.nio.charset.CharsetICU[IBM868]
+     * IBM869 value: java.nio.charset.CharsetICU[IBM869]
+     * IBM870 value: java.nio.charset.CharsetICU[IBM870]
+     * IBM871 value: java.nio.charset.CharsetICU[IBM871]
+     * IBM918 value: java.nio.charset.CharsetICU[IBM918]
+     * ISO-2022-CN value: java.nio.charset.CharsetICU[ISO-2022-CN]
+     * ISO-2022-CN-EXT value: java.nio.charset.CharsetICU[ISO-2022-CN-EXT]
+     * ISO-2022-JP value: java.nio.charset.CharsetICU[ISO-2022-JP]
+     * ISO-2022-JP-1 value: java.nio.charset.CharsetICU[ISO-2022-JP-1]
+     * ISO-2022-JP-2 value: java.nio.charset.CharsetICU[ISO-2022-JP-2]
+     * ISO-2022-KR value: java.nio.charset.CharsetICU[ISO-2022-KR]
+     * ISO-8859-1 value: java.nio.charset.CharsetICU[ISO-8859-1]
+     * ISO-8859-10 value: java.nio.charset.CharsetICU[ISO-8859-10]
+     * ISO-8859-13 value: java.nio.charset.CharsetICU[ISO-8859-13]
+     * ISO-8859-14 value: java.nio.charset.CharsetICU[ISO-8859-14]
+     * ISO-8859-15 value: java.nio.charset.CharsetICU[ISO-8859-15]
+     * ISO-8859-2 value: java.nio.charset.CharsetICU[ISO-8859-2]
+     * ISO-8859-3 value: java.nio.charset.CharsetICU[ISO-8859-3]
+     * ISO-8859-4 value: java.nio.charset.CharsetICU[ISO-8859-4]
+     * ISO-8859-5 value: java.nio.charset.CharsetICU[ISO-8859-5]
+     * ISO-8859-6 value: java.nio.charset.CharsetICU[ISO-8859-6]
+     * ISO-8859-7 value: java.nio.charset.CharsetICU[ISO-8859-7]
+     * ISO-8859-8 value: java.nio.charset.CharsetICU[ISO-8859-8]
+     * ISO-8859-9 value: java.nio.charset.CharsetICU[ISO-8859-9]
+     * KOI8-R value: java.nio.charset.CharsetICU[KOI8-R]
+     * KOI8-U value: java.nio.charset.CharsetICU[KOI8-U]
+     * macintosh value: java.nio.charset.CharsetICU[macintosh]
+     * SCSU value: java.nio.charset.CharsetICU[SCSU]
+     * Shift_JIS value: java.nio.charset.CharsetICU[Shift_JIS]
+     * TIS-620 value: java.nio.charset.CharsetICU[TIS-620]
+     * US-ASCII value: java.nio.charset.CharsetICU[US-ASCII]
+     * UTF-16 value: java.nio.charset.CharsetICU[UTF-16]
+     * UTF-16BE value: java.nio.charset.CharsetICU[UTF-16BE]
+     * UTF-16LE value: java.nio.charset.CharsetICU[UTF-16LE]
+     * UTF-32 value: java.nio.charset.CharsetICU[UTF-32]
+     * UTF-32BE value: java.nio.charset.CharsetICU[UTF-32BE]
+     * UTF-32LE value: java.nio.charset.CharsetICU[UTF-32LE]
+     * UTF-7 value: java.nio.charset.CharsetICU[UTF-7]
+     * UTF-8 value: java.nio.charset.CharsetICU[UTF-8]
+     * windows-1250 value: java.nio.charset.CharsetICU[windows-1250]
+     * windows-1251 value: java.nio.charset.CharsetICU[windows-1251]
+     * windows-1252 value: java.nio.charset.CharsetICU[windows-1252]
+     * windows-1253 value: java.nio.charset.CharsetICU[windows-1253]
+     * windows-1254 value: java.nio.charset.CharsetICU[windows-1254]
+     * windows-1255 value: java.nio.charset.CharsetICU[windows-1255]
+     * windows-1256 value: java.nio.charset.CharsetICU[windows-1256]
+     * windows-1257 value: java.nio.charset.CharsetICU[windows-1257]
+     * windows-1258 value: java.nio.charset.CharsetICU[windows-1258]
+     * x-compound-text value: java.nio.charset.CharsetICU[x-compound-text]
+     * x-ebcdic-xml-us value: java.nio.charset.CharsetICU[x-ebcdic-xml-us]
+     * x-gsm-03.38-2000 value: java.nio.charset.CharsetICU[x-gsm-03.38-2000]
+     * x-ibm-1047-s390 value: java.nio.charset.CharsetICU[x-ibm-1047-s390]
+     * x-ibm-1125_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1125_P100-1997]
+     * x-ibm-1129_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1129_P100-1997]
+     * x-ibm-1130_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1130_P100-1997]
+     * x-ibm-1131_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1131_P100-1997]
+     * x-ibm-1132_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-1132_P100-1998]
+     * x-ibm-1133_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1133_P100-1997]
+     * x-ibm-1137_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1137_P100-1999]
+     * x-ibm-1140-s390 value: java.nio.charset.CharsetICU[x-ibm-1140-s390]
+     * x-ibm-1141-s390 value: java.nio.charset.CharsetICU[x-ibm-1141-s390]
+     * x-ibm-1142-s390 value: java.nio.charset.CharsetICU[x-ibm-1142-s390]
+     * x-ibm-1143-s390 value: java.nio.charset.CharsetICU[x-ibm-1143-s390]
+     * x-ibm-1144-s390 value: java.nio.charset.CharsetICU[x-ibm-1144-s390]
+     * x-ibm-1145-s390 value: java.nio.charset.CharsetICU[x-ibm-1145-s390]
+     * x-ibm-1146-s390 value: java.nio.charset.CharsetICU[x-ibm-1146-s390]
+     * x-ibm-1147-s390 value: java.nio.charset.CharsetICU[x-ibm-1147-s390]
+     * x-ibm-1148-s390 value: java.nio.charset.CharsetICU[x-ibm-1148-s390]
+     * x-ibm-1149-s390 value: java.nio.charset.CharsetICU[x-ibm-1149-s390]
+     * x-ibm-1153-s390 value: java.nio.charset.CharsetICU[x-ibm-1153-s390]
+     * x-ibm-1154_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1154_P100-1999]
+     * x-ibm-1155_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1155_P100-1999]
+     * x-ibm-1156_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1156_P100-1999]
+     * x-ibm-1157_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1157_P100-1999]
+     * x-ibm-1158_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1158_P100-1999]
+     * x-ibm-1160_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1160_P100-1999]
+     * x-ibm-1162_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1162_P100-1999]
+     * x-ibm-1164_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-1164_P100-1999]
+     * x-ibm-1250_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1250_P100-1995]
+     * x-ibm-1251_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1251_P100-1995]
+     * x-ibm-1252_P100-2000 value: java.nio.charset.CharsetICU[x-ibm-1252_P100-2000]
+     * x-ibm-1253_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1253_P100-1995]
+     * x-ibm-1254_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1254_P100-1995]
+     * x-ibm-1255_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1255_P100-1995]
+     * x-ibm-1256_P110-1997 value: java.nio.charset.CharsetICU[x-ibm-1256_P110-1997]
+     * x-ibm-1257_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-1257_P100-1995]
+     * x-ibm-1258_P100-1997 value: java.nio.charset.CharsetICU[x-ibm-1258_P100-1997]
+     * x-ibm-12712-s390 value: java.nio.charset.CharsetICU[x-ibm-12712-s390]
+     * x-ibm-12712_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-12712_P100-1998]
+     * x-ibm-1373_P100-2002 value: java.nio.charset.CharsetICU[x-ibm-1373_P100-2002]
+     * x-ibm-1383_P110-1999 value: java.nio.charset.CharsetICU[x-ibm-1383_P110-1999]
+     * x-ibm-1386_P100-2001 value: java.nio.charset.CharsetICU[x-ibm-1386_P100-2001]
+     * x-ibm-16684_P110-2003 value: java.nio.charset.CharsetICU[x-ibm-16684_P110-2003]
+     * x-ibm-16804-s390 value: java.nio.charset.CharsetICU[x-ibm-16804-s390]
+     * x-ibm-16804_X110-1999 value: java.nio.charset.CharsetICU[x-ibm-16804_X110-1999]
+     * x-ibm-25546 value: java.nio.charset.CharsetICU[x-ibm-25546]
+     * x-ibm-33722_P12A_P12A-2009_U2 value:
+     *     java.nio.charset.CharsetICU[x-ibm-33722_P12A_P12A-2009_U2]
+     * x-ibm-37-s390 value: java.nio.charset.CharsetICU[x-ibm-37-s390]
+     * x-ibm-4517_P100-2005 value: java.nio.charset.CharsetICU[x-ibm-4517_P100-2005]
+     * x-ibm-4899_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-4899_P100-1998]
+     * x-ibm-4909_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-4909_P100-1999]
+     * x-ibm-4971_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-4971_P100-1999]
+     * x-ibm-5123_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-5123_P100-1999]
+     * x-ibm-5351_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-5351_P100-1998]
+     * x-ibm-5352_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-5352_P100-1998]
+     * x-ibm-5353_P100-1998 value: java.nio.charset.CharsetICU[x-ibm-5353_P100-1998]
+     * x-ibm-5478_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-5478_P100-1995]
+     * x-ibm-803_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-803_P100-1999]
+     * x-ibm-813_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-813_P100-1995]
+     * x-ibm-8482_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-8482_P100-1999]
+     * x-ibm-901_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-901_P100-1999]
+     * x-ibm-902_P100-1999 value: java.nio.charset.CharsetICU[x-ibm-902_P100-1999]
+     * x-ibm-9067_X100-2005 value: java.nio.charset.CharsetICU[x-ibm-9067_X100-2005]
+     * x-ibm-916_P100-1995 value: java.nio.charset.CharsetICU[x-ibm-916_P100-1995]
+     * x-IBM1006 value: java.nio.charset.CharsetICU[x-IBM1006]
+     * x-IBM1025 value: java.nio.charset.CharsetICU[x-IBM1025]
+     * x-IBM1097 value: java.nio.charset.CharsetICU[x-IBM1097]
+     * x-IBM1098 value: java.nio.charset.CharsetICU[x-IBM1098]
+     * x-IBM1112 value: java.nio.charset.CharsetICU[x-IBM1112]
+     * x-IBM1122 value: java.nio.charset.CharsetICU[x-IBM1122]
+     * x-IBM1123 value: java.nio.charset.CharsetICU[x-IBM1123]
+     * x-IBM1124 value: java.nio.charset.CharsetICU[x-IBM1124]
+     * x-IBM1153 value: java.nio.charset.CharsetICU[x-IBM1153]
+     * x-IBM1363 value: java.nio.charset.CharsetICU[x-IBM1363]
+     * x-IBM1364 value: java.nio.charset.CharsetICU[x-IBM1364]
+     * x-IBM1371 value: java.nio.charset.CharsetICU[x-IBM1371]
+     * x-IBM1388 value: java.nio.charset.CharsetICU[x-IBM1388]
+     * x-IBM1390 value: java.nio.charset.CharsetICU[x-IBM1390]
+     * x-IBM1399 value: java.nio.charset.CharsetICU[x-IBM1399]
+     * x-IBM33722 value: java.nio.charset.CharsetICU[x-IBM33722]
+     * x-IBM720 value: java.nio.charset.CharsetICU[x-IBM720]
+     * x-IBM737 value: java.nio.charset.CharsetICU[x-IBM737]
+     * x-IBM856 value: java.nio.charset.CharsetICU[x-IBM856]
+     * x-IBM867 value: java.nio.charset.CharsetICU[x-IBM867]
+     * x-IBM875 value: java.nio.charset.CharsetICU[x-IBM875]
+     * x-IBM922 value: java.nio.charset.CharsetICU[x-IBM922]
+     * x-IBM930 value: java.nio.charset.CharsetICU[x-IBM930]
+     * x-IBM933 value: java.nio.charset.CharsetICU[x-IBM933]
+     * x-IBM935 value: java.nio.charset.CharsetICU[x-IBM935]
+     * x-IBM937 value: java.nio.charset.CharsetICU[x-IBM937]
+     * x-IBM939 value: java.nio.charset.CharsetICU[x-IBM939]
+     * x-IBM942 value: java.nio.charset.CharsetICU[x-IBM942]
+     * x-IBM943 value: java.nio.charset.CharsetICU[x-IBM943]
+     * x-IBM949 value: java.nio.charset.CharsetICU[x-IBM949]
+     * x-IBM949C value: java.nio.charset.CharsetICU[x-IBM949C]
+     * x-IBM950 value: java.nio.charset.CharsetICU[x-IBM950]
+     * x-IBM954 value: java.nio.charset.CharsetICU[x-IBM954]
+     * x-IBM964 value: java.nio.charset.CharsetICU[x-IBM964]
+     * x-IBM970 value: java.nio.charset.CharsetICU[x-IBM970]
+     * x-IBM971 value: java.nio.charset.CharsetICU[x-IBM971]
+     * x-IMAP-mailbox-name value: java.nio.charset.CharsetICU[x-IMAP-mailbox-name]
+     * x-iscii-be value: java.nio.charset.CharsetICU[x-iscii-be]
+     * x-iscii-gu value: java.nio.charset.CharsetICU[x-iscii-gu]
+     * x-iscii-ka value: java.nio.charset.CharsetICU[x-iscii-ka]
+     * x-iscii-ma value: java.nio.charset.CharsetICU[x-iscii-ma]
+     * x-iscii-or value: java.nio.charset.CharsetICU[x-iscii-or]
+     * x-iscii-pa value: java.nio.charset.CharsetICU[x-iscii-pa]
+     * x-iscii-ta value: java.nio.charset.CharsetICU[x-iscii-ta]
+     * x-iscii-te value: java.nio.charset.CharsetICU[x-iscii-te]
+     * x-ISCII91 value: java.nio.charset.CharsetICU[x-ISCII91]
+     * x-ISO-2022-CN-CNS value: java.nio.charset.CharsetICU[x-ISO-2022-CN-CNS]
+     * x-iso-8859-11 value: java.nio.charset.CharsetICU[x-iso-8859-11]
+     * x-JavaUnicode value: java.nio.charset.CharsetICU[x-JavaUnicode]
+     * x-JavaUnicode2 value: java.nio.charset.CharsetICU[x-JavaUnicode2]
+     * x-JIS7 value: java.nio.charset.CharsetICU[x-JIS7]
+     * x-JIS8 value: java.nio.charset.CharsetICU[x-JIS8]
+     * x-LMBCS-1 value: java.nio.charset.CharsetICU[x-LMBCS-1]
+     * x-mac-centraleurroman value: java.nio.charset.CharsetICU[x-mac-centraleurroman]
+     * x-mac-cyrillic value: java.nio.charset.CharsetICU[x-mac-cyrillic]
+     * x-mac-greek value: java.nio.charset.CharsetICU[x-mac-greek]
+     * x-mac-turkish value: java.nio.charset.CharsetICU[x-mac-turkish]
+     * x-MS950-HKSCS value: java.nio.charset.CharsetICU[x-MS950-HKSCS]
+     * x-UnicodeBig value: java.nio.charset.CharsetICU[x-UnicodeBig]
+     * x-UTF-16LE-BOM value: java.nio.charset.CharsetICU[x-UTF-16LE-BOM]
+     * x-UTF16_OppositeEndian value: java.nio.charset.CharsetICU[x-UTF16_OppositeEndian]
+     * x-UTF16_PlatformEndian value: java.nio.charset.CharsetICU[x-UTF16_PlatformEndian]
+     * x-UTF32_OppositeEndian value: java.nio.charset.CharsetICU[x-UTF32_OppositeEndian]
+     * x-UTF32_PlatformEndian value: java.nio.charset.CharsetICU[x-UTF32_PlatformEndian]
+     *
+     */
+    public static final int ANY_CHARSET = 0x00;
+    public static final int US_ASCII    = 0x03;
+    public static final int ISO_8859_1  = 0x04;
+    public static final int ISO_8859_2  = 0x05;
+    public static final int ISO_8859_3  = 0x06;
+    public static final int ISO_8859_4  = 0x07;
+    public static final int ISO_8859_5  = 0x08;
+    public static final int ISO_8859_6  = 0x09;
+    public static final int ISO_8859_7  = 0x0A;
+    public static final int ISO_8859_8  = 0x0B;
+    public static final int ISO_8859_9  = 0x0C;
+    public static final int SHIFT_JIS   = 0x11;
+    public static final int EUC_JP      = 0x12;
+    public static final int EUC_KR      = 0x26;
+    public static final int ISO_2022_JP = 0x27;
+    public static final int ISO_2022_JP_2 = 0x28;
+    public static final int UTF_8       = 0x6A;
+    public static final int GBK         = 0x71;
+    public static final int GB18030     = 0x72;
+    public static final int GB2312      = 0x07E9;
+    public static final int BIG5        = 0x07EA;
+    public static final int UCS2        = 0x03E8;
+    public static final int UTF_16      = 0x03F7;
+    public static final int HZ_GB_2312  = 0x0825;
+
+    /**
+     * If the encoding of given data is unsupported, use UTF_8 to decode it.
+     */
+    public static final int DEFAULT_CHARSET = UTF_8;
+
+    /**
+     * Array of MIB enum numbers.
+     */
+    private static final int[] MIBENUM_NUMBERS = {
+            ANY_CHARSET,
+            US_ASCII,
+            ISO_8859_1,
+            ISO_8859_2,
+            ISO_8859_3,
+            ISO_8859_4,
+            ISO_8859_5,
+            ISO_8859_6,
+            ISO_8859_7,
+            ISO_8859_8,
+            ISO_8859_9,
+            SHIFT_JIS,
+            EUC_JP,
+            EUC_KR,
+            ISO_2022_JP,
+            ISO_2022_JP_2,
+            UTF_8,
+            GBK,
+            GB18030,
+            GB2312,
+            BIG5,
+            UCS2,
+            UTF_16,
+            HZ_GB_2312,
+    };
+
+    /**
+     * The Well-known-charset Mime name.
+     */
+    public static final String MIMENAME_ANY_CHARSET = "*";
+    public static final String MIMENAME_US_ASCII    = "us-ascii";
+    public static final String MIMENAME_ISO_8859_1  = "iso-8859-1";
+    public static final String MIMENAME_ISO_8859_2  = "iso-8859-2";
+    public static final String MIMENAME_ISO_8859_3  = "iso-8859-3";
+    public static final String MIMENAME_ISO_8859_4  = "iso-8859-4";
+    public static final String MIMENAME_ISO_8859_5  = "iso-8859-5";
+    public static final String MIMENAME_ISO_8859_6  = "iso-8859-6";
+    public static final String MIMENAME_ISO_8859_7  = "iso-8859-7";
+    public static final String MIMENAME_ISO_8859_8  = "iso-8859-8";
+    public static final String MIMENAME_ISO_8859_9  = "iso-8859-9";
+    public static final String MIMENAME_SHIFT_JIS   = "shift_JIS";
+    public static final String MIMENAME_EUC_JP      = "euc-jp";
+    public static final String MIMENAME_EUC_KR      = "euc-kr";
+    public static final String MIMENAME_ISO_2022_JP = "iso-2022-jp";
+    public static final String MIMENAME_ISO_2022_JP_2 = "iso-2022-jp-2";
+    public static final String MIMENAME_UTF_8       = "utf-8";
+    public static final String MIMENAME_GBK         = "gbk";
+    public static final String MIMENAME_GB18030     = "gb18030";
+    public static final String MIMENAME_GB2312      = "gb2312";
+    public static final String MIMENAME_BIG5        = "big5";
+    public static final String MIMENAME_UCS2        = "iso-10646-ucs-2";
+    public static final String MIMENAME_UTF_16      = "utf-16";
+    public static final String MIMENAME_HZ_GB_2312  = "hz-gb-2312";
+
+    public static final String DEFAULT_CHARSET_NAME = MIMENAME_UTF_8;
+
+    /**
+     * Array of the names of character sets.
+     */
+    private static final String[] MIME_NAMES = {
+            MIMENAME_ANY_CHARSET,
+            MIMENAME_US_ASCII,
+            MIMENAME_ISO_8859_1,
+            MIMENAME_ISO_8859_2,
+            MIMENAME_ISO_8859_3,
+            MIMENAME_ISO_8859_4,
+            MIMENAME_ISO_8859_5,
+            MIMENAME_ISO_8859_6,
+            MIMENAME_ISO_8859_7,
+            MIMENAME_ISO_8859_8,
+            MIMENAME_ISO_8859_9,
+            MIMENAME_SHIFT_JIS,
+            MIMENAME_EUC_JP,
+            MIMENAME_EUC_KR,
+            MIMENAME_ISO_2022_JP,
+            MIMENAME_ISO_2022_JP_2,
+            MIMENAME_UTF_8,
+            MIMENAME_GBK,
+            MIMENAME_GB18030,
+            MIMENAME_GB2312,
+            MIMENAME_BIG5,
+            MIMENAME_UCS2,
+            MIMENAME_UTF_16,
+            MIMENAME_HZ_GB_2312,
+    };
+
+    private static final SparseArray<String> MIBENUM_TO_NAME_MAP;
+
+    private static final SimpleArrayMap<String, Integer> NAME_TO_MIBENUM_MAP;
+
+    static {
+        // Create the HashMaps.
+        MIBENUM_TO_NAME_MAP = new SparseArray<String>();
+        NAME_TO_MIBENUM_MAP = new SimpleArrayMap<String, Integer>();
+        assert (MIBENUM_NUMBERS.length == MIME_NAMES.length);
+        final int count = MIBENUM_NUMBERS.length - 1;
+        for (int i = 0; i <= count; i++) {
+            MIBENUM_TO_NAME_MAP.put(MIBENUM_NUMBERS[i], MIME_NAMES[i]);
+            NAME_TO_MIBENUM_MAP.put(MIME_NAMES[i], MIBENUM_NUMBERS[i]);
+        }
+    }
+
+    private CharacterSets() {
+    } // Non-instantiatable
+
+    /**
+     * Map an MIBEnum number to the name of the charset which this number
+     * is assigned to by IANA.
+     *
+     * @param mibEnumValue An IANA assigned MIBEnum number.
+     * @return The name string of the charset.
+     */
+    public static String getMimeName(final int mibEnumValue)
+            throws UnsupportedEncodingException {
+        final String name = MIBENUM_TO_NAME_MAP.get(mibEnumValue);
+        if (name == null) {
+            throw new UnsupportedEncodingException();
+        }
+        return name;
+    }
+
+    /**
+     * Map a well-known charset name to its assigned MIBEnum number.
+     *
+     * @param mimeName The charset name.
+     * @return The MIBEnum number assigned by IANA for this charset.
+     */
+    public static int getMibEnumValue(final String mimeName)
+            throws UnsupportedEncodingException {
+        if (null == mimeName) {
+            return -1;
+        }
+
+        final Integer mibEnumValue = NAME_TO_MIBENUM_MAP.get(mimeName);
+        if (mibEnumValue == null) {
+            throw new UnsupportedEncodingException();
+        }
+        return mibEnumValue;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/DeliveryInd.java b/src/com/android/messaging/mmslib/pdu/DeliveryInd.java
new file mode 100644
index 0000000..5e1d873
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/DeliveryInd.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * M-Delivery.Ind Pdu.
+ */
+public class DeliveryInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public DeliveryInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_DELIVERY_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    DeliveryInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value, should not be null
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get Status value.
+     *
+     * @return the value
+     */
+    public int getStatus() {
+        return mPduHeaders.getOctet(PduHeaders.STATUS);
+    }
+
+    /**
+     * Set Status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.STATUS);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public EncodedStringValue getStatusText() {return null;}
+     *     public void setStatusText(EncodedStringValue value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/EncodedStringValue.java b/src/com/android/messaging/mmslib/pdu/EncodedStringValue.java
new file mode 100644
index 0000000..5870027
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/EncodedStringValue.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+/**
+ * Encoded-string-value = Text-string | Value-length Char-set Text-string
+ */
+public class EncodedStringValue implements Cloneable {
+    private static final String TAG = "EncodedStringValue";
+    private static final boolean DEBUG = false;
+    private static final boolean LOCAL_LOGV = false;
+
+    /**
+     * The Char-set value.
+     */
+    private int mCharacterSet;
+
+    /**
+     * The Text-string value.
+     */
+    private byte[] mData;
+
+    /**
+     * Constructor.
+     *
+     * @param charset the Char-set value
+     * @param data    the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public EncodedStringValue(int charset, byte[] data) {
+        // TODO: CharSet needs to be validated against MIBEnum.
+        if (null == data) {
+            throw new NullPointerException("EncodedStringValue: Text-string is null.");
+        }
+
+        mCharacterSet = charset;
+        mData = new byte[data.length];
+        System.arraycopy(data, 0, mData, 0, data.length);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param data the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public EncodedStringValue(byte[] data) {
+        this(CharacterSets.DEFAULT_CHARSET, data);
+    }
+
+    public EncodedStringValue(String data) {
+        this(CharacterSets.DEFAULT_CHARSET, data);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param charset
+     * @param data The text in Java String
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public EncodedStringValue(int charset, String data) {
+        if (null == data) {
+            throw new NullPointerException("EncodedStringValue: Text-string is null");
+        }
+        mCharacterSet = charset;
+        try {
+            mData = data.getBytes(CharacterSets.getMimeName(charset));
+        } catch (UnsupportedEncodingException e) {
+            Log.e(TAG, "Input encoding " + charset + " must be supported.", e);
+            mData = data.getBytes();
+        }
+    }
+
+    /**
+     * Get Char-set value.
+     *
+     * @return the value
+     */
+    public int getCharacterSet() {
+        return mCharacterSet;
+    }
+
+    /**
+     * Set Char-set value.
+     *
+     * @param charset the Char-set value
+     */
+    public void setCharacterSet(int charset) {
+        // TODO: CharSet needs to be validated against MIBEnum.
+        mCharacterSet = charset;
+    }
+
+    /**
+     * Get Text-string value.
+     *
+     * @return the value
+     */
+    public byte[] getTextString() {
+        byte[] byteArray = new byte[mData.length];
+
+        System.arraycopy(mData, 0, byteArray, 0, mData.length);
+        return byteArray;
+    }
+
+    /**
+     * Set Text-string value.
+     *
+     * @param textString the Text-string value
+     * @throws NullPointerException if Text-string value is null.
+     */
+    public void setTextString(byte[] textString) {
+        if (null == textString) {
+            throw new NullPointerException("EncodedStringValue: Text-string is null.");
+        }
+
+        mData = new byte[textString.length];
+        System.arraycopy(textString, 0, mData, 0, textString.length);
+    }
+
+    /**
+     * Convert this object to a {@link java.lang.String}. If the encoding of
+     * the EncodedStringValue is null or unsupported, it will be
+     * treated as iso-8859-1 encoding.
+     *
+     * @return The decoded String.
+     */
+    public String getString() {
+        if (CharacterSets.ANY_CHARSET == mCharacterSet) {
+            return new String(mData); // system default encoding.
+        } else {
+            try {
+                String name = CharacterSets.getMimeName(mCharacterSet);
+                return new String(mData, name);
+            } catch (UnsupportedEncodingException e) {
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, e.getMessage(), e);
+                }
+                try {
+                    return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
+                } catch (UnsupportedEncodingException exception) {
+                    return new String(mData); // system default encoding.
+                }
+            }
+        }
+    }
+
+    /**
+     * Append to Text-string.
+     *
+     * @param textString the textString to append
+     * @throws NullPointerException if the text String is null
+     *                              or an IOException occured.
+     */
+    public void appendTextString(byte[] textString) {
+        if (null == textString) {
+            throw new NullPointerException("Text-string is null.");
+        }
+
+        if (null == mData) {
+            mData = new byte[textString.length];
+            System.arraycopy(textString, 0, mData, 0, textString.length);
+        } else {
+            ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
+            try {
+                newTextString.write(mData);
+                newTextString.write(textString);
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new NullPointerException(
+                        "appendTextString: failed when write a new Text-string");
+            }
+
+            mData = newTextString.toByteArray();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public Object clone() throws CloneNotSupportedException {
+        int len = mData.length;
+        byte[] dstBytes = new byte[len];
+        System.arraycopy(mData, 0, dstBytes, 0, len);
+
+        try {
+            return new EncodedStringValue(mCharacterSet, dstBytes);
+        } catch (Exception e) {
+            Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
+            e.printStackTrace();
+            throw new CloneNotSupportedException(e.getMessage());
+        }
+    }
+
+    /**
+     * Split this encoded string around matches of the given pattern.
+     *
+     * @param pattern the delimiting pattern
+     * @return the array of encoded strings computed by splitting this encoded
+     *         string around matches of the given pattern
+     */
+    public EncodedStringValue[] split(String pattern) {
+        String[] temp = getString().split(pattern);
+        EncodedStringValue[] ret = new EncodedStringValue[temp.length];
+        for (int i = 0; i < ret.length; ++i) {
+            try {
+                ret[i] = new EncodedStringValue(mCharacterSet,
+                        temp[i].getBytes());
+            } catch (NullPointerException exception) {
+                // Can't arrive here
+                return null;
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Extract an EncodedStringValue[] from a given String.
+     */
+    public static EncodedStringValue[] extract(String src) {
+        String[] values = src.split(";");
+
+        ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
+        for (int i = 0; i < values.length; i++) {
+            if (values[i].length() > 0) {
+                list.add(new EncodedStringValue(values[i]));
+            }
+        }
+
+        int len = list.size();
+        if (len > 0) {
+            return list.toArray(new EncodedStringValue[len]);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Concatenate an EncodedStringValue[] into a single String.
+     */
+    public static String concat(EncodedStringValue[] addr) {
+        StringBuilder sb = new StringBuilder();
+        int maxIndex = addr.length - 1;
+        for (int i = 0; i <= maxIndex; i++) {
+            sb.append(addr[i].getString());
+            if (i < maxIndex) {
+                sb.append(";");
+            }
+        }
+
+        return sb.toString();
+    }
+
+    public static EncodedStringValue copy(EncodedStringValue value) {
+        if (value == null) {
+            return null;
+        }
+
+        return new EncodedStringValue(value.mCharacterSet, value.mData);
+    }
+
+    public static EncodedStringValue[] encodeStrings(String[] array) {
+        int count = array.length;
+        if (count > 0) {
+            EncodedStringValue[] encodedArray = new EncodedStringValue[count];
+            for (int i = 0; i < count; i++) {
+                encodedArray[i] = new EncodedStringValue(array[i]);
+            }
+            return encodedArray;
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/GenericPdu.java b/src/com/android/messaging/mmslib/pdu/GenericPdu.java
new file mode 100644
index 0000000..178dc5a
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/GenericPdu.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+public class GenericPdu {
+    /**
+     * The headers of pdu.
+     */
+    PduHeaders mPduHeaders = null;
+
+    /**
+     * Constructor.
+     */
+    public GenericPdu() {
+        mPduHeaders = new PduHeaders();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param headers Headers for this PDU.
+     */
+    GenericPdu(PduHeaders headers) {
+        mPduHeaders = headers;
+    }
+
+    /**
+     * Get the headers of this PDU.
+     *
+     * @return A PduHeaders of this PDU.
+     */
+    PduHeaders getPduHeaders() {
+        return mPduHeaders;
+    }
+
+    /**
+     * Get X-Mms-Message-Type field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getMessageType() {
+        return mPduHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
+    }
+
+    /**
+     * Set X-Mms-Message-Type field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if field's value is not Octet.
+     */
+    public void setMessageType(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.MESSAGE_TYPE);
+    }
+
+    /**
+     * Get X-Mms-MMS-Version field value.
+     *
+     * @return the X-Mms-MMS-Version value
+     */
+    public int getMmsVersion() {
+        return mPduHeaders.getOctet(PduHeaders.MMS_VERSION);
+    }
+
+    /**
+     * Set X-Mms-MMS-Version field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if field's value is not Octet.
+     */
+    public void setMmsVersion(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.MMS_VERSION);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/MultimediaMessagePdu.java b/src/com/android/messaging/mmslib/pdu/MultimediaMessagePdu.java
new file mode 100644
index 0000000..cb8c8c7
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/MultimediaMessagePdu.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * Multimedia message PDU.
+ */
+public class MultimediaMessagePdu extends GenericPdu {
+    /**
+     * The body.
+     */
+    private PduBody mMessageBody;
+
+    /**
+     * Constructor.
+     */
+    public MultimediaMessagePdu() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param header the header of this PDU
+     * @param body   the body of this PDU
+     */
+    public MultimediaMessagePdu(PduHeaders header, PduBody body) {
+        super(header);
+        mMessageBody = body;
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    MultimediaMessagePdu(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get body of the PDU.
+     *
+     * @return the body
+     */
+    public PduBody getBody() {
+        return mMessageBody;
+    }
+
+    /**
+     * Set body of the PDU.
+     *
+     * @param body the body
+     */
+    public void setBody(PduBody body) {
+        mMessageBody = body;
+    }
+
+    /**
+     * Get subject.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getSubject() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Set subject.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setSubject(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Add a "To" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addTo(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-Mms-Priority value.
+     *
+     * @return the value
+     */
+    public int getPriority() {
+        return mPduHeaders.getOctet(PduHeaders.PRIORITY);
+    }
+
+    /**
+     * Set X-Mms-Priority value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setPriority(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.PRIORITY);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value in seconds.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get the message size
+     *
+     * @return the size of the message
+     */
+    public long getMessageSize() {
+        return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/NotificationInd.java b/src/com/android/messaging/mmslib/pdu/NotificationInd.java
new file mode 100644
index 0000000..4cbbd30
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/NotificationInd.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * M-Notification.ind PDU.
+ */
+public class NotificationInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public NotificationInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    NotificationInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Content-Class Value.
+     *
+     * @return the value
+     */
+    public int getContentClass() {
+        return mPduHeaders.getOctet(PduHeaders.CONTENT_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Content-Class Value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setContentClass(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.CONTENT_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Content-Location value.
+     * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
+     * Content-location-value = Uri-value
+     *
+     * @return the value
+     */
+    public byte[] getContentLocation() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_LOCATION);
+    }
+
+    /**
+     * Set X-Mms-Content-Location value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setContentLocation(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_LOCATION);
+    }
+
+    /**
+     * Get X-Mms-Expiry value.
+     *
+     * Expiry-value = Value-length
+     *      (Absolute-token Date-value | Relative-token Delta-seconds-value)
+     *
+     * @return the value
+     */
+    public long getExpiry() {
+        return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Set X-Mms-Expiry value.
+     *
+     * @param value the value
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setExpiry(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Message-Size value.
+     * Message-size-value = Long-integer
+     *
+     * @return the value
+     */
+    public long getMessageSize() {
+        return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Set X-Mms-Message-Size value.
+     *
+     * @param value the value
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setMessageSize(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Get subject.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getSubject() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Set subject.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setSubject(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id.
+     *
+     * @return the value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report Value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report Value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public byte getDistributionIndicator() {return 0x00;}
+     *     public void setDistributionIndicator(byte value) {}
+     *
+     *     public ElementDescriptorValue getElementDescriptor() {return null;}
+     *     public void getElementDescriptor(ElementDescriptorValue value) {}
+     *
+     *     public byte getPriority() {return 0x00;}
+     *     public void setPriority(byte value) {}
+     *
+     *     public byte getRecommendedRetrievalMode() {return 0x00;}
+     *     public void setRecommendedRetrievalMode(byte value) {}
+     *
+     *     public byte getRecommendedRetrievalModeText() {return 0x00;}
+     *     public void setRecommendedRetrievalModeText(byte value) {}
+     *
+     *     public byte[] getReplaceId() {return 0x00;}
+     *     public void setReplaceId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     *
+     *     public byte getStored() {return 0x00;}
+     *     public void setStored(byte value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/NotifyRespInd.java b/src/com/android/messaging/mmslib/pdu/NotifyRespInd.java
new file mode 100644
index 0000000..7dabd89
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/NotifyRespInd.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * M-NofifyResp.ind PDU.
+ */
+public class NotifyRespInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-NotifyResp.ind pdu.
+     *
+     * @param mmsVersion    current version of mms
+     * @param transactionId the transaction-id value
+     * @param status        the status value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     * @throws NullPointerException if transactionId is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public NotifyRespInd(int mmsVersion,
+            byte[] transactionId,
+            int status) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+        setStatus(status);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    NotifyRespInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get X-Mms-Report-Allowed field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public int getReportAllowed() {
+        return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Report-Allowed field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setReportAllowed(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
+    }
+
+    /**
+     * Set X-Mms-Status field value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.STATUS);
+    }
+
+    /**
+     * GetX-Mms-Status field value.
+     *
+     * @return the X-Mms-Status value
+     */
+    public int getStatus() {
+        return mPduHeaders.getOctet(PduHeaders.STATUS);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     * @throws RuntimeException if an undeclared error occurs.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduBody.java b/src/com/android/messaging/mmslib/pdu/PduBody.java
new file mode 100644
index 0000000..8cbb2e6
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduBody.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import java.util.Vector;
+
+public class PduBody {
+    private Vector<PduPart> mParts = null;
+
+    /**
+     * Constructor.
+     */
+    public PduBody() {
+        mParts = new Vector<PduPart>();
+    }
+
+    /**
+     * Appends the specified part to the end of this body.
+     *
+     * @param part part to be appended
+     * @return true when success, false when fail
+     * @throws NullPointerException when part is null
+     */
+    public boolean addPart(PduPart part) {
+        if (null == part) {
+            throw new NullPointerException();
+        }
+
+        return mParts.add(part);
+    }
+
+    /**
+     * Inserts the specified part at the specified position.
+     *
+     * @param index index at which the specified part is to be inserted
+     * @param part  part to be inserted
+     * @throws NullPointerException when part is null
+     */
+    public void addPart(int index, PduPart part) {
+        if (null == part) {
+            throw new NullPointerException();
+        }
+
+        mParts.add(index, part);
+    }
+
+    /**
+     * Remove all of the parts.
+     */
+    public void removeAll() {
+        mParts.clear();
+    }
+
+    /**
+     * Get the part at the specified position.
+     *
+     * @param index index of the part to return
+     * @return part at the specified index
+     */
+    public PduPart getPart(int index) {
+        return mParts.get(index);
+    }
+
+    /**
+     * Get the number of parts.
+     *
+     * @return the number of parts
+     */
+    public int getPartsNum() {
+        return mParts.size();
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduComposer.java b/src/com/android/messaging/mmslib/pdu/PduComposer.java
new file mode 100644
index 0000000..ace49d1
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduComposer.java
@@ -0,0 +1,1260 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import androidx.collection.SimpleArrayMap;
+import android.text.TextUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+public class PduComposer {
+    /**
+     * Address type.
+     */
+    private static final int PDU_PHONE_NUMBER_ADDRESS_TYPE = 1;
+    private static final int PDU_EMAIL_ADDRESS_TYPE = 2;
+    private static final int PDU_IPV4_ADDRESS_TYPE = 3;
+    private static final int PDU_IPV6_ADDRESS_TYPE = 4;
+    private static final int PDU_UNKNOWN_ADDRESS_TYPE = 5;
+
+    /**
+     * Address regular expression string.
+     */
+    static final String REGEXP_PHONE_NUMBER_ADDRESS_TYPE = "\\+?[0-9|\\.|\\-]+";
+
+    static final String REGEXP_EMAIL_ADDRESS_TYPE = "[a-zA-Z| ]*\\<{0,1}[a-zA-Z| ]+@{1}" +
+            "[a-zA-Z| ]+\\.{1}[a-zA-Z| ]+\\>{0,1}";
+
+    static final String REGEXP_IPV6_ADDRESS_TYPE =
+            "[a-fA-F]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
+                    "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
+                    "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}";
+
+    static final String REGEXP_IPV4_ADDRESS_TYPE = "[0-9]{1,3}\\.{1}[0-9]{1,3}\\.{1}" +
+            "[0-9]{1,3}\\.{1}[0-9]{1,3}";
+
+    /**
+     * The postfix strings of address.
+     */
+    static final String STRING_PHONE_NUMBER_ADDRESS_TYPE = "/TYPE=PLMN";
+    static final String STRING_IPV4_ADDRESS_TYPE = "/TYPE=IPV4";
+    static final String STRING_IPV6_ADDRESS_TYPE = "/TYPE=IPV6";
+
+    /**
+     * Error values.
+     */
+    private static final int PDU_COMPOSE_SUCCESS = 0;
+    private static final int PDU_COMPOSE_CONTENT_ERROR = 1;
+    private static final int PDU_COMPOSE_FIELD_NOT_SET = 2;
+    private static final int PDU_COMPOSE_FIELD_NOT_SUPPORTED = 3;
+
+    /**
+     * WAP values defined in WSP spec.
+     */
+    private static final int QUOTED_STRING_FLAG = 34;
+    private static final int END_STRING_FLAG = 0;
+    private static final int LENGTH_QUOTE = 31;
+    private static final int TEXT_MAX = 127;
+    private static final int SHORT_INTEGER_MAX = 127;
+    private static final int LONG_INTEGER_LENGTH_MAX = 8;
+
+    /**
+     * Block size when read data from InputStream.
+     */
+    private static final int PDU_COMPOSER_BLOCK_SIZE = 1024;
+
+    /**
+     * The output message.
+     */
+    protected ByteArrayOutputStream mMessage = null;
+
+    /**
+     * The PDU.
+     */
+    private GenericPdu mPdu = null;
+
+    /**
+     * Current visiting position of the mMessage.
+     */
+    protected int mPosition = 0;
+
+    /**
+     * Message compose buffer stack.
+     */
+    private BufferStack mStack = null;
+
+    /**
+     * Content resolver.
+     */
+    private final ContentResolver mResolver;
+
+    /**
+     * Header of this pdu.
+     */
+    private PduHeaders mPduHeader = null;
+
+    /**
+     * Map of all content type
+     */
+    private static SimpleArrayMap<String, Integer> mContentTypeMap = null;
+
+    static {
+        mContentTypeMap = new SimpleArrayMap<String, Integer>();
+
+        int i;
+        for (i = 0; i < PduContentTypes.contentTypes.length; i++) {
+            mContentTypeMap.put(PduContentTypes.contentTypes[i], i);
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param context the context
+     * @param pdu     the pdu to be composed
+     */
+    public PduComposer(final Context context, final GenericPdu pdu) {
+        mPdu = pdu;
+        mResolver = context.getContentResolver();
+        mPduHeader = pdu.getPduHeaders();
+        mStack = new BufferStack();
+        mMessage = new ByteArrayOutputStream();
+        mPosition = 0;
+    }
+
+    /**
+     * Make the message. No need to check whether mandatory fields are set,
+     * because the constructors of outgoing pdus are taking care of this.
+     *
+     * @return OutputStream of maked message. Return null if
+     * the PDU is invalid.
+     */
+    public byte[] make() {
+        // Get Message-type.
+        final int type = mPdu.getMessageType();
+
+        /* make the message */
+        switch (type) {
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                if (makeSendReqPdu() != PDU_COMPOSE_SUCCESS) {
+                    return null;
+                }
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                if (makeNotifyResp() != PDU_COMPOSE_SUCCESS) {
+                    return null;
+                }
+                break;
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                if (makeAckInd() != PDU_COMPOSE_SUCCESS) {
+                    return null;
+                }
+                break;
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                if (makeReadRecInd() != PDU_COMPOSE_SUCCESS) {
+                    return null;
+                }
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                if (makeNotificationInd() != PDU_COMPOSE_SUCCESS) {
+                    return null;
+                }
+                break;
+            default:
+                return null;
+        }
+
+        return mMessage.toByteArray();
+    }
+
+    /**
+     * Copy buf to mMessage.
+     */
+    protected void arraycopy(final byte[] buf, final int pos, final int length) {
+        mMessage.write(buf, pos, length);
+        mPosition = mPosition + length;
+    }
+
+    /**
+     * Append a byte to mMessage.
+     */
+    protected void append(final int value) {
+        mMessage.write(value);
+        mPosition++;
+    }
+
+    /**
+     * Append short integer value to mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendShortInteger(final int value) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Short-integer = OCTET
+         * ; Integers in range 0-127 shall be encoded as a one octet value
+         * ; with the most significant bit set to one (1xxx xxxx) and with
+         * ; the value in the remaining least significant bits.
+         * In our implementation, only low 7 bits are stored and otherwise
+         * bits are ignored.
+         */
+        append((value | 0x80) & 0xff);
+    }
+
+    /**
+     * Append an octet number between 128 and 255 into mMessage.
+     * NOTE:
+     * A value between 0 and 127 should be appended by using appendShortInteger.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendOctet(final int number) {
+        append(number);
+    }
+
+    /**
+     * Append a short length into mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendShortLength(final int value) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Short-length = <Any octet 0-30>
+         */
+        append(value);
+    }
+
+    /**
+     * Append long integer into mMessage. it's used for really long integers.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendLongInteger(final long longInt) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Long-integer = Short-length Multi-octet-integer
+         * ; The Short-length indicates the length of the Multi-octet-integer
+         * Multi-octet-integer = 1*30 OCTET
+         * ; The content octets shall be an unsigned integer value with the
+         * ; most significant octet encoded first (big-endian representation).
+         * ; The minimum number of octets must be used to encode the value.
+         */
+        int size;
+        long temp = longInt;
+
+        // Count the length of the long integer.
+        for (size = 0; (temp != 0) && (size < LONG_INTEGER_LENGTH_MAX); size++) {
+            temp = (temp >>> 8);
+        }
+
+        // Set Length.
+        appendShortLength(size);
+
+        // Count and set the long integer.
+        int i;
+        int shift = (size - 1) * 8;
+
+        for (i = 0; i < size; i++) {
+            append((int) ((longInt >>> shift) & 0xff));
+            shift = shift - 8;
+        }
+    }
+
+    /**
+     * Append text string into mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendTextString(final byte[] text) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Text-string = [Quote] *TEXT End-of-string
+         * ; If the first character in the TEXT is in the range of 128-255,
+         * ; a Quote character must precede it. Otherwise the Quote character
+         * ;must be omitted. The Quote is not part of the contents.
+         */
+        if (((text[0]) & 0xff) > TEXT_MAX) { // No need to check for <= 255
+            append(TEXT_MAX);
+        }
+
+        arraycopy(text, 0, text.length);
+        append(0);
+    }
+
+    /**
+     * Append text string into mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendTextString(final String str) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Text-string = [Quote] *TEXT End-of-string
+         * ; If the first character in the TEXT is in the range of 128-255,
+         * ; a Quote character must precede it. Otherwise the Quote character
+         * ;must be omitted. The Quote is not part of the contents.
+         */
+        appendTextString(str.getBytes());
+    }
+
+    /**
+     * Append encoded string value to mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendEncodedString(final EncodedStringValue enStr) {
+        /*
+         * From OMA-TS-MMS-ENC-V1_3-20050927-C:
+         * Encoded-string-value = Text-string | Value-length Char-set Text-string
+         */
+        assert (enStr != null);
+
+        final int charset = enStr.getCharacterSet();
+        final byte[] textString = enStr.getTextString();
+        if (null == textString) {
+            return;
+        }
+
+        /*
+         * In the implementation of EncodedStringValue, the charset field will
+         * never be 0. It will always be composed as
+         * Encoded-string-value = Value-length Char-set Text-string
+         */
+        mStack.newbuf();
+        final PositionMarker start = mStack.mark();
+
+        appendShortInteger(charset);
+        appendTextString(textString);
+
+        final int len = start.getLength();
+        mStack.pop();
+        appendValueLength(len);
+        mStack.copy();
+    }
+
+    /**
+     * Append uintvar integer into mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendUintvarInteger(final long value) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * To encode a large unsigned integer, split it into 7-bit fragments
+         * and place them in the payloads of multiple octets. The most significant
+         * bits are placed in the first octets with the least significant bits
+         * ending up in the last octet. All octets MUST set the Continue bit to 1
+         * except the last octet, which MUST set the Continue bit to 0.
+         */
+        int i;
+        long max = SHORT_INTEGER_MAX;
+
+        for (i = 0; i < 5; i++) {
+            if (value < max) {
+                break;
+            }
+
+            max = (max << 7) | 0x7fL;
+        }
+
+        while (i > 0) {
+            long temp = value >>> (i * 7);
+            temp = temp & 0x7f;
+
+            append((int) ((temp | 0x80) & 0xff));
+
+            i--;
+        }
+
+        append((int) (value & 0x7f));
+    }
+
+    /**
+     * Append date value into mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendDateValue(final long date) {
+        /*
+         * From OMA-TS-MMS-ENC-V1_3-20050927-C:
+         * Date-value = Long-integer
+         */
+        appendLongInteger(date);
+    }
+
+    /**
+     * Append value length to mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendValueLength(final long value) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Value-length = Short-length | (Length-quote Length)
+         * ; Value length is used to indicate the length of the value to follow
+         * Short-length = <Any octet 0-30>
+         * Length-quote = <Octet 31>
+         * Length = Uintvar-integer
+         */
+        if (value < LENGTH_QUOTE) {
+            appendShortLength((int) value);
+            return;
+        }
+
+        append(LENGTH_QUOTE);
+        appendUintvarInteger(value);
+    }
+
+    /**
+     * Append quoted string to mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendQuotedString(final byte[] text) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Quoted-string = <Octet 34> *TEXT End-of-string
+         * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
+         * ;quotation-marks <"> removed.
+         */
+        append(QUOTED_STRING_FLAG);
+        arraycopy(text, 0, text.length);
+        append(END_STRING_FLAG);
+    }
+
+    /**
+     * Append quoted string to mMessage.
+     * This implementation doesn't check the validity of parameter, since it
+     * assumes that the values are validated in the GenericPdu setter methods.
+     */
+    protected void appendQuotedString(final String str) {
+        /*
+         * From WAP-230-WSP-20010705-a:
+         * Quoted-string = <Octet 34> *TEXT End-of-string
+         * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
+         * ;quotation-marks <"> removed.
+         */
+        appendQuotedString(str.getBytes());
+    }
+
+    private EncodedStringValue appendAddressType(final EncodedStringValue address) {
+        EncodedStringValue temp = null;
+
+        try {
+            final int addressType = checkAddressType(address.getString());
+            temp = EncodedStringValue.copy(address);
+            if (PDU_PHONE_NUMBER_ADDRESS_TYPE == addressType) {
+                // Phone number.
+                temp.appendTextString(STRING_PHONE_NUMBER_ADDRESS_TYPE.getBytes());
+            } else if (PDU_IPV4_ADDRESS_TYPE == addressType) {
+                // Ipv4 address.
+                temp.appendTextString(STRING_IPV4_ADDRESS_TYPE.getBytes());
+            } else if (PDU_IPV6_ADDRESS_TYPE == addressType) {
+                // Ipv6 address.
+                temp.appendTextString(STRING_IPV6_ADDRESS_TYPE.getBytes());
+            }
+        } catch (final NullPointerException e) {
+            return null;
+        }
+
+        return temp;
+    }
+
+    /**
+     * Append header to mMessage.
+     */
+    private int appendHeader(final int field) {
+        switch (field) {
+            case PduHeaders.MMS_VERSION:
+                appendOctet(field);
+
+                final int version = mPduHeader.getOctet(field);
+                if (0 == version) {
+                    appendShortInteger(PduHeaders.CURRENT_MMS_VERSION);
+                } else {
+                    appendShortInteger(version);
+                }
+
+                break;
+
+            case PduHeaders.MESSAGE_ID:
+            case PduHeaders.TRANSACTION_ID:
+            case PduHeaders.CONTENT_LOCATION:
+                final byte[] textString = mPduHeader.getTextString(field);
+                if (null == textString) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+                appendTextString(textString);
+                break;
+
+            case PduHeaders.TO:
+            case PduHeaders.BCC:
+            case PduHeaders.CC:
+                final EncodedStringValue[] addr = mPduHeader.getEncodedStringValues(field);
+
+                if (null == addr) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                EncodedStringValue temp;
+                for (int i = 0; i < addr.length; i++) {
+                    temp = appendAddressType(addr[i]);
+                    if (temp == null) {
+                        return PDU_COMPOSE_CONTENT_ERROR;
+                    }
+
+                    appendOctet(field);
+                    appendEncodedString(temp);
+                }
+                break;
+
+            case PduHeaders.FROM:
+                // Value-length (Address-present-token Encoded-string-value | Insert-address-token)
+                appendOctet(field);
+
+                final EncodedStringValue from = mPduHeader.getEncodedStringValue(field);
+                if ((from == null)
+                        || TextUtils.isEmpty(from.getString())
+                        || new String(from.getTextString()).equals(
+                        PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) {
+                    // Length of from = 1
+                    append(1);
+                    // Insert-address-token = <Octet 129>
+                    append(PduHeaders.FROM_INSERT_ADDRESS_TOKEN);
+                } else {
+                    mStack.newbuf();
+                    final PositionMarker fstart = mStack.mark();
+
+                    // Address-present-token = <Octet 128>
+                    append(PduHeaders.FROM_ADDRESS_PRESENT_TOKEN);
+
+                    temp = appendAddressType(from);
+                    if (temp == null) {
+                        return PDU_COMPOSE_CONTENT_ERROR;
+                    }
+
+                    appendEncodedString(temp);
+
+                    final int flen = fstart.getLength();
+                    mStack.pop();
+                    appendValueLength(flen);
+                    mStack.copy();
+                }
+                break;
+
+            case PduHeaders.READ_STATUS:
+            case PduHeaders.STATUS:
+            case PduHeaders.REPORT_ALLOWED:
+            case PduHeaders.PRIORITY:
+            case PduHeaders.DELIVERY_REPORT:
+            case PduHeaders.READ_REPORT:
+                final int octet = mPduHeader.getOctet(field);
+                if (0 == octet) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+                appendOctet(octet);
+                break;
+
+            case PduHeaders.DATE:
+                final long date = mPduHeader.getLongInteger(field);
+                if (-1 == date) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+                appendDateValue(date);
+                break;
+
+            case PduHeaders.SUBJECT:
+                final EncodedStringValue enString =
+                        mPduHeader.getEncodedStringValue(field);
+                if (null == enString) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+                appendEncodedString(enString);
+                break;
+
+            case PduHeaders.MESSAGE_CLASS:
+                final byte[] messageClass = mPduHeader.getTextString(field);
+                if (null == messageClass) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+                if (Arrays.equals(messageClass,
+                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes())) {
+                    appendOctet(PduHeaders.MESSAGE_CLASS_ADVERTISEMENT);
+                } else if (Arrays.equals(messageClass,
+                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes())) {
+                    appendOctet(PduHeaders.MESSAGE_CLASS_AUTO);
+                } else if (Arrays.equals(messageClass,
+                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes())) {
+                    appendOctet(PduHeaders.MESSAGE_CLASS_PERSONAL);
+                } else if (Arrays.equals(messageClass,
+                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes())) {
+                    appendOctet(PduHeaders.MESSAGE_CLASS_INFORMATIONAL);
+                } else {
+                    appendTextString(messageClass);
+                }
+                break;
+
+            case PduHeaders.EXPIRY:
+            case PduHeaders.MESSAGE_SIZE:
+                final long value = mPduHeader.getLongInteger(field);
+                if (-1 == value) {
+                    return PDU_COMPOSE_FIELD_NOT_SET;
+                }
+
+                appendOctet(field);
+
+                mStack.newbuf();
+                final PositionMarker valueStart = mStack.mark();
+
+                append(PduHeaders.VALUE_RELATIVE_TOKEN);
+                appendLongInteger(value);
+
+                final int valueLength = valueStart.getLength();
+                mStack.pop();
+                appendValueLength(valueLength);
+                mStack.copy();
+                break;
+
+            default:
+                return PDU_COMPOSE_FIELD_NOT_SUPPORTED;
+        }
+
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Make ReadRec.Ind.
+     */
+    private int makeReadRecInd() {
+        if (mMessage == null) {
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        // X-Mms-Message-Type
+        appendOctet(PduHeaders.MESSAGE_TYPE);
+        appendOctet(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
+
+        // X-Mms-MMS-Version
+        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Message-ID
+        if (appendHeader(PduHeaders.MESSAGE_ID) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // To
+        if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // From
+        if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Date Optional
+        appendHeader(PduHeaders.DATE);
+
+        // X-Mms-Read-Status
+        if (appendHeader(PduHeaders.READ_STATUS) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // X-Mms-Applic-ID Optional(not support)
+        // X-Mms-Reply-Applic-ID Optional(not support)
+        // X-Mms-Aux-Applic-Info Optional(not support)
+
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Make NotifyResp.Ind.
+     */
+    private int makeNotifyResp() {
+        if (mMessage == null) {
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        //    X-Mms-Message-Type
+        appendOctet(PduHeaders.MESSAGE_TYPE);
+        appendOctet(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
+
+        // X-Mms-Transaction-ID
+        if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // X-Mms-MMS-Version
+        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        //  X-Mms-Status
+        if (appendHeader(PduHeaders.STATUS) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // X-Mms-Report-Allowed Optional (not support)
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Make Acknowledge.Ind.
+     */
+    private int makeAckInd() {
+        if (mMessage == null) {
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        //    X-Mms-Message-Type
+        appendOctet(PduHeaders.MESSAGE_TYPE);
+        appendOctet(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
+
+        // X-Mms-Transaction-ID
+        if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        //     X-Mms-MMS-Version
+        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // X-Mms-Report-Allowed Optional
+        appendHeader(PduHeaders.REPORT_ALLOWED);
+
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Make Acknowledge.Ind.
+     */
+    private int makeNotificationInd() {
+        if (mMessage == null) {
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        //    X-Mms-Message-Type
+        appendOctet(PduHeaders.MESSAGE_TYPE);
+        appendOctet(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
+
+        // X-Mms-Transaction-ID
+        if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        //     X-Mms-MMS-Version
+        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // From
+        if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Subject Optional
+        appendHeader(PduHeaders.SUBJECT);
+
+        // Expiry
+        if (appendHeader(PduHeaders.MESSAGE_CLASS) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Expiry
+        if (appendHeader(PduHeaders.MESSAGE_SIZE) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Expiry
+        if (appendHeader(PduHeaders.EXPIRY) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // X-Mms-Content-Location
+        if (appendHeader(PduHeaders.CONTENT_LOCATION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Make Send.req.
+     */
+    private int makeSendReqPdu() {
+        if (mMessage == null) {
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        // X-Mms-Message-Type
+        appendOctet(PduHeaders.MESSAGE_TYPE);
+        appendOctet(PduHeaders.MESSAGE_TYPE_SEND_REQ);
+
+        // X-Mms-Transaction-ID
+        appendOctet(PduHeaders.TRANSACTION_ID);
+
+        final byte[] trid = mPduHeader.getTextString(PduHeaders.TRANSACTION_ID);
+        if (trid == null) {
+            // Transaction-ID should be set(by Transaction) before make().
+            throw new IllegalArgumentException("Transaction-ID is null.");
+        }
+        appendTextString(trid);
+
+        //  X-Mms-MMS-Version
+        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Date Date-value Optional.
+        appendHeader(PduHeaders.DATE);
+
+        // From
+        if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        boolean recipient = false;
+
+        // To
+        if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_CONTENT_ERROR) {
+            recipient = true;
+        }
+
+        // Cc
+        if (appendHeader(PduHeaders.CC) != PDU_COMPOSE_CONTENT_ERROR) {
+            recipient = true;
+        }
+
+        // Bcc
+        if (appendHeader(PduHeaders.BCC) != PDU_COMPOSE_CONTENT_ERROR) {
+            recipient = true;
+        }
+
+        // Need at least one of "cc", "bcc" and "to".
+        if (false == recipient) {
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        // Subject Optional
+        appendHeader(PduHeaders.SUBJECT);
+
+        // X-Mms-Message-Class Optional
+        // Message-class-value = Class-identifier | Token-text
+        appendHeader(PduHeaders.MESSAGE_CLASS);
+
+        // X-Mms-Expiry Optional
+        appendHeader(PduHeaders.EXPIRY);
+
+        // X-Mms-Priority Optional
+        appendHeader(PduHeaders.PRIORITY);
+
+        // X-Mms-Delivery-Report Optional
+        appendHeader(PduHeaders.DELIVERY_REPORT);
+
+        // X-Mms-Read-Report Optional
+        appendHeader(PduHeaders.READ_REPORT);
+
+        //    Content-Type
+        appendOctet(PduHeaders.CONTENT_TYPE);
+
+        //  Message body
+        return makeMessageBody();
+    }
+
+    /**
+     * Make message body.
+     */
+    private int makeMessageBody() {
+        // 1. add body informations
+        mStack.newbuf();  // Switching buffer because we need to
+
+        final PositionMarker ctStart = mStack.mark();
+
+        // This contentTypeIdentifier should be used for type of attachment...
+        final String contentType = new String(mPduHeader.getTextString(PduHeaders.CONTENT_TYPE));
+        final Integer contentTypeIdentifier = mContentTypeMap.get(contentType);
+        if (contentTypeIdentifier == null) {
+            // content type is mandatory
+            return PDU_COMPOSE_CONTENT_ERROR;
+        }
+
+        appendShortInteger(contentTypeIdentifier.intValue());
+
+        // content-type parameter: start
+        final PduBody body = ((SendReq) mPdu).getBody();
+        if (null == body || body.getPartsNum() == 0) {
+            // empty message
+            appendUintvarInteger(0);
+            mStack.pop();
+            mStack.copy();
+            return PDU_COMPOSE_SUCCESS;
+        }
+
+        PduPart part;
+        try {
+            part = body.getPart(0);
+
+            final byte[] start = part.getContentId();
+            if (start != null) {
+                appendOctet(PduPart.P_DEP_START);
+                if (('<' == start[0]) && ('>' == start[start.length - 1])) {
+                    appendTextString(start);
+                } else {
+                    appendTextString("<" + new String(start) + ">");
+                }
+            }
+
+            // content-type parameter: type
+            appendOctet(PduPart.P_CT_MR_TYPE);
+            appendTextString(part.getContentType());
+        } catch (final ArrayIndexOutOfBoundsException e) {
+            e.printStackTrace();
+        }
+
+        final int ctLength = ctStart.getLength();
+        mStack.pop();
+        appendValueLength(ctLength);
+        mStack.copy();
+
+        // 3. add content
+        final int partNum = body.getPartsNum();
+        appendUintvarInteger(partNum);
+        for (int i = 0; i < partNum; i++) {
+            part = body.getPart(i);
+            mStack.newbuf();  // Leaving space for header lengh and data length
+            final PositionMarker attachment = mStack.mark();
+
+            mStack.newbuf();  // Leaving space for Content-Type length
+            final PositionMarker contentTypeBegin = mStack.mark();
+
+            final byte[] partContentType = part.getContentType();
+
+            if (partContentType == null) {
+                // content type is mandatory
+                return PDU_COMPOSE_CONTENT_ERROR;
+            }
+
+            // content-type value
+            final Integer partContentTypeIdentifier =
+                    mContentTypeMap.get(new String(partContentType));
+            if (partContentTypeIdentifier == null) {
+                appendTextString(partContentType);
+            } else {
+                appendShortInteger(partContentTypeIdentifier.intValue());
+            }
+
+            /* Content-type parameter : name.
+             * The value of name, filename, content-location is the same.
+             * Just one of them is enough for this PDU.
+             */
+            byte[] name = part.getName();
+
+            if (null == name) {
+                name = part.getFilename();
+
+                if (null == name) {
+                    name = part.getContentLocation();
+
+                    if (null == name) {
+                        /* at lease one of name, filename, Content-location
+                         * should be available.
+                         */
+                        // I found that an mms received from tmomail.net will include a SMIL part
+                        // that has no name. That would cause the code here to return
+                        // PDU_COMPOSE_CONTENT_ERROR when a user tried to forward the message. The
+                        // message would never send and the user would be stuck in a retry
+                        // situation. Simply jam in any old name here to fix the problem.
+                        name = "smil.xml".getBytes();
+                    }
+                }
+            }
+            appendOctet(PduPart.P_DEP_NAME);
+            appendTextString(name);
+
+            // content-type parameter : charset
+            final int charset = part.getCharset();
+            if (charset != 0) {
+                appendOctet(PduPart.P_CHARSET);
+                appendShortInteger(charset);
+            }
+
+            final int contentTypeLength = contentTypeBegin.getLength();
+            mStack.pop();
+            appendValueLength(contentTypeLength);
+            mStack.copy();
+
+            // content id
+            final byte[] contentId = part.getContentId();
+
+            if (null != contentId) {
+                appendOctet(PduPart.P_CONTENT_ID);
+                if (('<' == contentId[0]) && ('>' == contentId[contentId.length - 1])) {
+                    appendQuotedString(contentId);
+                } else {
+                    appendQuotedString("<" + new String(contentId) + ">");
+                }
+            }
+
+            // content-location
+            final byte[] contentLocation = part.getContentLocation();
+            if (null != contentLocation) {
+                appendOctet(PduPart.P_CONTENT_LOCATION);
+                appendTextString(contentLocation);
+            }
+
+            // content
+            final int headerLength = attachment.getLength();
+
+            int dataLength = 0; // Just for safety...
+            final byte[] partData = part.getData();
+
+            if (partData != null) {
+                arraycopy(partData, 0, partData.length);
+                dataLength = partData.length;
+            } else {
+                InputStream cr = null;
+                try {
+                    final byte[] buffer = new byte[PDU_COMPOSER_BLOCK_SIZE];
+                    cr = mResolver.openInputStream(part.getDataUri());
+                    int len = 0;
+                    while ((len = cr.read(buffer)) != -1) {
+                        mMessage.write(buffer, 0, len);
+                        mPosition += len;
+                        dataLength += len;
+                    }
+                } catch (final FileNotFoundException e) {
+                    return PDU_COMPOSE_CONTENT_ERROR;
+                } catch (final IOException e) {
+                    return PDU_COMPOSE_CONTENT_ERROR;
+                } catch (final RuntimeException e) {
+                    return PDU_COMPOSE_CONTENT_ERROR;
+                } finally {
+                    if (cr != null) {
+                        try {
+                            cr.close();
+                        } catch (final IOException e) {
+                            // Nothing to do
+                        }
+                    }
+                }
+            }
+
+            if (dataLength != (attachment.getLength() - headerLength)) {
+                throw new RuntimeException("BUG: Length check failed");
+            }
+
+            mStack.pop();
+            appendUintvarInteger(headerLength);
+            appendUintvarInteger(dataLength);
+            mStack.copy();
+        }
+
+        return PDU_COMPOSE_SUCCESS;
+    }
+
+    /**
+     * Record current message informations.
+     */
+    private static class LengthRecordNode {
+
+        ByteArrayOutputStream currentMessage = null;
+
+        public int currentPosition = 0;
+
+        public LengthRecordNode next = null;
+    }
+
+    /**
+     * Mark current message position and stact size.
+     */
+    private class PositionMarker {
+
+        private int c_pos;   // Current position
+
+        private int currentStackSize;  // Current stack size
+
+        int getLength() {
+            // If these assert fails, likely that you are finding the
+            // size of buffer that is deep in BufferStack you can only
+            // find the length of the buffer that is on top
+            if (currentStackSize != mStack.stackSize) {
+                throw new RuntimeException("BUG: Invalid call to getLength()");
+            }
+
+            return mPosition - c_pos;
+        }
+    }
+
+    /**
+     * This implementation can be OPTIMIZED to use only
+     * 2 buffers. This optimization involves changing BufferStack
+     * only... Its usage (interface) will not change.
+     */
+    private class BufferStack {
+
+        private LengthRecordNode stack = null;
+
+        private LengthRecordNode toCopy = null;
+
+        int stackSize = 0;
+
+        /**
+         * Create a new message buffer and push it into the stack.
+         */
+        void newbuf() {
+            // You can't create a new buff when toCopy != null
+            // That is after calling pop() and before calling copy()
+            // If you do, it is a bug
+            if (toCopy != null) {
+                throw new RuntimeException("BUG: Invalid newbuf() before copy()");
+            }
+
+            final LengthRecordNode temp = new LengthRecordNode();
+
+            temp.currentMessage = mMessage;
+            temp.currentPosition = mPosition;
+
+            temp.next = stack;
+            stack = temp;
+
+            stackSize = stackSize + 1;
+
+            mMessage = new ByteArrayOutputStream();
+            mPosition = 0;
+        }
+
+        /**
+         * Pop the message before and record current message in the stack.
+         */
+        void pop() {
+            final ByteArrayOutputStream currentMessage = mMessage;
+            final int currentPosition = mPosition;
+
+            mMessage = stack.currentMessage;
+            mPosition = stack.currentPosition;
+
+            toCopy = stack;
+            // Re using the top element of the stack to avoid memory allocation
+
+            stack = stack.next;
+            stackSize = stackSize - 1;
+
+            toCopy.currentMessage = currentMessage;
+            toCopy.currentPosition = currentPosition;
+        }
+
+        /**
+         * Append current message to the message before.
+         */
+        void copy() {
+            arraycopy(toCopy.currentMessage.toByteArray(), 0,
+                    toCopy.currentPosition);
+
+            toCopy = null;
+        }
+
+        /**
+         * Mark current message position
+         */
+        PositionMarker mark() {
+            final PositionMarker m = new PositionMarker();
+
+            m.c_pos = mPosition;
+            m.currentStackSize = stackSize;
+
+            return m;
+        }
+    }
+
+    /**
+     * Check address type.
+     *
+     * @param address address string without the postfix stinng type,
+     *                such as "/TYPE=PLMN", "/TYPE=IPv6" and "/TYPE=IPv4"
+     * @return PDU_PHONE_NUMBER_ADDRESS_TYPE if it is phone number,
+     *         PDU_EMAIL_ADDRESS_TYPE if it is email address,
+     *         PDU_IPV4_ADDRESS_TYPE if it is ipv4 address,
+     *         PDU_IPV6_ADDRESS_TYPE if it is ipv6 address,
+     *         PDU_UNKNOWN_ADDRESS_TYPE if it is unknown.
+     */
+    protected static int checkAddressType(final String address) {
+        /**
+         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf, section 8.
+         * address = ( e-mail / device-address / alphanum-shortcode / num-shortcode)
+         * e-mail = mailbox; to the definition of mailbox as described in
+         * section 3.4 of [RFC2822], but excluding the
+         * obsolete definitions as indicated by the "obs-" prefix.
+         * device-address = ( global-phone-number "/TYPE=PLMN" )
+         * / ( ipv4 "/TYPE=IPv4" ) / ( ipv6 "/TYPE=IPv6" )
+         * / ( escaped-value "/TYPE=" address-type )
+         *
+         * global-phone-number = ["+"] 1*( DIGIT / written-sep )
+         * written-sep =("-"/".")
+         *
+         * ipv4 = 1*3DIGIT 3( "." 1*3DIGIT ) ; IPv4 address value
+         *
+         * ipv6 = 4HEXDIG 7( ":" 4HEXDIG ) ; IPv6 address per RFC 2373
+         */
+
+        if (null == address) {
+            return PDU_UNKNOWN_ADDRESS_TYPE;
+        }
+
+        if (address.matches(REGEXP_IPV4_ADDRESS_TYPE)) {
+            // Ipv4 address.
+            return PDU_IPV4_ADDRESS_TYPE;
+        } else if (address.matches(REGEXP_PHONE_NUMBER_ADDRESS_TYPE)) {
+            // Phone number.
+            return PDU_PHONE_NUMBER_ADDRESS_TYPE;
+        } else if (address.matches(REGEXP_EMAIL_ADDRESS_TYPE)) {
+            // Email address.
+            return PDU_EMAIL_ADDRESS_TYPE;
+        } else if (address.matches(REGEXP_IPV6_ADDRESS_TYPE)) {
+            // Ipv6 address.
+            return PDU_IPV6_ADDRESS_TYPE;
+        } else {
+            // Unknown address.
+            return PDU_UNKNOWN_ADDRESS_TYPE;
+        }
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduContentTypes.java b/src/com/android/messaging/mmslib/pdu/PduContentTypes.java
new file mode 100644
index 0000000..f2cebf1
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduContentTypes.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+public class PduContentTypes {
+    /**
+     * All content types. From:
+     * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.htm
+     */
+    static final String[] contentTypes = {
+            "*/*",                                        /* 0x00 */
+            "text/*",                                     /* 0x01 */
+            "text/html",                                  /* 0x02 */
+            "text/plain",                                 /* 0x03 */
+            "text/x-hdml",                                /* 0x04 */
+            "text/x-ttml",                                /* 0x05 */
+            "text/x-vCalendar",                           /* 0x06 */
+            "text/x-vCard",                               /* 0x07 */
+            "text/vnd.wap.wml",                           /* 0x08 */
+            "text/vnd.wap.wmlscript",                     /* 0x09 */
+            "text/vnd.wap.wta-event",                     /* 0x0A */
+            "multipart/*",                                /* 0x0B */
+            "multipart/mixed",                            /* 0x0C */
+            "multipart/form-data",                        /* 0x0D */
+            "multipart/byterantes",                       /* 0x0E */
+            "multipart/alternative",                      /* 0x0F */
+            "application/*",                              /* 0x10 */
+            "application/java-vm",                        /* 0x11 */
+            "application/x-www-form-urlencoded",          /* 0x12 */
+            "application/x-hdmlc",                        /* 0x13 */
+            "application/vnd.wap.wmlc",                   /* 0x14 */
+            "application/vnd.wap.wmlscriptc",             /* 0x15 */
+            "application/vnd.wap.wta-eventc",             /* 0x16 */
+            "application/vnd.wap.uaprof",                 /* 0x17 */
+            "application/vnd.wap.wtls-ca-certificate",    /* 0x18 */
+            "application/vnd.wap.wtls-user-certificate",  /* 0x19 */
+            "application/x-x509-ca-cert",                 /* 0x1A */
+            "application/x-x509-user-cert",               /* 0x1B */
+            "image/*",                                    /* 0x1C */
+            "image/gif",                                  /* 0x1D */
+            "image/jpeg",                                 /* 0x1E */
+            "image/tiff",                                 /* 0x1F */
+            "image/png",                                  /* 0x20 */
+            "image/vnd.wap.wbmp",                         /* 0x21 */
+            "application/vnd.wap.multipart.*",            /* 0x22 */
+            "application/vnd.wap.multipart.mixed",        /* 0x23 */
+            "application/vnd.wap.multipart.form-data",    /* 0x24 */
+            "application/vnd.wap.multipart.byteranges",   /* 0x25 */
+            "application/vnd.wap.multipart.alternative",  /* 0x26 */
+            "application/xml",                            /* 0x27 */
+            "text/xml",                                   /* 0x28 */
+            "application/vnd.wap.wbxml",                  /* 0x29 */
+            "application/x-x968-cross-cert",              /* 0x2A */
+            "application/x-x968-ca-cert",                 /* 0x2B */
+            "application/x-x968-user-cert",               /* 0x2C */
+            "text/vnd.wap.si",                            /* 0x2D */
+            "application/vnd.wap.sic",                    /* 0x2E */
+            "text/vnd.wap.sl",                            /* 0x2F */
+            "application/vnd.wap.slc",                    /* 0x30 */
+            "text/vnd.wap.co",                            /* 0x31 */
+            "application/vnd.wap.coc",                    /* 0x32 */
+            "application/vnd.wap.multipart.related",      /* 0x33 */
+            "application/vnd.wap.sia",                    /* 0x34 */
+            "text/vnd.wap.connectivity-xml",              /* 0x35 */
+            "application/vnd.wap.connectivity-wbxml",     /* 0x36 */
+            "application/pkcs7-mime",                     /* 0x37 */
+            "application/vnd.wap.hashed-certificate",     /* 0x38 */
+            "application/vnd.wap.signed-certificate",     /* 0x39 */
+            "application/vnd.wap.cert-response",          /* 0x3A */
+            "application/xhtml+xml",                      /* 0x3B */
+            "application/wml+xml",                        /* 0x3C */
+            "text/css",                                   /* 0x3D */
+            "application/vnd.wap.mms-message",            /* 0x3E */
+            "application/vnd.wap.rollover-certificate",   /* 0x3F */
+            "application/vnd.wap.locc+wbxml",             /* 0x40 */
+            "application/vnd.wap.loc+xml",                /* 0x41 */
+            "application/vnd.syncml.dm+wbxml",            /* 0x42 */
+            "application/vnd.syncml.dm+xml",              /* 0x43 */
+            "application/vnd.syncml.notification",        /* 0x44 */
+            "application/vnd.wap.xhtml+xml",              /* 0x45 */
+            "application/vnd.wv.csp.cir",                 /* 0x46 */
+            "application/vnd.oma.dd+xml",                 /* 0x47 */
+            "application/vnd.oma.drm.message",            /* 0x48 */
+            "application/vnd.oma.drm.content",            /* 0x49 */
+            "application/vnd.oma.drm.rights+xml",         /* 0x4A */
+            "application/vnd.oma.drm.rights+wbxml",       /* 0x4B */
+            "application/vnd.wv.csp+xml",                 /* 0x4C */
+            "application/vnd.wv.csp+wbxml",               /* 0x4D */
+            "application/vnd.syncml.ds.notification",     /* 0x4E */
+            "audio/*",                                    /* 0x4F */
+            "video/*",                                    /* 0x50 */
+            "application/vnd.oma.dd2+xml",                /* 0x51 */
+            "application/mikey"                           /* 0x52 */
+    };
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduHeaders.java b/src/com/android/messaging/mmslib/pdu/PduHeaders.java
new file mode 100644
index 0000000..96d18ee
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduHeaders.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.util.SparseArray;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+import java.util.ArrayList;
+
+public class PduHeaders {
+    /**
+     * All pdu header fields.
+     */
+    public static final int BCC                             = 0x81;
+    public static final int CC                              = 0x82;
+    public static final int CONTENT_LOCATION                = 0x83;
+    public static final int CONTENT_TYPE                    = 0x84;
+    public static final int DATE                            = 0x85;
+    public static final int DELIVERY_REPORT                 = 0x86;
+    public static final int DELIVERY_TIME                   = 0x87;
+    public static final int EXPIRY                          = 0x88;
+    public static final int FROM                            = 0x89;
+    public static final int MESSAGE_CLASS                   = 0x8A;
+    public static final int MESSAGE_ID                      = 0x8B;
+    public static final int MESSAGE_TYPE                    = 0x8C;
+    public static final int MMS_VERSION                     = 0x8D;
+    public static final int MESSAGE_SIZE                    = 0x8E;
+    public static final int PRIORITY                        = 0x8F;
+
+    public static final int READ_REPLY                      = 0x90;
+    public static final int READ_REPORT                     = 0x90;
+    public static final int REPORT_ALLOWED                  = 0x91;
+    public static final int RESPONSE_STATUS                 = 0x92;
+    public static final int RESPONSE_TEXT                   = 0x93;
+    public static final int SENDER_VISIBILITY               = 0x94;
+    public static final int STATUS                          = 0x95;
+    public static final int SUBJECT                         = 0x96;
+    public static final int TO                              = 0x97;
+    public static final int TRANSACTION_ID                  = 0x98;
+    public static final int RETRIEVE_STATUS                 = 0x99;
+    public static final int RETRIEVE_TEXT                   = 0x9A;
+    public static final int READ_STATUS                     = 0x9B;
+    public static final int REPLY_CHARGING                  = 0x9C;
+    public static final int REPLY_CHARGING_DEADLINE         = 0x9D;
+    public static final int REPLY_CHARGING_ID               = 0x9E;
+    public static final int REPLY_CHARGING_SIZE             = 0x9F;
+
+    public static final int PREVIOUSLY_SENT_BY              = 0xA0;
+    public static final int PREVIOUSLY_SENT_DATE            = 0xA1;
+    public static final int STORE                           = 0xA2;
+    public static final int MM_STATE                        = 0xA3;
+    public static final int MM_FLAGS                        = 0xA4;
+    public static final int STORE_STATUS                    = 0xA5;
+    public static final int STORE_STATUS_TEXT               = 0xA6;
+    public static final int STORED                          = 0xA7;
+    public static final int ATTRIBUTES                      = 0xA8;
+    public static final int TOTALS                          = 0xA9;
+    public static final int MBOX_TOTALS                     = 0xAA;
+    public static final int QUOTAS                          = 0xAB;
+    public static final int MBOX_QUOTAS                     = 0xAC;
+    public static final int MESSAGE_COUNT                   = 0xAD;
+    public static final int CONTENT                         = 0xAE;
+    public static final int START                           = 0xAF;
+
+    public static final int ADDITIONAL_HEADERS              = 0xB0;
+    public static final int DISTRIBUTION_INDICATOR          = 0xB1;
+    public static final int ELEMENT_DESCRIPTOR              = 0xB2;
+    public static final int LIMIT                           = 0xB3;
+    public static final int RECOMMENDED_RETRIEVAL_MODE      = 0xB4;
+    public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
+    public static final int STATUS_TEXT                     = 0xB6;
+    public static final int APPLIC_ID                       = 0xB7;
+    public static final int REPLY_APPLIC_ID                 = 0xB8;
+    public static final int AUX_APPLIC_ID                   = 0xB9;
+    public static final int CONTENT_CLASS                   = 0xBA;
+    public static final int DRM_CONTENT                     = 0xBB;
+    public static final int ADAPTATION_ALLOWED              = 0xBC;
+    public static final int REPLACE_ID                      = 0xBD;
+    public static final int CANCEL_ID                       = 0xBE;
+    public static final int CANCEL_STATUS                   = 0xBF;
+
+    /**
+     * X-Mms-Message-Type field types.
+     */
+    public static final int MESSAGE_TYPE_SEND_REQ           = 0x80;
+    public static final int MESSAGE_TYPE_SEND_CONF          = 0x81;
+    public static final int MESSAGE_TYPE_NOTIFICATION_IND   = 0x82;
+    public static final int MESSAGE_TYPE_NOTIFYRESP_IND     = 0x83;
+    public static final int MESSAGE_TYPE_RETRIEVE_CONF      = 0x84;
+    public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND    = 0x85;
+    public static final int MESSAGE_TYPE_DELIVERY_IND       = 0x86;
+    public static final int MESSAGE_TYPE_READ_REC_IND       = 0x87;
+    public static final int MESSAGE_TYPE_READ_ORIG_IND      = 0x88;
+    public static final int MESSAGE_TYPE_FORWARD_REQ        = 0x89;
+    public static final int MESSAGE_TYPE_FORWARD_CONF       = 0x8A;
+    public static final int MESSAGE_TYPE_MBOX_STORE_REQ     = 0x8B;
+    public static final int MESSAGE_TYPE_MBOX_STORE_CONF    = 0x8C;
+    public static final int MESSAGE_TYPE_MBOX_VIEW_REQ      = 0x8D;
+    public static final int MESSAGE_TYPE_MBOX_VIEW_CONF     = 0x8E;
+    public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ    = 0x8F;
+    public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF   = 0x90;
+    public static final int MESSAGE_TYPE_MBOX_DELETE_REQ    = 0x91;
+    public static final int MESSAGE_TYPE_MBOX_DELETE_CONF   = 0x92;
+    public static final int MESSAGE_TYPE_MBOX_DESCR         = 0x93;
+    public static final int MESSAGE_TYPE_DELETE_REQ         = 0x94;
+    public static final int MESSAGE_TYPE_DELETE_CONF        = 0x95;
+    public static final int MESSAGE_TYPE_CANCEL_REQ         = 0x96;
+    public static final int MESSAGE_TYPE_CANCEL_CONF        = 0x97;
+
+    /**
+     * X-Mms-Delivery-Report |
+     * X-Mms-Read-Report |
+     * X-Mms-Report-Allowed |
+     * X-Mms-Sender-Visibility |
+     * X-Mms-Store |
+     * X-Mms-Stored |
+     * X-Mms-Totals |
+     * X-Mms-Quotas |
+     * X-Mms-Distribution-Indicator |
+     * X-Mms-DRM-Content |
+     * X-Mms-Adaptation-Allowed |
+     * field types.
+     */
+    public static final int VALUE_YES                       = 0x80;
+    public static final int VALUE_NO                        = 0x81;
+
+    /**
+     * Delivery-Time |
+     * Expiry and Reply-Charging-Deadline |
+     * field type components.
+     */
+    public static final int VALUE_ABSOLUTE_TOKEN            = 0x80;
+    public static final int VALUE_RELATIVE_TOKEN            = 0x81;
+
+    /**
+     * X-Mms-MMS-Version field types.
+     */
+    public static final int MMS_VERSION_1_3                 = ((1 << 4) | 3);
+    public static final int MMS_VERSION_1_2                 = ((1 << 4) | 2);
+    public static final int MMS_VERSION_1_1                 = ((1 << 4) | 1);
+    public static final int MMS_VERSION_1_0                 = ((1 << 4) | 0);
+
+    // Current version is 1.2.
+    public static final int CURRENT_MMS_VERSION             = MMS_VERSION_1_2;
+
+    /**
+     * From field type components.
+     */
+    public static final int FROM_ADDRESS_PRESENT_TOKEN      = 0x80;
+    public static final int FROM_INSERT_ADDRESS_TOKEN       = 0x81;
+
+    public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
+
+    public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
+
+    /**
+     * X-Mms-Status Field.
+     */
+    public static final int STATUS_EXPIRED                  = 0x80;
+    public static final int STATUS_RETRIEVED                = 0x81;
+    public static final int STATUS_REJECTED                 = 0x82;
+    public static final int STATUS_DEFERRED                 = 0x83;
+    public static final int STATUS_UNRECOGNIZED             = 0x84;
+    public static final int STATUS_INDETERMINATE            = 0x85;
+    public static final int STATUS_FORWARDED                = 0x86;
+    public static final int STATUS_UNREACHABLE              = 0x87;
+
+    /**
+     * MM-Flags field type components.
+     */
+    public static final int MM_FLAGS_ADD_TOKEN              = 0x80;
+    public static final int MM_FLAGS_REMOVE_TOKEN           = 0x81;
+    public static final int MM_FLAGS_FILTER_TOKEN           = 0x82;
+
+    /**
+     * X-Mms-Message-Class field types.
+     */
+    public static final int MESSAGE_CLASS_PERSONAL          = 0x80;
+    public static final int MESSAGE_CLASS_ADVERTISEMENT     = 0x81;
+    public static final int MESSAGE_CLASS_INFORMATIONAL     = 0x82;
+    public static final int MESSAGE_CLASS_AUTO              = 0x83;
+
+    public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
+
+    public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
+
+    public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
+
+    public static final String MESSAGE_CLASS_AUTO_STR = "auto";
+
+    /**
+     * X-Mms-Priority field types.
+     */
+    public static final int PRIORITY_LOW                    = 0x80;
+    public static final int PRIORITY_NORMAL                 = 0x81;
+    public static final int PRIORITY_HIGH                   = 0x82;
+
+    /**
+     * X-Mms-Response-Status field types.
+     */
+    public static final int RESPONSE_STATUS_OK                   = 0x80;
+    public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED    = 0x81;
+    public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
+
+    public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT     = 0x83;
+    public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
+
+    public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND    = 0x85;
+    public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM      = 0x86;
+    public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
+    public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE  = 0x88;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE    = 0xC0;
+
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND         = 0xC2;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM           = 0xC3;
+    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS           = 0xC4;
+
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE
+            = 0xE0;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED
+            = 0xE1;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT
+            = 0xE2;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED
+            = 0xE3;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND
+            = 0xE4;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED
+            = 0xE5;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET
+            = 0xE6;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED
+            = 0xE7;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED
+            = 0xE8;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED
+            = 0xE9;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED
+            = 0xEA;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID
+            = 0xEB;
+    public static final int RESPONSE_STATUS_ERROR_PERMANENT_END
+            = 0xFF;
+
+    /**
+     *  X-Mms-Retrieve-Status field types.
+     */
+    public static final int RETRIEVE_STATUS_OK                                  = 0x80;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE             = 0xC0;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND   = 0xC1;
+    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM     = 0xC2;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE             = 0xE0;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED      = 0xE1;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND   = 0xE2;
+    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
+    public static final int RETRIEVE_STATUS_ERROR_END                           = 0xFF;
+
+    /**
+     * X-Mms-Sender-Visibility field types.
+     */
+    public static final int SENDER_VISIBILITY_HIDE          = 0x80;
+    public static final int SENDER_VISIBILITY_SHOW          = 0x81;
+
+    /**
+     * X-Mms-Read-Status field types.
+     */
+    public static final int READ_STATUS_READ                        = 0x80;
+    public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
+
+    /**
+     * X-Mms-Cancel-Status field types.
+     */
+    public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
+    public static final int CANCEL_STATUS_REQUEST_CORRUPTED             = 0x81;
+
+    /**
+     * X-Mms-Reply-Charging field types.
+     */
+    public static final int REPLY_CHARGING_REQUESTED           = 0x80;
+    public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
+    public static final int REPLY_CHARGING_ACCEPTED            = 0x82;
+    public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY  = 0x83;
+
+    /**
+     * X-Mms-MM-State field types.
+     */
+    public static final int MM_STATE_DRAFT                  = 0x80;
+    public static final int MM_STATE_SENT                   = 0x81;
+    public static final int MM_STATE_NEW                    = 0x82;
+    public static final int MM_STATE_RETRIEVED              = 0x83;
+    public static final int MM_STATE_FORWARDED              = 0x84;
+
+    /**
+     * X-Mms-Recommended-Retrieval-Mode field types.
+     */
+    public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
+
+    /**
+     * X-Mms-Content-Class field types.
+     */
+    public static final int CONTENT_CLASS_TEXT              = 0x80;
+    public static final int CONTENT_CLASS_IMAGE_BASIC       = 0x81;
+    public static final int CONTENT_CLASS_IMAGE_RICH        = 0x82;
+    public static final int CONTENT_CLASS_VIDEO_BASIC       = 0x83;
+    public static final int CONTENT_CLASS_VIDEO_RICH        = 0x84;
+    public static final int CONTENT_CLASS_MEGAPIXEL         = 0x85;
+    public static final int CONTENT_CLASS_CONTENT_BASIC     = 0x86;
+    public static final int CONTENT_CLASS_CONTENT_RICH      = 0x87;
+
+    /**
+     * X-Mms-Store-Status field types.
+     */
+    public static final int STORE_STATUS_SUCCESS                                = 0x80;
+    public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE                = 0xC0;
+    public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM        = 0xC1;
+    public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE                = 0xE0;
+    public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED         = 0xE1;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND      = 0xE3;
+    public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL             = 0xE4;
+    public static final int STORE_STATUS_ERROR_END                              = 0xFF;
+
+    /**
+     * The map contains the value of all headers.
+     */
+    private SparseArray<Object> mHeaderMap = null;
+
+    /**
+     * Constructor of PduHeaders.
+     */
+    public PduHeaders() {
+        mHeaderMap = new SparseArray<Object>();
+    }
+
+    /**
+     * Get octet value by header field.
+     *
+     * @param field the field
+     * @return the octet value of the pdu header
+     * with specified header field. Return 0 if
+     * the value is not set.
+     */
+    protected int getOctet(int field) {
+        Integer octet = (Integer) mHeaderMap.get(field);
+        if (null == octet) {
+            return 0;
+        }
+
+        return octet;
+    }
+
+    /**
+     * Set octet value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    protected void setOctet(int value, int field)
+            throws InvalidHeaderValueException {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        switch (field) {
+            case REPORT_ALLOWED:
+            case ADAPTATION_ALLOWED:
+            case DELIVERY_REPORT:
+            case DRM_CONTENT:
+            case DISTRIBUTION_INDICATOR:
+            case QUOTAS:
+            case READ_REPORT:
+            case STORE:
+            case STORED:
+            case TOTALS:
+            case SENDER_VISIBILITY:
+                if ((VALUE_YES != value) && (VALUE_NO != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case READ_STATUS:
+                if ((READ_STATUS_READ != value) &&
+                        (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case CANCEL_STATUS:
+                if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
+                        (CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case PRIORITY:
+                if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case STATUS:
+                if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case REPLY_CHARGING:
+                if ((value < REPLY_CHARGING_REQUESTED)
+                        || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case MM_STATE:
+                if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case RECOMMENDED_RETRIEVAL_MODE:
+                if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case CONTENT_CLASS:
+                if ((value < CONTENT_CLASS_TEXT)
+                        || (value > CONTENT_CLASS_CONTENT_RICH)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            case RETRIEVE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
+                if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
+                        (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
+                        (value <= RETRIEVE_STATUS_ERROR_END)) {
+                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
+                } else if ((value < RETRIEVE_STATUS_OK) ||
+                        ((value > RETRIEVE_STATUS_OK) &&
+                                (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                        (value > RETRIEVE_STATUS_ERROR_END)) {
+                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case STORE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
+                if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
+                        (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
+                        (value <= STORE_STATUS_ERROR_END)) {
+                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
+                } else if ((value < STORE_STATUS_SUCCESS) ||
+                        ((value > STORE_STATUS_SUCCESS) &&
+                                (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                        (value > STORE_STATUS_ERROR_END)) {
+                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case RESPONSE_STATUS:
+                // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
+                if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
+                        (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
+                    value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
+                } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
+                        (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
+                        (value < RESPONSE_STATUS_OK) ||
+                        ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
+                                (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
+                        (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
+                    value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
+                }
+                break;
+            case MMS_VERSION:
+                if ((value < MMS_VERSION_1_0) || (value > MMS_VERSION_1_3)) {
+                    value = CURRENT_MMS_VERSION; // Current version is the default value.
+                }
+                break;
+            case MESSAGE_TYPE:
+                if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
+                    // Invalid value.
+                    throw new InvalidHeaderValueException("Invalid Octet value!");
+                }
+                break;
+            default:
+                // This header value should not be Octect.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Get TextString value by header field.
+     *
+     * @param field the field
+     * @return the TextString value of the pdu header
+     * with specified header field
+     */
+    protected byte[] getTextString(int field) {
+        return (byte[]) mHeaderMap.get(field);
+    }
+
+    /**
+     * Set TextString value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the TextString value of the pdu header
+     * with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setTextString(byte[] value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case TRANSACTION_ID:
+            case REPLY_CHARGING_ID:
+            case AUX_APPLIC_ID:
+            case APPLIC_ID:
+            case REPLY_APPLIC_ID:
+            case MESSAGE_ID:
+            case REPLACE_ID:
+            case CANCEL_ID:
+            case CONTENT_LOCATION:
+            case MESSAGE_CLASS:
+            case CONTENT_TYPE:
+                break;
+            default:
+                // This header value should not be Text-String.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Get EncodedStringValue value by header field.
+     *
+     * @param field the field
+     * @return the EncodedStringValue value of the pdu header
+     * with specified header field
+     */
+    protected EncodedStringValue getEncodedStringValue(int field) {
+        return (EncodedStringValue) mHeaderMap.get(field);
+    }
+
+    /**
+     * Get TO, CC or BCC header value.
+     *
+     * @param field the field
+     * @return the EncodeStringValue array of the pdu header
+     * with specified header field
+     */
+    protected EncodedStringValue[] getEncodedStringValues(int field) {
+        ArrayList<EncodedStringValue> list =
+                (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
+        if (null == list) {
+            return null;
+        }
+        EncodedStringValue[] values = new EncodedStringValue[list.size()];
+        return list.toArray(values);
+    }
+
+    /**
+     * Set EncodedStringValue value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the EncodedStringValue value of the pdu header
+     * with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setEncodedStringValue(EncodedStringValue value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case SUBJECT:
+            case RECOMMENDED_RETRIEVAL_MODE_TEXT:
+            case RETRIEVE_TEXT:
+            case STATUS_TEXT:
+            case STORE_STATUS_TEXT:
+            case RESPONSE_TEXT:
+            case FROM:
+            case PREVIOUSLY_SENT_BY:
+            case MM_FLAGS:
+                break;
+            default:
+                // This header value should not be Encoded-String-Value.
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        mHeaderMap.put(field, value);
+    }
+
+    /**
+     * Set TO, CC or BCC header value.
+     *
+     * @param value the value
+     * @param field the field
+     * @return the EncodedStringValue value array of the pdu header
+     * with specified header field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case BCC:
+            case CC:
+            case TO:
+                break;
+            default:
+                // This header value should not be Encoded-String-Value.
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
+        for (int i = 0; i < value.length; i++) {
+            list.add(value[i]);
+        }
+        mHeaderMap.put(field, list);
+    }
+
+    /**
+     * Append one EncodedStringValue to another.
+     *
+     * @param value the EncodedStringValue to append
+     * @param field the field
+     * @throws NullPointerException if the value is null.
+     */
+    protected void appendEncodedStringValue(EncodedStringValue value,
+            int field) {
+        if (null == value) {
+            throw new NullPointerException();
+        }
+
+        switch (field) {
+            case BCC:
+            case CC:
+            case TO:
+                break;
+            default:
+                throw new RuntimeException("Invalid header field!");
+        }
+
+        ArrayList<EncodedStringValue> list =
+                (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
+        if (null == list) {
+            list = new ArrayList<EncodedStringValue>();
+        }
+        list.add(value);
+        mHeaderMap.put(field, list);
+    }
+
+    /**
+     * Get LongInteger value by header field.
+     *
+     * @param field the field
+     * @return the LongInteger value of the pdu header
+     * with specified header field. if return -1, the
+     * field is not existed in pdu header.
+     */
+    protected long getLongInteger(int field) {
+        Long longInteger = (Long) mHeaderMap.get(field);
+        if (null == longInteger) {
+            return -1;
+        }
+
+        return longInteger.longValue();
+    }
+
+    /**
+     * Set LongInteger value to pdu header by header field.
+     *
+     * @param value the value
+     * @param field the field
+     */
+    protected void setLongInteger(long value, int field) {
+        /**
+         * Check whether this field can be set for specific
+         * header and check validity of the field.
+         */
+        switch (field) {
+            case DATE:
+            case REPLY_CHARGING_SIZE:
+            case MESSAGE_SIZE:
+            case MESSAGE_COUNT:
+            case START:
+            case LIMIT:
+            case DELIVERY_TIME:
+            case EXPIRY:
+            case REPLY_CHARGING_DEADLINE:
+            case PREVIOUSLY_SENT_DATE:
+                break;
+            default:
+                // This header value should not be LongInteger.
+                throw new RuntimeException("Invalid header field!");
+        }
+        mHeaderMap.put(field, value);
+    }
+
+    public boolean hasHeader(int field) {
+        return mHeaderMap.get(field, null) != null;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduParser.java b/src/com/android/messaging/mmslib/pdu/PduParser.java
new file mode 100755
index 0000000..e392fb5
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduParser.java
@@ -0,0 +1,2044 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+import com.android.messaging.util.ContentType;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+public class PduParser {
+    /**
+     * The log tag.
+     */
+    private static final String LOG_TAG = "PduParser";
+
+    private static final boolean LOCAL_LOGV = false;
+
+    /**
+     * The next are WAP values defined in WSP specification.
+     */
+    private static final int QUOTE = 127;
+
+    private static final int LENGTH_QUOTE = 31;
+
+    private static final int TEXT_MIN = 32;
+
+    private static final int TEXT_MAX = 127;
+
+    private static final int SHORT_INTEGER_MAX = 127;
+
+    private static final int SHORT_LENGTH_MAX = 30;
+
+    private static final int LONG_INTEGER_LENGTH_MAX = 8;
+
+    private static final int QUOTED_STRING_FLAG = 34;
+
+    private static final int END_STRING_FLAG = 0x00;
+
+    //The next two are used by the interface "parseWapString" to
+    //distinguish Text-String and Quoted-String.
+    private static final int TYPE_TEXT_STRING = 0;
+
+    private static final int TYPE_QUOTED_STRING = 1;
+
+    private static final int TYPE_TOKEN_STRING = 2;
+
+    /**
+     * Specify the part position.
+     */
+    private static final int THE_FIRST_PART = 0;
+
+    private static final int THE_LAST_PART = 1;
+
+    /**
+     * The pdu data.
+     */
+    private ByteArrayInputStream mPduDataStream = null;
+
+    /**
+     * Store pdu headers
+     */
+    private PduHeaders mHeaders = null;
+
+    /**
+     * Store pdu parts.
+     */
+    private PduBody mBody = null;
+
+    /**
+     * Store the "type" parameter in "Content-Type" header field.
+     */
+    private static byte[] mTypeParam = null;
+
+    /**
+     * Store the "start" parameter in "Content-Type" header field.
+     */
+    private static byte[] mStartParam = null;
+
+    /**
+     * Whether to parse content-disposition part header
+     */
+    private final boolean mParseContentDisposition;
+
+    /**
+     * Constructor.
+     *
+     * @param pduDataStream pdu data to be parsed
+     * @param parseContentDisposition whether to parse the Content-Disposition part header
+     */
+    public PduParser(byte[] pduDataStream, boolean parseContentDisposition) {
+        mPduDataStream = new ByteArrayInputStream(pduDataStream);
+        mParseContentDisposition = parseContentDisposition;
+    }
+
+    /**
+     * Parse the pdu.
+     *
+     * @return the pdu structure if parsing successfully.
+     * null if parsing error happened or mandatory fields are not set.
+     */
+    public GenericPdu parse() {
+        if (mPduDataStream == null) {
+            return null;
+        }
+
+        /* parse headers */
+        mHeaders = parseHeaders(mPduDataStream);
+        if (null == mHeaders) {
+            // Parse headers failed.
+            return null;
+        }
+
+        /* get the message type */
+        int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
+
+        /* check mandatory header fields */
+        if (false == checkMandatoryHeader(mHeaders)) {
+            log("check mandatory headers failed!");
+            return null;
+        }
+        /*
+         * Get retrieve status. If the header is not there, assuming it is OK status.
+         * Some carriers may choose to not send this header.
+         */
+        int retrieveStatus = mHeaders.hasHeader(PduHeaders.RETRIEVE_STATUS) ?
+                mHeaders.getOctet(PduHeaders.RETRIEVE_STATUS) : PduHeaders.RETRIEVE_STATUS_OK;
+
+        if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
+                (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType &&
+                retrieveStatus == PduHeaders.RETRIEVE_STATUS_OK)) {
+            /* need to parse the parts */
+            mBody = parseParts(mPduDataStream);
+            if (null == mBody) {
+                // Parse parts failed.
+                return null;
+            }
+        }
+
+        switch (messageType) {
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_REQ");
+                }
+                SendReq sendReq = new SendReq(mHeaders, mBody);
+                return sendReq;
+            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_CONF");
+                }
+                SendConf sendConf = new SendConf(mHeaders);
+                return sendConf;
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFICATION_IND");
+                }
+                NotificationInd notificationInd =
+                        new NotificationInd(mHeaders);
+                return notificationInd;
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFYRESP_IND");
+                }
+                NotifyRespInd notifyRespInd =
+                        new NotifyRespInd(mHeaders);
+                return notifyRespInd;
+            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF");
+                }
+                RetrieveConf retrieveConf =
+                        new RetrieveConf(mHeaders, mBody);
+                if (retrieveStatus != PduHeaders.RETRIEVE_STATUS_OK) {
+                    // For failure only no need to check content type
+                    return retrieveConf;
+                }
+                byte[] contentType = retrieveConf.getContentType();
+                if (null == contentType) {
+                    return null;
+                }
+                String ctTypeStr = new String(contentType);
+                if (ctTypeStr.equals(ContentType.MMS_MULTIPART_MIXED)
+                        || ctTypeStr.equals(ContentType.MMS_MULTIPART_RELATED)
+                        || ctTypeStr.equals(ContentType.MMS_MULTIPART_ALTERNATIVE)) {
+                    // The MMS content type must be "application/vnd.wap.multipart.mixed"
+                    // or "application/vnd.wap.multipart.related"
+                    // or "application/vnd.wap.multipart.alternative"
+                    return retrieveConf;
+                } else if (ctTypeStr.equals(ContentType.MMS_MULTIPART_ALTERNATIVE)) {
+                    // "application/vnd.wap.multipart.alternative"
+                    // should take only the first part.
+                    PduPart firstPart = mBody.getPart(0);
+                    mBody.removeAll();
+                    mBody.addPart(0, firstPart);
+                    return retrieveConf;
+                }
+                return null;
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_DELIVERY_IND");
+                }
+                DeliveryInd deliveryInd =
+                        new DeliveryInd(mHeaders);
+                return deliveryInd;
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_ACKNOWLEDGE_IND");
+                }
+                AcknowledgeInd acknowledgeInd =
+                        new AcknowledgeInd(mHeaders);
+                return acknowledgeInd;
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_ORIG_IND");
+                }
+                ReadOrigInd readOrigInd =
+                        new ReadOrigInd(mHeaders);
+                return readOrigInd;
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_REC_IND");
+                }
+                ReadRecInd readRecInd =
+                        new ReadRecInd(mHeaders);
+                return readRecInd;
+            default:
+                log("Parser doesn't support this message type in this version!");
+                return null;
+        }
+    }
+
+    /**
+     * Parse pdu headers.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return headers in PduHeaders structure, null when parse fail
+     */
+    protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream) {
+        if (pduDataStream == null) {
+            return null;
+        }
+        boolean keepParsing = true;
+        PduHeaders headers = new PduHeaders();
+
+        while (keepParsing && (pduDataStream.available() > 0)) {
+            pduDataStream.mark(1);
+            int headerField = extractByteValue(pduDataStream);
+            /* parse custom text header */
+            if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
+                pduDataStream.reset();
+                byte[] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
+                }
+                /* we should ignore it at the moment */
+                continue;
+            }
+            switch (headerField) {
+                case PduHeaders.MESSAGE_TYPE: {
+                    int messageType = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: messageType: " + messageType +
+                                " (" + Integer.toHexString(headerField) + ")");
+                    }
+                    switch (messageType) {
+                        // We don't support these kind of messages now.
+                        case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
+                        case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
+                        case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
+                        case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
+                        case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
+                        case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
+                            return null;
+                    }
+                    try {
+                        headers.setOctet(messageType, headerField);
+                    } catch (InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + messageType +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+                /* Octect value */
+                case PduHeaders.REPORT_ALLOWED:
+                case PduHeaders.ADAPTATION_ALLOWED:
+                case PduHeaders.DELIVERY_REPORT:
+                case PduHeaders.DRM_CONTENT:
+                case PduHeaders.DISTRIBUTION_INDICATOR:
+                case PduHeaders.QUOTAS:
+                case PduHeaders.READ_REPORT:
+                case PduHeaders.STORE:
+                case PduHeaders.STORED:
+                case PduHeaders.TOTALS:
+                case PduHeaders.SENDER_VISIBILITY:
+                case PduHeaders.READ_STATUS:
+                case PduHeaders.CANCEL_STATUS:
+                case PduHeaders.PRIORITY:
+                case PduHeaders.STATUS:
+                case PduHeaders.REPLY_CHARGING:
+                case PduHeaders.MM_STATE:
+                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE:
+                case PduHeaders.CONTENT_CLASS:
+                case PduHeaders.RETRIEVE_STATUS:
+                case PduHeaders.STORE_STATUS:
+                    /**
+                     * The following field has a different value when
+                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
+                     * For now we ignore this fact, since we do not support these PDUs
+                     */
+                case PduHeaders.RESPONSE_STATUS: {
+                    int value = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ") Octect value: " +
+                                value);
+                    }
+
+                    try {
+                        headers.setOctet(value, headerField);
+                    } catch (InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + value +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Long-Integer */
+                case PduHeaders.DATE:
+                case PduHeaders.REPLY_CHARGING_SIZE:
+                case PduHeaders.MESSAGE_SIZE: {
+                    try {
+                        long value = parseLongInteger(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) + ") longint value: " +
+                                    value);
+                        }
+                        headers.setLongInteger(value, headerField);
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Integer-Value */
+                case PduHeaders.MESSAGE_COUNT:
+                case PduHeaders.START:
+                case PduHeaders.LIMIT: {
+                    try {
+                        long value = parseIntegerValue(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) + ") integer value: " +
+                                    value);
+                        }
+                        headers.setLongInteger(value, headerField);
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                /* Text-String */
+                case PduHeaders.TRANSACTION_ID:
+                case PduHeaders.REPLY_CHARGING_ID:
+                case PduHeaders.AUX_APPLIC_ID:
+                case PduHeaders.APPLIC_ID:
+                case PduHeaders.REPLY_APPLIC_ID:
+                    /**
+                     * The next three header fields are email addresses
+                     * as defined in RFC2822,
+                     * not including the characters "<" and ">"
+                     */
+                case PduHeaders.MESSAGE_ID:
+                case PduHeaders.REPLACE_ID:
+                case PduHeaders.CANCEL_ID:
+                    /**
+                     * The following field has a different value when
+                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
+                     * For now we ignore this fact, since we do not support these PDUs
+                     */
+                case PduHeaders.CONTENT_LOCATION: {
+                    byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if (null != value) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                        " (" + Integer.toHexString(headerField) + ") string value: "
+                                        +
+                                        new String(value));
+                            }
+                            headers.setTextString(value, headerField);
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Encoded-string-value */
+                case PduHeaders.SUBJECT:
+                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT:
+                case PduHeaders.RETRIEVE_TEXT:
+                case PduHeaders.STATUS_TEXT:
+                case PduHeaders.STORE_STATUS_TEXT:
+                    /* the next one is not support
+                     * M-Mbox-Delete.conf and M-Delete.conf now */
+                case PduHeaders.RESPONSE_TEXT: {
+                    EncodedStringValue value =
+                            parseEncodedStringValue(pduDataStream);
+                    if (null != value) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                        " (" + Integer.toHexString(headerField)
+                                        + ") encoded string: " +
+                                        value.getString());
+                            }
+                            headers.setEncodedStringValue(value, headerField);
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Addressing model */
+                case PduHeaders.BCC:
+                case PduHeaders.CC:
+                case PduHeaders.TO: {
+                    EncodedStringValue value =
+                            parseEncodedStringValue(pduDataStream);
+                    if (null != value) {
+                        byte[] address = value.getTextString();
+                        if (null != address) {
+                            String str = new String(address);
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: (to/cc/bcc) address: " + headerField
+                                        + " value: " + str);
+                            }
+                            int endIndex = str.indexOf("/");
+                            if (endIndex > 0) {
+                                str = str.substring(0, endIndex);
+                            }
+                            try {
+                                value.setTextString(str.getBytes());
+                            } catch (NullPointerException e) {
+                                log("null pointer error!");
+                                return null;
+                            }
+                        }
+
+                        try {
+                            headers.appendEncodedStringValue(value, headerField);
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                /* Value-length
+                 * (Absolute-token Date-value | Relative-token Delta-seconds-value) */
+                case PduHeaders.DELIVERY_TIME:
+                case PduHeaders.EXPIRY:
+                case PduHeaders.REPLY_CHARGING_DEADLINE: {
+                    /* parse Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Absolute-token or Relative-token */
+                    int token = extractByteValue(pduDataStream);
+
+                    /* Date-value or Delta-seconds-value */
+                    long timeValue;
+                    try {
+                        timeValue = parseLongInteger(pduDataStream);
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    if (PduHeaders.VALUE_RELATIVE_TOKEN == token) {
+                        /* need to convert the Delta-seconds-value
+                         * into Date-value */
+                        timeValue = System.currentTimeMillis() / 1000 + timeValue;
+                    }
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) + ") time value: " +
+                                    timeValue);
+                        }
+                        headers.setLongInteger(timeValue, headerField);
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.FROM: {
+                    /* From-value =
+                     * Value-length
+                     * (Address-present-token Encoded-string-value | Insert-address-token)
+                     */
+                    EncodedStringValue from = null;
+                    parseValueLength(pduDataStream); /* parse value-length */
+
+                    /* Address-present-token or Insert-address-token */
+                    int fromToken = extractByteValue(pduDataStream);
+
+                    /* Address-present-token or Insert-address-token */
+                    if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) {
+                        /* Encoded-string-value */
+                        from = parseEncodedStringValue(pduDataStream);
+                        if (null != from) {
+                            byte[] address = from.getTextString();
+                            if (null != address) {
+                                String str = new String(address);
+                                int endIndex = str.indexOf("/");
+                                if (endIndex > 0) {
+                                    str = str.substring(0, endIndex);
+                                }
+                                try {
+                                    from.setTextString(str.getBytes());
+                                } catch (NullPointerException e) {
+                                    log("null pointer error!");
+                                    return null;
+                                }
+                            }
+                        }
+                    } else {
+                        try {
+                            from = new EncodedStringValue(
+                                    PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes());
+                        } catch (NullPointerException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) + ") from address: " +
+                                    from.getString());
+                        }
+                        headers.setEncodedStringValue(from, PduHeaders.FROM);
+                    } catch (NullPointerException e) {
+                        log("null pointer error!");
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Encoded-String-Value header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.MESSAGE_CLASS: {
+                    /* Message-class-value = Class-identifier | Token-text */
+                    pduDataStream.mark(1);
+                    int messageClass = extractByteValue(pduDataStream);
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ") MESSAGE_CLASS: " +
+                                messageClass);
+                    }
+
+                    if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) {
+                        /* Class-identifier */
+                        try {
+                            if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) {
+                                headers.setTextString(
+                                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(),
+                                        PduHeaders.MESSAGE_CLASS);
+                            }
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    } else {
+                        /* Token-text */
+                        pduDataStream.reset();
+                        byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if (null != messageClassString) {
+                            try {
+                                headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS);
+                            } catch (NullPointerException e) {
+                                log("null pointer error!");
+                            } catch (RuntimeException e) {
+                                log(headerField + "is not Text-String header field!");
+                                return null;
+                            }
+                        }
+                    }
+                    break;
+                }
+
+                case PduHeaders.MMS_VERSION: {
+                    int version = parseShortInteger(pduDataStream);
+
+                    try {
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) + ") MMS_VERSION: " +
+                                    version);
+                        }
+                        headers.setOctet(version, PduHeaders.MMS_VERSION);
+                    } catch (InvalidHeaderValueException e) {
+                        log("Set invalid Octet value: " + version +
+                                " into the header filed: " + headerField);
+                        return null;
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Octet header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.PREVIOUSLY_SENT_BY: {
+                    /* Previously-sent-by-value =
+                     * Value-length Forwarded-count-value Encoded-string-value */
+                    /* parse value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* parse Forwarded-count-value */
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch (RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* parse Encoded-string-value */
+                    EncodedStringValue previouslySentBy =
+                            parseEncodedStringValue(pduDataStream);
+                    if (null != previouslySentBy) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                        " (" + Integer.toHexString(headerField) +
+                                        ") PREVIOUSLY_SENT_BY: " + previouslySentBy.getString());
+                            }
+                            headers.setEncodedStringValue(previouslySentBy,
+                                    PduHeaders.PREVIOUSLY_SENT_BY);
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Encoded-String-Value header field!");
+                            return null;
+                        }
+                    }
+                    break;
+                }
+
+                case PduHeaders.PREVIOUSLY_SENT_DATE: {
+                    /* Previously-sent-date-value =
+                     * Value-length Forwarded-count-value Date-value */
+                    /* parse value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* parse Forwarded-count-value */
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch (RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* Date-value */
+                    try {
+                        long previouslySentDate = parseLongInteger(pduDataStream);
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                    " (" + Integer.toHexString(headerField) +
+                                    ") PREVIOUSLY_SENT_DATE: " + previouslySentDate);
+                        }
+                        headers.setLongInteger(previouslySentDate,
+                                PduHeaders.PREVIOUSLY_SENT_DATE);
+                    } catch (RuntimeException e) {
+                        log(headerField + "is not Long-Integer header field!");
+                        return null;
+                    }
+                    break;
+                }
+
+                case PduHeaders.MM_FLAGS: {
+                    /* MM-flags-value =
+                     * Value-length
+                     * ( Add-token | Remove-token | Filter-token )
+                     * Encoded-string-value
+                     */
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ") MM_FLAGS: " +
+                                " NOT REALLY SUPPORTED");
+                    }
+
+                    /* parse Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Add-token | Remove-token | Filter-token */
+                    extractByteValue(pduDataStream);
+
+                    /* Encoded-string-value */
+                    parseEncodedStringValue(pduDataStream);
+
+                    /* not store this header filed in "headers",
+                     * because now PduHeaders doesn't support it */
+                    break;
+                }
+
+                /* Value-length
+                 * (Message-total-token | Size-total-token) Integer-Value */
+                case PduHeaders.MBOX_TOTALS:
+                case PduHeaders.MBOX_QUOTAS: {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ") MBOX_");
+                    }
+                    /* Value-length */
+                    parseValueLength(pduDataStream);
+
+                    /* Message-total-token | Size-total-token */
+                    extractByteValue(pduDataStream);
+
+                    /*Integer-Value*/
+                    try {
+                        parseIntegerValue(pduDataStream);
+                    } catch (RuntimeException e) {
+                        log(headerField + " is not Integer-Value");
+                        return null;
+                    }
+
+                    /* not store these headers filed in "headers",
+                    because now PduHeaders doesn't support them */
+                    break;
+                }
+
+                case PduHeaders.ELEMENT_DESCRIPTOR: {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ") ELEMENT_DESCRIPTOR");
+                    }
+                    parseContentType(pduDataStream, null);
+
+                    /* not store this header filed in "headers",
+                    because now PduHeaders doesn't support it */
+                    break;
+                }
+
+                case PduHeaders.CONTENT_TYPE: {
+                    SparseArray<Object> map = new SparseArray<Object>();
+                    byte[] contentType =
+                            parseContentType(pduDataStream, map);
+
+                    if (null != contentType) {
+                        try {
+                            if (LOCAL_LOGV) {
+                                Log.v(LOG_TAG, "parseHeaders: headerField: " + headerField +
+                                        " (" + Integer.toHexString(headerField) + ") CONTENT_TYPE: "
+                                        + Arrays.toString(contentType));
+                            }
+                            headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
+                        } catch (NullPointerException e) {
+                            log("null pointer error!");
+                        } catch (RuntimeException e) {
+                            log(headerField + "is not Text-String header field!");
+                            return null;
+                        }
+                    }
+
+                    /* get start parameter */
+                    mStartParam = (byte[]) map.get(PduPart.P_START);
+
+                    /* get charset parameter */
+                    mTypeParam = (byte[]) map.get(PduPart.P_TYPE);
+
+                    keepParsing = false;
+                    break;
+                }
+
+                case PduHeaders.CONTENT:
+                case PduHeaders.ADDITIONAL_HEADERS:
+                case PduHeaders.ATTRIBUTES:
+                default: {
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "parseHeaders: Unknown header: " + headerField +
+                                " (" + Integer.toHexString(headerField) + ")");
+                    }
+                    log("Unknown header");
+                }
+            }
+        }
+
+        return headers;
+    }
+
+    /**
+     * Parse pdu parts.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return parts in PduBody structure
+     */
+    protected PduBody parseParts(ByteArrayInputStream pduDataStream) {
+        if (pduDataStream == null) {
+            return null;
+        }
+
+        int count = parseUnsignedInt(pduDataStream); // get the number of parts
+        PduBody body = new PduBody();
+
+        for (int i = 0; i < count; i++) {
+            int headerLength = parseUnsignedInt(pduDataStream);
+            int dataLength = parseUnsignedInt(pduDataStream);
+            PduPart part = new PduPart();
+            int startPos = pduDataStream.available();
+            if (startPos <= 0) {
+                // Invalid part.
+                return null;
+            }
+
+            /* parse part's content-type */
+            SparseArray<Object> map = new SparseArray<Object>();
+            byte[] contentType = parseContentType(pduDataStream, map);
+            if (null != contentType) {
+                part.setContentType(contentType);
+            } else {
+                part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
+            }
+
+            /* get name parameter */
+            byte[] name = (byte[]) map.get(PduPart.P_NAME);
+            if (null != name) {
+                part.setName(name);
+            }
+
+            /* get charset parameter */
+            Integer charset = (Integer) map.get(PduPart.P_CHARSET);
+            if (null != charset) {
+                part.setCharset(charset);
+            }
+
+            /* parse part's headers */
+            int endPos = pduDataStream.available();
+            int partHeaderLen = headerLength - (startPos - endPos);
+            if (partHeaderLen > 0) {
+                if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
+                    // Parse part header faild.
+                    return null;
+                }
+            } else if (partHeaderLen < 0) {
+                // Invalid length of content-type.
+                return null;
+            }
+
+            /* TODO: check content-id, name, filename and content location,
+             * if not set anyone of them, generate a default content-location
+             */
+            if ((null == part.getContentLocation())
+                    && (null == part.getName())
+                    && (null == part.getFilename())
+                    && (null == part.getContentId())) {
+                part.setContentLocation(Long.toOctalString(
+                        System.currentTimeMillis()).getBytes());
+            }
+
+            /* get part's data */
+            if (dataLength > 0) {
+                byte[] partData = new byte[dataLength];
+                String partContentType = new String(part.getContentType());
+                pduDataStream.read(partData, 0, dataLength);
+                if (partContentType.equalsIgnoreCase(ContentType.MMS_MULTIPART_ALTERNATIVE)) {
+                    // parse "multipart/vnd.wap.multipart.alternative".
+                    PduBody childBody = parseParts(new ByteArrayInputStream(partData));
+                    // take the first part of children.
+                    part = childBody.getPart(0);
+                } else {
+                    // Check Content-Transfer-Encoding.
+                    byte[] partDataEncoding = part.getContentTransferEncoding();
+                    if (null != partDataEncoding) {
+                        String encoding = new String(partDataEncoding);
+                        if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
+                            // Decode "base64" into "binary".
+                            partData = Base64.decodeBase64(partData);
+                        } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
+                            // Decode "quoted-printable" into "binary".
+                            partData = QuotedPrintable.decodeQuotedPrintable(partData);
+                        } else {
+                            // "binary" is the default encoding.
+                        }
+                    }
+                    if (null == partData) {
+                        log("Decode part data error!");
+                        return null;
+                    }
+                    part.setData(partData);
+                }
+            }
+
+            /* add this part to body */
+            if (THE_FIRST_PART == checkPartPosition(part)) {
+                /* this is the first part */
+                body.addPart(0, part);
+            } else {
+                /* add the part to the end */
+                body.addPart(part);
+            }
+        }
+
+        return body;
+    }
+
+    /**
+     * Log status.
+     *
+     * @param text log information
+     */
+    private static void log(String text) {
+        if (LOCAL_LOGV) {
+            Log.v(LOG_TAG, text);
+        }
+    }
+
+    /**
+     * Parse unsigned integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the integer, -1 when failed
+     */
+    protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * The maximum size of a uintvar is 32 bits.
+         * So it will be encoded in no more than 5 octets.
+         */
+        assert (null != pduDataStream);
+        int result = 0;
+        int temp = pduDataStream.read();
+        if (temp == -1) {
+            return temp;
+        }
+
+        while ((temp & 0x80) != 0) {
+            result = result << 7;
+            result |= temp & 0x7F;
+            temp = pduDataStream.read();
+            if (temp == -1) {
+                return temp;
+            }
+        }
+
+        result = result << 7;
+        result |= temp & 0x7F;
+
+        return result;
+    }
+
+    /**
+     * Parse value length.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the integer
+     */
+    protected static int parseValueLength(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Value-length = Short-length | (Length-quote Length)
+         * Short-length = <Any octet 0-30>
+         * Length-quote = <Octet 31>
+         * Length = Uintvar-integer
+         * Uintvar-integer = 1*5 OCTET
+         */
+        assert (null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        int first = temp & 0xFF;
+
+        if (first <= SHORT_LENGTH_MAX) {
+            return first;
+        } else if (first == LENGTH_QUOTE) {
+            return parseUnsignedInt(pduDataStream);
+        }
+
+        throw new RuntimeException("Value length > LENGTH_QUOTE!");
+    }
+
+    /**
+     * Parse encoded string value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the EncodedStringValue
+     */
+    protected static EncodedStringValue parseEncodedStringValue(
+            ByteArrayInputStream pduDataStream) {
+        /**
+         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf
+         * Encoded-string-value = Text-string | Value-length Char-set Text-string
+         */
+        assert (null != pduDataStream);
+        pduDataStream.mark(1);
+        EncodedStringValue returnValue = null;
+        int charset = 0;
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        int first = temp & 0xFF;
+        if (first == 0) {
+            return null;    //  Blank subject, bail.
+        }
+
+        pduDataStream.reset();
+        if (first < TEXT_MIN) {
+            parseValueLength(pduDataStream);
+
+            charset = parseShortInteger(pduDataStream); //get the "Charset"
+        }
+
+        byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+
+        try {
+            if (0 != charset) {
+                returnValue = new EncodedStringValue(charset, textString);
+            } else {
+                returnValue = new EncodedStringValue(textString);
+            }
+        } catch (Exception e) {
+            return null;
+        }
+
+        return returnValue;
+    }
+
+    /**
+     * Parse Text-String or Quoted-String.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param stringType    TYPE_TEXT_STRING or TYPE_QUOTED_STRING
+     * @return the string without End-of-string in byte array
+     */
+    protected static byte[] parseWapString(ByteArrayInputStream pduDataStream,
+            int stringType) {
+        assert (null != pduDataStream);
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Text-string = [Quote] *TEXT End-of-string
+         * If the first character in the TEXT is in the range of 128-255,
+         * a Quote character must precede it.
+         * Otherwise the Quote character must be omitted.
+         * The Quote is not part of the contents.
+         * Quote = <Octet 127>
+         * End-of-string = <Octet 0>
+         *
+         * Quoted-string = <Octet 34> *TEXT End-of-string
+         *
+         * Token-text = Token End-of-string
+         */
+
+        // Mark supposed beginning of Text-string
+        // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG
+        pduDataStream.mark(1);
+
+        // Check first char
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        if ((TYPE_QUOTED_STRING == stringType) &&
+                (QUOTED_STRING_FLAG == temp)) {
+            // Mark again if QUOTED_STRING_FLAG and ignore it
+            pduDataStream.mark(1);
+        } else if ((TYPE_TEXT_STRING == stringType) &&
+                (QUOTE == temp)) {
+            // Mark again if QUOTE and ignore it
+            pduDataStream.mark(1);
+        } else {
+            // Otherwise go back to origin
+            pduDataStream.reset();
+        }
+
+        // We are now definitely at the beginning of string
+        /**
+         * Return *TOKEN or *TEXT (Text-String without QUOTE,
+         * Quoted-String without QUOTED_STRING_FLAG and without End-of-string)
+         */
+        return getWapString(pduDataStream, stringType);
+    }
+
+    /**
+     * Check TOKEN data defined in RFC2616.
+     *
+     * @param ch checking data
+     * @return true when ch is TOKEN, false when ch is not TOKEN
+     */
+    protected static boolean isTokenCharacter(int ch) {
+        /**
+         * Token      = 1*<any CHAR except CTLs or separators>
+         * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64)
+         *            | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34)
+         *            | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61)
+         *            | "{"(123) | "}"(125) | SP(32) | HT(9)
+         * CHAR       = <any US-ASCII character (octets 0 - 127)>
+         * CTL        = <any US-ASCII control character
+         *            (octets 0 - 31) and DEL (127)>
+         * SP         = <US-ASCII SP, space (32)>
+         * HT         = <US-ASCII HT, horizontal-tab (9)>
+         */
+        if ((ch < 33) || (ch > 126)) {
+            return false;
+        }
+
+        switch (ch) {
+            case '"': /* '"' */
+            case '(': /* '(' */
+            case ')': /* ')' */
+            case ',': /* ',' */
+            case '/': /* '/' */
+            case ':': /* ':' */
+            case ';': /* ';' */
+            case '<': /* '<' */
+            case '=': /* '=' */
+            case '>': /* '>' */
+            case '?': /* '?' */
+            case '@': /* '@' */
+            case '[': /* '[' */
+            case '\\': /* '\' */
+            case ']': /* ']' */
+            case '{': /* '{' */
+            case '}': /* '}' */
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check TEXT data defined in RFC2616.
+     *
+     * @param ch checking data
+     * @return true when ch is TEXT, false when ch is not TEXT
+     */
+    protected static boolean isText(int ch) {
+        /**
+         * TEXT = <any OCTET except CTLs,
+         *      but including LWS>
+         * CTL  = <any US-ASCII control character
+         *      (octets 0 - 31) and DEL (127)>
+         * LWS  = [CRLF] 1*( SP | HT )
+         * CRLF = CR LF
+         * CR   = <US-ASCII CR, carriage return (13)>
+         * LF   = <US-ASCII LF, linefeed (10)>
+         */
+        if (((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) {
+            return true;
+        }
+
+        switch (ch) {
+            case '\t': /* '\t' */
+            case '\n': /* '\n' */
+            case '\r': /* '\r' */
+                return true;
+        }
+
+        return false;
+    }
+
+    protected static byte[] getWapString(ByteArrayInputStream pduDataStream,
+            int stringType) {
+        assert (null != pduDataStream);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        while ((-1 != temp) && ('\0' != temp)) {
+            // check each of the character
+            if (stringType == TYPE_TOKEN_STRING) {
+                if (isTokenCharacter(temp)) {
+                    out.write(temp);
+                }
+            } else {
+                if (isText(temp)) {
+                    out.write(temp);
+                }
+            }
+
+            temp = pduDataStream.read();
+            assert (-1 != temp);
+        }
+
+        if (out.size() > 0) {
+            return out.toByteArray();
+        }
+
+        return null;
+    }
+
+    /**
+     * Extract a byte value from the input stream.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the byte
+     */
+    protected static int extractByteValue(ByteArrayInputStream pduDataStream) {
+        assert (null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        return temp & 0xFF;
+    }
+
+    /**
+     * Parse Short-Integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return the byte
+     */
+    protected static int parseShortInteger(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Short-integer = OCTET
+         * Integers in range 0-127 shall be encoded as a one
+         * octet value with the most significant bit set to one (1xxx xxxx)
+         * and with the value in the remaining least significant bits.
+         */
+        assert (null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        return temp & 0x7F;
+    }
+
+    /**
+     * Parse Long-Integer.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return long integer
+     */
+    protected static long parseLongInteger(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Long-integer = Short-length Multi-octet-integer
+         * The Short-length indicates the length of the Multi-octet-integer
+         * Multi-octet-integer = 1*30 OCTET
+         * The content octets shall be an unsigned integer value
+         * with the most significant octet encoded first (big-endian representation).
+         * The minimum number of octets must be used to encode the value.
+         * Short-length = <Any octet 0-30>
+         */
+        assert (null != pduDataStream);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        int count = temp & 0xFF;
+
+        if (count > LONG_INTEGER_LENGTH_MAX) {
+            throw new RuntimeException("Octet count greater than 8 and I can't represent that!");
+        }
+
+        long result = 0;
+
+        for (int i = 0; i < count; i++) {
+            temp = pduDataStream.read();
+            assert (-1 != temp);
+            result <<= 8;
+            result += (temp & 0xFF);
+        }
+
+        return result;
+    }
+
+    /**
+     * Parse Integer-Value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @return long integer
+     */
+    protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Integer-Value = Short-integer | Long-integer
+         */
+        assert (null != pduDataStream);
+        pduDataStream.mark(1);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        pduDataStream.reset();
+        if (temp > SHORT_INTEGER_MAX) {
+            return parseShortInteger(pduDataStream);
+        } else {
+            return parseLongInteger(pduDataStream);
+        }
+    }
+
+    /**
+     * To skip length of the wap value.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param length        area size
+     * @return the values in this area
+     */
+    protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) {
+        assert (null != pduDataStream);
+        byte[] area = new byte[length];
+        int readLen = pduDataStream.read(area, 0, length);
+        if (readLen < length) { //The actually read length is lower than the length
+            return -1;
+        } else {
+            return readLen;
+        }
+    }
+
+    /**
+     * Parse content type parameters. For now we just support
+     * four parameters used in mms: "type", "start", "name", "charset".
+     *
+     * @param pduDataStream pdu data input stream
+     * @param map           to store parameters of Content-Type field
+     * @param length        length of all the parameters
+     */
+    protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream,
+            SparseArray<Object> map, Integer length) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Parameter = Typed-parameter | Untyped-parameter
+         * Typed-parameter = Well-known-parameter-token Typed-value
+         * the actual expected type of the value is implied by the well-known parameter
+         * Well-known-parameter-token = Integer-value
+         * the code values used for parameters are specified in the Assigned Numbers appendix
+         * Typed-value = Compact-value | Text-value
+         * In addition to the expected type, there may be no value.
+         * If the value cannot be encoded using the expected type, it shall be encoded as text.
+         * Compact-value = Integer-value |
+         * Date-value | Delta-seconds-value | Q-value | Version-value |
+         * Uri-value
+         * Untyped-parameter = Token-text Untyped-value
+         * the type of the value is unknown, but it shall be encoded as an integer,
+         * if that is possible.
+         * Untyped-value = Integer-value | Text-value
+         */
+        assert (null != pduDataStream);
+        assert (length > 0);
+
+        int startPos = pduDataStream.available();
+        int tempPos = 0;
+        int lastLen = length;
+        while (0 < lastLen) {
+            int param = pduDataStream.read();
+            assert (-1 != param);
+            lastLen--;
+
+            switch (param) {
+                /**
+                 * From rfc2387, chapter 3.1
+                 * The type parameter must be specified and its value is the MIME media
+                 * type of the "root" body part. It permits a MIME user agent to
+                 * determine the content-type without reference to the enclosed body
+                 * part. If the value of the type parameter and the root body part's
+                 * content-type differ then the User Agent's behavior is undefined.
+                 *
+                 * From wap-230-wsp-20010705-a.pdf
+                 * type = Constrained-encoding
+                 * Constrained-encoding = Extension-Media | Short-integer
+                 * Extension-media = *TEXT End-of-string
+                 */
+                case PduPart.P_TYPE:
+                case PduPart.P_CT_MR_TYPE:
+                    pduDataStream.mark(1);
+                    int first = extractByteValue(pduDataStream);
+                    pduDataStream.reset();
+                    if (first > TEXT_MAX) {
+                        // Short-integer (well-known type)
+                        int index = parseShortInteger(pduDataStream);
+
+                        if (index < PduContentTypes.contentTypes.length) {
+                            byte[] type = (PduContentTypes.contentTypes[index]).getBytes();
+                            map.put(PduPart.P_TYPE, type);
+                        } else {
+                            //not support this type, ignore it.
+                        }
+                    } else {
+                        // Text-String (extension-media)
+                        byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if ((null != type) && (null != map)) {
+                            map.put(PduPart.P_TYPE, type);
+                        }
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3.
+                     * Start Parameter Referring to Presentation
+                     *
+                     * From rfc2387, chapter 3.2
+                     * The start parameter, if given, is the content-ID of the compound
+                     * object's "root". If not present the "root" is the first body part in
+                     * the Multipart/Related entity. The "root" is the element the
+                     * applications processes first.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * start = Text-String
+                     */
+                case PduPart.P_START:
+                case PduPart.P_DEP_START:
+                    byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if ((null != start) && (null != map)) {
+                        map.put(PduPart.P_START, start);
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf
+                     * In creation, the character set SHALL be either us-ascii
+                     * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode].
+                     * In retrieval, both us-ascii and utf-8 SHALL be supported.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * charset = Well-known-charset|Text-String
+                     * Well-known-charset = Any-charset | Integer-value
+                     * Both are encoded using values from Character Set
+                     * Assignments table in Assigned Numbers
+                     * Any-charset = <Octet 128>
+                     * Equivalent to the special RFC2616 charset value "*"
+                     */
+                case PduPart.P_CHARSET:
+                    pduDataStream.mark(1);
+                    int firstValue = extractByteValue(pduDataStream);
+                    pduDataStream.reset();
+                    //Check first char
+                    if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) ||
+                            (END_STRING_FLAG == firstValue)) {
+                        //Text-String (extension-charset)
+                        byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        try {
+                            int charsetInt = CharacterSets.getMibEnumValue(
+                                    new String(charsetStr));
+                            map.put(PduPart.P_CHARSET, charsetInt);
+                        } catch (UnsupportedEncodingException e) {
+                            // Not a well-known charset, use "*".
+                            Log.e(LOG_TAG, Arrays.toString(charsetStr), e);
+                            map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET);
+                        }
+                    } else {
+                        //Well-known-charset
+                        int charset = (int) parseIntegerValue(pduDataStream);
+                        if (map != null) {
+                            map.put(PduPart.P_CHARSET, charset);
+                        }
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+
+                    /**
+                     * From oma-ts-mms-conf-v1_3.pdf
+                     * A name for multipart object SHALL be encoded using name-parameter
+                     * for Content-Type header in WSP multipart headers.
+                     *
+                     * From wap-230-wsp-20010705-a.pdf
+                     * name = Text-String
+                     */
+                case PduPart.P_DEP_NAME:
+                case PduPart.P_NAME:
+                    byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                    if ((null != name) && (null != map)) {
+                        map.put(PduPart.P_NAME, name);
+                    }
+
+                    tempPos = pduDataStream.available();
+                    lastLen = length - (startPos - tempPos);
+                    break;
+                default:
+                    if (LOCAL_LOGV) {
+                        Log.v(LOG_TAG, "Not supported Content-Type parameter");
+                    }
+                    if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                        Log.e(LOG_TAG, "Corrupt Content-Type");
+                    } else {
+                        lastLen = 0;
+                    }
+                    break;
+            }
+        }
+
+        if (0 != lastLen) {
+            Log.e(LOG_TAG, "Corrupt Content-Type");
+        }
+    }
+
+    /**
+     * Parse content type.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param map           to store parameters in Content-Type header field
+     * @return Content-Type value
+     */
+    protected static byte[] parseContentType(ByteArrayInputStream pduDataStream,
+            SparseArray<Object> map) {
+        /**
+         * From wap-230-wsp-20010705-a.pdf
+         * Content-type-value = Constrained-media | Content-general-form
+         * Content-general-form = Value-length Media-type
+         * Media-type = (Well-known-media | Extension-Media) *(Parameter)
+         */
+        assert (null != pduDataStream);
+
+        byte[] contentType = null;
+        pduDataStream.mark(1);
+        int temp = pduDataStream.read();
+        assert (-1 != temp);
+        pduDataStream.reset();
+
+        int cur = (temp & 0xFF);
+
+        if (cur < TEXT_MIN) {
+            int length = parseValueLength(pduDataStream);
+            int startPos = pduDataStream.available();
+            pduDataStream.mark(1);
+            temp = pduDataStream.read();
+            assert (-1 != temp);
+            pduDataStream.reset();
+            int first = (temp & 0xFF);
+
+            if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) {
+                contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+            } else if (first > TEXT_MAX) {
+                int index = parseShortInteger(pduDataStream);
+
+                if (index < PduContentTypes.contentTypes.length) { //well-known type
+                    contentType = (PduContentTypes.contentTypes[index]).getBytes();
+                } else {
+                    pduDataStream.reset();
+                    contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                }
+            } else {
+                Log.e(LOG_TAG, "Corrupt content-type");
+                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
+            }
+
+            int endPos = pduDataStream.available();
+            int parameterLen = length - (startPos - endPos);
+            if (parameterLen > 0) {//have parameters
+                parseContentTypeParams(pduDataStream, map, parameterLen);
+            }
+
+            if (parameterLen < 0) {
+                Log.e(LOG_TAG, "Corrupt MMS message");
+                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
+            }
+        } else if (cur <= TEXT_MAX) {
+            contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+        } else {
+            contentType =
+                    (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes();
+        }
+
+        return contentType;
+    }
+
+    /**
+     * Parse part's headers.
+     *
+     * @param pduDataStream pdu data input stream
+     * @param part          to store the header informations of the part
+     * @param length        length of the headers
+     * @return true if parse successfully, false otherwise
+     */
+    protected boolean parsePartHeaders(ByteArrayInputStream pduDataStream,
+            PduPart part, int length) {
+        assert (null != pduDataStream);
+        assert (null != part);
+        assert (length > 0);
+
+        /**
+         * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.
+         * A name for multipart object SHALL be encoded using name-parameter
+         * for Content-Type header in WSP multipart headers.
+         * In decoding, name-parameter of Content-Type SHALL be used if available.
+         * If name-parameter of Content-Type is not available,
+         * filename parameter of Content-Disposition header SHALL be used if available.
+         * If neither name-parameter of Content-Type header nor filename parameter
+         * of Content-Disposition header is available,
+         * Content-Location header SHALL be used if available.
+         *
+         * Within SMIL part the reference to the media object parts SHALL use
+         * either Content-ID or Content-Location mechanism [RFC2557]
+         * and the corresponding WSP part headers in media object parts
+         * contain the corresponding definitions.
+         */
+        int startPos = pduDataStream.available();
+        int tempPos = 0;
+        int lastLen = length;
+        while (0 < lastLen) {
+            int header = pduDataStream.read();
+            assert (-1 != header);
+            lastLen--;
+
+            if (header > TEXT_MAX) {
+                // Number assigned headers.
+                switch (header) {
+                    case PduPart.P_CONTENT_LOCATION:
+                        /**
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-location-value = Uri-value
+                         */
+                        byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                        if (null != contentLocation) {
+                            part.setContentLocation(contentLocation);
+                        }
+
+                        tempPos = pduDataStream.available();
+                        lastLen = length - (startPos - tempPos);
+                        break;
+                    case PduPart.P_CONTENT_ID:
+                        /**
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-ID-value = Quoted-string
+                         */
+                        byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING);
+                        if (null != contentId) {
+                            part.setContentId(contentId);
+                        }
+
+                        tempPos = pduDataStream.available();
+                        lastLen = length - (startPos - tempPos);
+                        break;
+                    case PduPart.P_DEP_CONTENT_DISPOSITION:
+                    case PduPart.P_CONTENT_DISPOSITION:
+                        /*
+                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
+                         * Content-disposition-value = Value-length Disposition *(Parameter)
+                         * Disposition = Form-data | Attachment | Inline | Token-text
+                         * Form-data = <Octet 128>
+                         * Attachment = <Octet 129>
+                         * Inline = <Octet 130>
+                         *
+                         * some carrier mmsc servers do not support content_disposition
+                         * field correctly
+                        */
+                        if (mParseContentDisposition) {
+                            int len = parseValueLength(pduDataStream);
+                            pduDataStream.mark(1);
+                            int thisStartPos = pduDataStream.available();
+                            int thisEndPos = 0;
+                            int value = pduDataStream.read();
+
+                            if (value == PduPart.P_DISPOSITION_FROM_DATA) {
+                                part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
+                            } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
+                                part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
+                            } else if (value == PduPart.P_DISPOSITION_INLINE) {
+                                part.setContentDisposition(PduPart.DISPOSITION_INLINE);
+                            } else {
+                                pduDataStream.reset();
+                                /* Token-text */
+                                part.setContentDisposition(parseWapString(pduDataStream
+                                        , TYPE_TEXT_STRING));
+                            }
+
+                            /* get filename parameter and skip other parameters */
+                            thisEndPos = pduDataStream.available();
+                            if (thisStartPos - thisEndPos < len) {
+                                value = pduDataStream.read();
+                                if (value == PduPart.P_FILENAME) { //filename is text-string
+                                    part.setFilename(parseWapString(pduDataStream
+                                            , TYPE_TEXT_STRING));
+                                }
+
+                                /* skip other parameters */
+                                thisEndPos = pduDataStream.available();
+                                if (thisStartPos - thisEndPos < len) {
+                                    int last = len - (thisStartPos - thisEndPos);
+                                    byte[] temp = new byte[last];
+                                    pduDataStream.read(temp, 0, last);
+                                }
+                            }
+
+                            tempPos = pduDataStream.available();
+                            lastLen = length - (startPos - tempPos);
+                        }
+                        break;
+                    default:
+                        if (LOCAL_LOGV) {
+                            Log.v(LOG_TAG, "Not supported Part headers: " + header);
+                        }
+                        if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                            Log.e(LOG_TAG, "Corrupt Part headers");
+                            return false;
+                        }
+                        lastLen = 0;
+                        break;
+                }
+            } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) {
+                // Not assigned header.
+                byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+                byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+
+                // Check the header whether it is "Content-Transfer-Encoding".
+                if (true ==
+                        PduPart.CONTENT_TRANSFER_ENCODING
+                                .equalsIgnoreCase(new String(tempHeader))) {
+                    part.setContentTransferEncoding(tempValue);
+                }
+
+                tempPos = pduDataStream.available();
+                lastLen = length - (startPos - tempPos);
+            } else {
+                if (LOCAL_LOGV) {
+                    Log.v(LOG_TAG, "Not supported Part headers: " + header);
+                }
+                // Skip all headers of this part.
+                if (-1 == skipWapValue(pduDataStream, lastLen)) {
+                    Log.e(LOG_TAG, "Corrupt Part headers");
+                    return false;
+                }
+                lastLen = 0;
+            }
+        }
+
+        if (0 != lastLen) {
+            Log.e(LOG_TAG, "Corrupt Part headers");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check the position of a specified part.
+     *
+     * @param part the part to be checked
+     * @return part position, THE_FIRST_PART when it's the
+     * first one, THE_LAST_PART when it's the last one.
+     */
+    private static int checkPartPosition(PduPart part) {
+        assert (null != part);
+        if ((null == mTypeParam) &&
+                (null == mStartParam)) {
+            return THE_LAST_PART;
+        }
+
+        /* check part's content-id */
+        if (null != mStartParam) {
+            byte[] contentId = part.getContentId();
+            if (null != contentId) {
+                if (true == Arrays.equals(mStartParam, contentId)) {
+                    return THE_FIRST_PART;
+                }
+            }
+            // This is not the first part, so append to end (keeping the original order)
+            // Check b/19607294 for details of this change
+            return THE_LAST_PART;
+        }
+
+        /* check part's content-type */
+        if (null != mTypeParam) {
+            byte[] contentType = part.getContentType();
+            if (null != contentType) {
+                if (true == Arrays.equals(mTypeParam, contentType)) {
+                    return THE_FIRST_PART;
+                }
+            }
+        }
+
+        return THE_LAST_PART;
+    }
+
+    /**
+     * Check mandatory headers of a pdu.
+     *
+     * @param headers pdu headers
+     * @return true if the pdu has all of the mandatory headers, false otherwise.
+     */
+    protected static boolean checkMandatoryHeader(PduHeaders headers) {
+        if (null == headers) {
+            return false;
+        }
+
+        /* get message type */
+        int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
+
+        /* check Mms-Version field */
+        int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION);
+        if (0 == mmsVersion) {
+            // Every message should have Mms-Version field.
+            return false;
+        }
+
+        /* check mandatory header fields */
+        switch (messageType) {
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                // Content-Type field.
+                byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
+                if (null == srContentType) {
+                    return false;
+                }
+
+                // From field.
+                EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == srFrom) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == srTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
+                // Response-Status field.
+                int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS);
+                if (0 == scResponseStatus) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == scTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                // Content-Location field.
+                byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION);
+                if (null == niContentLocation) {
+                    return false;
+                }
+
+                // Expiry field.
+                long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY);
+                if (-1 == niExpiry) {
+                    return false;
+                }
+
+                // Message-Class field.
+                byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS);
+                if (null == niMessageClass) {
+                    return false;
+                }
+
+                // Message-Size field.
+                long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE);
+                if (-1 == niMessageSize) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == niTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                // Status field.
+                int nriStatus = headers.getOctet(PduHeaders.STATUS);
+                if (0 == nriStatus) {
+                    return false;
+                }
+
+                // Transaction-Id field.
+                byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == nriTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                // Content-Type field.
+                byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
+                if (null == rcContentType) {
+                    return false;
+                }
+
+                // Date field.
+                long rcDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == rcDate) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+                // Date field.
+                long diDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == diDate) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == diMessageId) {
+                    return false;
+                }
+
+                // Status field.
+                int diStatus = headers.getOctet(PduHeaders.STATUS);
+                if (0 == diStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == diTo) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                // Transaction-Id field.
+                byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
+                if (null == aiTransactionId) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
+                // Date field.
+                long roDate = headers.getLongInteger(PduHeaders.DATE);
+                if (-1 == roDate) {
+                    return false;
+                }
+
+                // From field.
+                EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == roFrom) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == roMessageId) {
+                    return false;
+                }
+
+                // Read-Status field.
+                int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
+                if (0 == roReadStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == roTo) {
+                    return false;
+                }
+
+                break;
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                // From field.
+                EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM);
+                if (null == rrFrom) {
+                    return false;
+                }
+
+                // Message-Id field.
+                byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
+                if (null == rrMessageId) {
+                    return false;
+                }
+
+                // Read-Status field.
+                int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
+                if (0 == rrReadStatus) {
+                    return false;
+                }
+
+                // To field.
+                EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO);
+                if (null == rrTo) {
+                    return false;
+                }
+
+                break;
+            default:
+                // Parser doesn't support this message type in this version.
+                return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/PduPart.java b/src/com/android/messaging/mmslib/pdu/PduPart.java
new file mode 100644
index 0000000..dcdb7a6
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduPart.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.net.Uri;
+import android.util.SparseArray;
+
+/**
+ * The pdu part.
+ */
+public class PduPart {
+    /**
+     * Well-Known Parameters.
+     */
+    public static final int P_Q                  = 0x80;
+    public static final int P_CHARSET            = 0x81;
+    public static final int P_LEVEL              = 0x82;
+    public static final int P_TYPE               = 0x83;
+    public static final int P_DEP_NAME           = 0x85;
+    public static final int P_DEP_FILENAME       = 0x86;
+    public static final int P_DIFFERENCES        = 0x87;
+    public static final int P_PADDING            = 0x88;
+    // This value of "TYPE" s used with Content-Type: multipart/related
+    public static final int P_CT_MR_TYPE         = 0x89;
+    public static final int P_DEP_START          = 0x8A;
+    public static final int P_DEP_START_INFO     = 0x8B;
+    public static final int P_DEP_COMMENT        = 0x8C;
+    public static final int P_DEP_DOMAIN         = 0x8D;
+    public static final int P_MAX_AGE            = 0x8E;
+    public static final int P_DEP_PATH           = 0x8F;
+    public static final int P_SECURE             = 0x90;
+    public static final int P_SEC                = 0x91;
+    public static final int P_MAC                = 0x92;
+    public static final int P_CREATION_DATE      = 0x93;
+    public static final int P_MODIFICATION_DATE  = 0x94;
+    public static final int P_READ_DATE          = 0x95;
+    public static final int P_SIZE               = 0x96;
+    public static final int P_NAME               = 0x97;
+    public static final int P_FILENAME           = 0x98;
+    public static final int P_START              = 0x99;
+    public static final int P_START_INFO         = 0x9A;
+    public static final int P_COMMENT            = 0x9B;
+    public static final int P_DOMAIN             = 0x9C;
+    public static final int P_PATH               = 0x9D;
+
+    /**
+     * Header field names.
+     */
+     public static final int P_CONTENT_TYPE       = 0x91;
+     public static final int P_CONTENT_LOCATION   = 0x8E;
+     public static final int P_CONTENT_ID         = 0xC0;
+     public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
+     public static final int P_CONTENT_DISPOSITION = 0xC5;
+    // The next header is unassigned header, use reserved header(0x48) value.
+    public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
+
+    /**
+     * Content=Transfer-Encoding string.
+     */
+    public static final String CONTENT_TRANSFER_ENCODING =
+            "Content-Transfer-Encoding";
+
+    /**
+     * Value of Content-Transfer-Encoding.
+     */
+    public static final String P_BINARY = "binary";
+    public static final String P_7BIT = "7bit";
+    public static final String P_8BIT = "8bit";
+    public static final String P_BASE64 = "base64";
+    public static final String P_QUOTED_PRINTABLE = "quoted-printable";
+
+    /**
+     * Value of disposition can be set to PduPart when the value is octet in
+     * the PDU.
+     * "from-data" instead of Form-data<Octet 128>.
+     * "attachment" instead of Attachment<Octet 129>.
+     * "inline" instead of Inline<Octet 130>.
+     */
+    static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
+    static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
+    static final byte[] DISPOSITION_INLINE = "inline".getBytes();
+
+    /**
+     * Content-Disposition value.
+     */
+    public static final int P_DISPOSITION_FROM_DATA = 0x80;
+    public static final int P_DISPOSITION_ATTACHMENT = 0x81;
+    public static final int P_DISPOSITION_INLINE = 0x82;
+
+    /**
+     * Header of part.
+     */
+    private SparseArray<Object> mPartHeader = null;
+
+    /**
+     * Data uri.
+     */
+    private Uri mUri = null;
+
+    /**
+     * Part data.
+     */
+    private byte[] mPartData = null;
+
+    private static final String TAG = "PduPart";
+
+    /**
+     * Empty Constructor.
+     */
+    public PduPart() {
+        mPartHeader = new SparseArray<Object>();
+    }
+
+    /**
+     * Set part data. The data are stored as byte array.
+     *
+     * @param data the data
+     */
+    public void setData(final byte[] data) {
+        mPartData = data;
+    }
+
+    /**
+     * @return The part data or null if the data wasn't set or
+     * the data is stored as Uri.
+     * @see #getDataUri
+     */
+    public byte[] getData() {
+        return mPartData;
+    }
+
+    /**
+     * Set data uri. The data are stored as Uri.
+     *
+     * @param uri the uri
+     */
+    public void setDataUri(final Uri uri) {
+        mUri = uri;
+    }
+
+    /**
+     * @return The Uri of the part data or null if the data wasn't set or
+     * the data is stored as byte array.
+     * @see #getData
+     */
+    public Uri getDataUri() {
+        return mUri;
+    }
+
+    /**
+     * Set Content-id value
+     *
+     * @param contentId the content-id value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentId(final byte[] contentId) {
+        if ((contentId == null) || (contentId.length == 0)) {
+            throw new IllegalArgumentException(
+                    "Content-Id may not be null or empty.");
+        }
+
+        if ((contentId.length > 1)
+                && ((char) contentId[0] == '<')
+                && ((char) contentId[contentId.length - 1] == '>')) {
+            mPartHeader.put(P_CONTENT_ID, contentId);
+            return;
+        }
+
+        // Insert beginning '<' and trailing '>' for Content-Id.
+        final byte[] buffer = new byte[contentId.length + 2];
+        buffer[0] = (byte) (0xff & '<');
+        buffer[buffer.length - 1] = (byte) (0xff & '>');
+        System.arraycopy(contentId, 0, buffer, 1, contentId.length);
+        mPartHeader.put(P_CONTENT_ID, buffer);
+    }
+
+    /**
+     * Get Content-id value.
+     *
+     * @return the value
+     */
+    public byte[] getContentId() {
+        return (byte[]) mPartHeader.get(P_CONTENT_ID);
+    }
+
+    /**
+     * Set Char-set value.
+     *
+     * @param charset the value
+     */
+    public void setCharset(final int charset) {
+        mPartHeader.put(P_CHARSET, charset);
+    }
+
+    /**
+     * Get Char-set value
+     *
+     * @return the charset value. Return 0 if charset was not set.
+     */
+    public int getCharset() {
+        final Integer charset = (Integer) mPartHeader.get(P_CHARSET);
+        if (charset == null) {
+            return 0;
+        } else {
+            return charset.intValue();
+        }
+    }
+
+    /**
+     * Set Content-Location value.
+     *
+     * @param contentLocation the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentLocation(final byte[] contentLocation) {
+        if (contentLocation == null) {
+            throw new NullPointerException("null content-location");
+        }
+
+        mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
+    }
+
+    /**
+     * Get Content-Location value.
+     *
+     * @return the value
+     * return PduPart.disposition[0] instead of <Octet 128> (Form-data).
+     * return PduPart.disposition[1] instead of <Octet 129> (Attachment).
+     * return PduPart.disposition[2] instead of <Octet 130> (Inline).
+     */
+    public byte[] getContentLocation() {
+        return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
+    }
+
+    /**
+     * Set Content-Disposition value.
+     * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
+     * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
+     * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
+     *
+     * @param contentDisposition the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentDisposition(final byte[] contentDisposition) {
+        if (contentDisposition == null) {
+            throw new NullPointerException("null content-disposition");
+        }
+
+        mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
+    }
+
+    /**
+     * Get Content-Disposition value.
+     *
+     * @return the value
+     */
+    public byte[] getContentDisposition() {
+        return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
+    }
+
+    /**
+     * Set Content-Type value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentType(final byte[] contentType) {
+        if (contentType == null) {
+            throw new NullPointerException("null content-type");
+        }
+
+        mPartHeader.put(P_CONTENT_TYPE, contentType);
+    }
+
+    /**
+     * Get Content-Type value of part.
+     *
+     * @return the value
+     */
+    public byte[] getContentType() {
+        return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
+    }
+
+    /**
+     * Set Content-Transfer-Encoding value
+     *
+     * @param contentId the content-id value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentTransferEncoding(final byte[] contentTransferEncoding) {
+        if (contentTransferEncoding == null) {
+            throw new NullPointerException("null content-transfer-encoding");
+        }
+
+        mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
+    }
+
+    /**
+     * Get Content-Transfer-Encoding value.
+     *
+     * @return the value
+     */
+    public byte[] getContentTransferEncoding() {
+        return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
+    }
+
+    /**
+     * Set Content-type parameter: name.
+     *
+     * @param name the name value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setName(final byte[] name) {
+        if (null == name) {
+            throw new NullPointerException("null content-id");
+        }
+
+        mPartHeader.put(P_NAME, name);
+    }
+
+    /**
+     * Get content-type parameter: name.
+     *
+     * @return the name
+     */
+    public byte[] getName() {
+        return (byte[]) mPartHeader.get(P_NAME);
+    }
+
+    /**
+     * Get Content-disposition parameter: filename
+     *
+     * @param fileName the filename value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFilename(final byte[] fileName) {
+        if (null == fileName) {
+            throw new NullPointerException("null content-id");
+        }
+
+        mPartHeader.put(P_FILENAME, fileName);
+    }
+
+    /**
+     * Set Content-disposition parameter: filename
+     *
+     * @return the filename
+     */
+    public byte[] getFilename() {
+        return (byte[]) mPartHeader.get(P_FILENAME);
+    }
+
+    public String generateLocation() {
+        // Assumption: At least one of the content-location / name / filename
+        // or content-id should be set. This is guaranteed by the PduParser
+        // for incoming messages and by MM composer for outgoing messages.
+        byte[] location = (byte[]) mPartHeader.get(P_NAME);
+        if (null == location) {
+            location = (byte[]) mPartHeader.get(P_FILENAME);
+
+            if (null == location) {
+                location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
+            }
+        }
+
+        if (null == location) {
+            final byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
+            return "cid:" + new String(contentId);
+        } else {
+            return new String(location);
+        }
+    }
+}
+
diff --git a/src/com/android/messaging/mmslib/pdu/PduPersister.java b/src/com/android/messaging/mmslib/pdu/PduPersister.java
new file mode 100644
index 0000000..436867a
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/PduPersister.java
@@ -0,0 +1,1692 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Mms.Addr;
+import android.provider.Telephony.Mms.Part;
+import android.provider.Telephony.MmsSms;
+import android.provider.Telephony.MmsSms.PendingMessages;
+import androidx.collection.ArrayMap;
+import androidx.collection.SimpleArrayMap;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+import com.android.messaging.mmslib.MmsException;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.mmslib.util.DownloadDrmHelper;
+import com.android.messaging.mmslib.util.DrmConvertSession;
+import com.android.messaging.mmslib.util.PduCache;
+import com.android.messaging.mmslib.util.PduCacheEntry;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UriUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * This class is the high-level manager of PDU storage.
+ */
+public class PduPersister {
+    private static final String TAG = "PduPersister";
+    private static final boolean LOCAL_LOGV = false;
+
+    /**
+     * The uri of temporary drm objects.
+     */
+    public static final String TEMPORARY_DRM_OBJECT_URI =
+            "content://mms/" + Long.MAX_VALUE + "/part";
+
+    /**
+     * Indicate that we transiently failed to process a MM.
+     */
+    public static final int PROC_STATUS_TRANSIENT_FAILURE = 1;
+
+    /**
+     * Indicate that we permanently failed to process a MM.
+     */
+    public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2;
+
+    /**
+     * Indicate that we have successfully processed a MM.
+     */
+    public static final int PROC_STATUS_COMPLETED = 3;
+
+    public static final String BEGIN_VCARD = "BEGIN:VCARD";
+
+    private static PduPersister sPersister;
+
+    private static final PduCache PDU_CACHE_INSTANCE;
+
+    private static final int[] ADDRESS_FIELDS = new int[]{
+            PduHeaders.BCC,
+            PduHeaders.CC,
+            PduHeaders.FROM,
+            PduHeaders.TO
+    };
+
+    public static final String[] PDU_PROJECTION = new String[]{
+            Mms._ID,
+            Mms.MESSAGE_BOX,
+            Mms.THREAD_ID,
+            Mms.RETRIEVE_TEXT,
+            Mms.SUBJECT,
+            Mms.CONTENT_LOCATION,
+            Mms.CONTENT_TYPE,
+            Mms.MESSAGE_CLASS,
+            Mms.MESSAGE_ID,
+            Mms.RESPONSE_TEXT,
+            Mms.TRANSACTION_ID,
+            Mms.CONTENT_CLASS,
+            Mms.DELIVERY_REPORT,
+            Mms.MESSAGE_TYPE,
+            Mms.MMS_VERSION,
+            Mms.PRIORITY,
+            Mms.READ_REPORT,
+            Mms.READ_STATUS,
+            Mms.REPORT_ALLOWED,
+            Mms.RETRIEVE_STATUS,
+            Mms.STATUS,
+            Mms.DATE,
+            Mms.DELIVERY_TIME,
+            Mms.EXPIRY,
+            Mms.MESSAGE_SIZE,
+            Mms.SUBJECT_CHARSET,
+            Mms.RETRIEVE_TEXT_CHARSET,
+            Mms.READ,
+            Mms.SEEN,
+    };
+
+    public static final int PDU_COLUMN_ID                    = 0;
+    public static final int PDU_COLUMN_MESSAGE_BOX           = 1;
+    public static final int PDU_COLUMN_THREAD_ID             = 2;
+    public static final int PDU_COLUMN_RETRIEVE_TEXT         = 3;
+    public static final int PDU_COLUMN_SUBJECT               = 4;
+    public static final int PDU_COLUMN_CONTENT_LOCATION      = 5;
+    public static final int PDU_COLUMN_CONTENT_TYPE          = 6;
+    public static final int PDU_COLUMN_MESSAGE_CLASS         = 7;
+    public static final int PDU_COLUMN_MESSAGE_ID            = 8;
+    public static final int PDU_COLUMN_RESPONSE_TEXT         = 9;
+    public static final int PDU_COLUMN_TRANSACTION_ID        = 10;
+    public static final int PDU_COLUMN_CONTENT_CLASS         = 11;
+    public static final int PDU_COLUMN_DELIVERY_REPORT       = 12;
+    public static final int PDU_COLUMN_MESSAGE_TYPE          = 13;
+    public static final int PDU_COLUMN_MMS_VERSION           = 14;
+    public static final int PDU_COLUMN_PRIORITY              = 15;
+    public static final int PDU_COLUMN_READ_REPORT           = 16;
+    public static final int PDU_COLUMN_READ_STATUS           = 17;
+    public static final int PDU_COLUMN_REPORT_ALLOWED        = 18;
+    public static final int PDU_COLUMN_RETRIEVE_STATUS       = 19;
+    public static final int PDU_COLUMN_STATUS                = 20;
+    public static final int PDU_COLUMN_DATE                  = 21;
+    public static final int PDU_COLUMN_DELIVERY_TIME         = 22;
+    public static final int PDU_COLUMN_EXPIRY                = 23;
+    public static final int PDU_COLUMN_MESSAGE_SIZE          = 24;
+    public static final int PDU_COLUMN_SUBJECT_CHARSET       = 25;
+    public static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26;
+    public static final int PDU_COLUMN_READ                  = 27;
+    public static final int PDU_COLUMN_SEEN                  = 28;
+
+    private static final String[] PART_PROJECTION = new String[] {
+            Part._ID,
+            Part.CHARSET,
+            Part.CONTENT_DISPOSITION,
+            Part.CONTENT_ID,
+            Part.CONTENT_LOCATION,
+            Part.CONTENT_TYPE,
+            Part.FILENAME,
+            Part.NAME,
+            Part.TEXT
+    };
+
+    private static final int PART_COLUMN_ID                  = 0;
+    private static final int PART_COLUMN_CHARSET             = 1;
+    private static final int PART_COLUMN_CONTENT_DISPOSITION = 2;
+    private static final int PART_COLUMN_CONTENT_ID          = 3;
+    private static final int PART_COLUMN_CONTENT_LOCATION    = 4;
+    private static final int PART_COLUMN_CONTENT_TYPE        = 5;
+    private static final int PART_COLUMN_FILENAME            = 6;
+    private static final int PART_COLUMN_NAME                = 7;
+    private static final int PART_COLUMN_TEXT                = 8;
+
+    private static final SimpleArrayMap<Uri, Integer> MESSAGE_BOX_MAP;
+
+    // These map are used for convenience in persist() and load().
+    private static final SparseIntArray CHARSET_COLUMN_INDEX_MAP;
+
+    private static final SparseIntArray ENCODED_STRING_COLUMN_INDEX_MAP;
+
+    private static final SparseIntArray TEXT_STRING_COLUMN_INDEX_MAP;
+
+    private static final SparseIntArray OCTET_COLUMN_INDEX_MAP;
+
+    private static final SparseIntArray LONG_COLUMN_INDEX_MAP;
+
+    private static final SparseArray<String> CHARSET_COLUMN_NAME_MAP;
+
+    private static final SparseArray<String> ENCODED_STRING_COLUMN_NAME_MAP;
+
+    private static final SparseArray<String> TEXT_STRING_COLUMN_NAME_MAP;
+
+    private static final SparseArray<String> OCTET_COLUMN_NAME_MAP;
+
+    private static final SparseArray<String> LONG_COLUMN_NAME_MAP;
+
+    static {
+        MESSAGE_BOX_MAP = new SimpleArrayMap<Uri, Integer>();
+        MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI, Mms.MESSAGE_BOX_INBOX);
+        MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI, Mms.MESSAGE_BOX_SENT);
+        MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI, Mms.MESSAGE_BOX_DRAFTS);
+        MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX);
+
+        CHARSET_COLUMN_INDEX_MAP = new SparseIntArray();
+        CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET);
+        CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET);
+
+        CHARSET_COLUMN_NAME_MAP = new SparseArray<String>();
+        CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET);
+        CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET);
+
+        // Encoded string field code -> column index/name map.
+        ENCODED_STRING_COLUMN_INDEX_MAP = new SparseIntArray();
+        ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT);
+        ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT);
+
+        ENCODED_STRING_COLUMN_NAME_MAP = new SparseArray<String>();
+        ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT);
+        ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT);
+
+        // Text string field code -> column index/name map.
+        TEXT_STRING_COLUMN_INDEX_MAP = new SparseIntArray();
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION);
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE);
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS);
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID);
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT);
+        TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID);
+
+        TEXT_STRING_COLUMN_NAME_MAP = new SparseArray<String>();
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION);
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE);
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS);
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID);
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT);
+        TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID);
+
+        // Octet field code -> column index/name map.
+        OCTET_COLUMN_INDEX_MAP = new SparseIntArray();
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS);
+        OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS);
+
+        OCTET_COLUMN_NAME_MAP = new SparseArray<String>();
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS);
+        OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS);
+
+        // Long field code -> column index/name map.
+        LONG_COLUMN_INDEX_MAP = new SparseIntArray();
+        LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE);
+        LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME);
+        LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY);
+        LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE);
+
+        LONG_COLUMN_NAME_MAP = new SparseArray<String>();
+        LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE);
+        LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME);
+        LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY);
+        LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE);
+
+        PDU_CACHE_INSTANCE = PduCache.getInstance();
+    }
+
+    private final Context mContext;
+
+    private final ContentResolver mContentResolver;
+
+    private PduPersister(final Context context) {
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+    }
+
+    /** Get(or create if not exist) an instance of PduPersister */
+    public static PduPersister getPduPersister(final Context context) {
+        if ((sPersister == null) || !context.equals(sPersister.mContext)) {
+            sPersister = new PduPersister(context);
+        }
+        if (LOCAL_LOGV) {
+            LogUtil.v(TAG, "PduPersister getPduPersister");
+        }
+
+        return sPersister;
+    }
+
+    private void setEncodedStringValueToHeaders(
+            final Cursor c, final int columnIndex,
+            final PduHeaders headers, final int mapColumn) {
+        final String s = c.getString(columnIndex);
+        if ((s != null) && (s.length() > 0)) {
+            final int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn);
+            final int charset = c.getInt(charsetColumnIndex);
+            final EncodedStringValue value = new EncodedStringValue(
+                    charset, getBytes(s));
+            headers.setEncodedStringValue(value, mapColumn);
+        }
+    }
+
+    private void setTextStringToHeaders(
+            final Cursor c, final int columnIndex,
+            final PduHeaders headers, final int mapColumn) {
+        final String s = c.getString(columnIndex);
+        if (s != null) {
+            headers.setTextString(getBytes(s), mapColumn);
+        }
+    }
+
+    private void setOctetToHeaders(
+            final Cursor c, final int columnIndex,
+            final PduHeaders headers, final int mapColumn) throws InvalidHeaderValueException {
+        if (!c.isNull(columnIndex)) {
+            final int b = c.getInt(columnIndex);
+            headers.setOctet(b, mapColumn);
+        }
+    }
+
+    private void setLongToHeaders(
+            final Cursor c, final int columnIndex,
+            final PduHeaders headers, final int mapColumn) {
+        if (!c.isNull(columnIndex)) {
+            final long l = c.getLong(columnIndex);
+            headers.setLongInteger(l, mapColumn);
+        }
+    }
+
+    private Integer getIntegerFromPartColumn(final Cursor c, final int columnIndex) {
+        if (!c.isNull(columnIndex)) {
+            return c.getInt(columnIndex);
+        }
+        return null;
+    }
+
+    private byte[] getByteArrayFromPartColumn(final Cursor c, final int columnIndex) {
+        if (!c.isNull(columnIndex)) {
+            return getBytes(c.getString(columnIndex));
+        }
+        return null;
+    }
+
+    private PduPart[] loadParts(final long msgId) throws MmsException {
+        final Cursor c = SqliteWrapper.query(mContext, mContentResolver,
+                Uri.parse("content://mms/" + msgId + "/part"),
+                PART_PROJECTION, null, null, null);
+
+        PduPart[] parts = null;
+
+        try {
+            if ((c == null) || (c.getCount() == 0)) {
+                if (LOCAL_LOGV) {
+                    LogUtil.v(TAG, "loadParts(" + msgId + "): no part to load.");
+                }
+                return null;
+            }
+
+            final int partCount = c.getCount();
+            int partIdx = 0;
+            parts = new PduPart[partCount];
+            while (c.moveToNext()) {
+                final PduPart part = new PduPart();
+                final Integer charset = getIntegerFromPartColumn(
+                        c, PART_COLUMN_CHARSET);
+                if (charset != null) {
+                    part.setCharset(charset);
+                }
+
+                final byte[] contentDisposition = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_CONTENT_DISPOSITION);
+                if (contentDisposition != null) {
+                    part.setContentDisposition(contentDisposition);
+                }
+
+                final byte[] contentId = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_CONTENT_ID);
+                if (contentId != null) {
+                    part.setContentId(contentId);
+                }
+
+                final byte[] contentLocation = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_CONTENT_LOCATION);
+                if (contentLocation != null) {
+                    part.setContentLocation(contentLocation);
+                }
+
+                final byte[] contentType = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_CONTENT_TYPE);
+                if (contentType != null) {
+                    part.setContentType(contentType);
+                } else {
+                    throw new MmsException("Content-Type must be set.");
+                }
+
+                final byte[] fileName = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_FILENAME);
+                if (fileName != null) {
+                    part.setFilename(fileName);
+                }
+
+                final byte[] name = getByteArrayFromPartColumn(
+                        c, PART_COLUMN_NAME);
+                if (name != null) {
+                    part.setName(name);
+                }
+
+                // Construct a Uri for this part.
+                final long partId = c.getLong(PART_COLUMN_ID);
+                final Uri partURI = Uri.parse("content://mms/part/" + partId);
+                part.setDataUri(partURI);
+
+                // For images/audio/video, we won't keep their data in Part
+                // because their renderer accept Uri as source.
+                final String type = toIsoString(contentType);
+                if (!ContentType.isImageType(type)
+                        && !ContentType.isAudioType(type)
+                        && !ContentType.isVideoType(type)) {
+                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    InputStream is = null;
+
+                    // Store simple string values directly in the database instead of an
+                    // external file.  This makes the text searchable and retrieval slightly
+                    // faster.
+                    if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type)
+                            || ContentType.TEXT_HTML.equals(type)) {
+                        final String text = c.getString(PART_COLUMN_TEXT);
+                        final byte[] blob = new EncodedStringValue(
+                                charset != null ? charset : CharacterSets.DEFAULT_CHARSET,
+                                text != null ? text : "")
+                                .getTextString();
+                        baos.write(blob, 0, blob.length);
+                    } else {
+
+                        try {
+                            is = mContentResolver.openInputStream(partURI);
+
+                            final byte[] buffer = new byte[256];
+                            int len = is.read(buffer);
+                            while (len >= 0) {
+                                baos.write(buffer, 0, len);
+                                len = is.read(buffer);
+                            }
+                        } catch (final IOException e) {
+                            Log.e(TAG, "Failed to load part data", e);
+                            c.close();
+                            throw new MmsException(e);
+                        } finally {
+                            if (is != null) {
+                                try {
+                                    is.close();
+                                } catch (final IOException e) {
+                                    Log.e(TAG, "Failed to close stream", e);
+                                } // Ignore
+                            }
+                        }
+                    }
+                    part.setData(baos.toByteArray());
+                }
+                parts[partIdx++] = part;
+            }
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+
+        return parts;
+    }
+
+    private void loadAddress(final long msgId, final PduHeaders headers) {
+        final Cursor c = SqliteWrapper.query(mContext, mContentResolver,
+                Uri.parse("content://mms/" + msgId + "/addr"),
+                new String[]{Addr.ADDRESS, Addr.CHARSET, Addr.TYPE},
+                null, null, null);
+
+        if (c != null) {
+            try {
+                while (c.moveToNext()) {
+                    final String addr = c.getString(0);
+                    if (!TextUtils.isEmpty(addr)) {
+                        final int addrType = c.getInt(2);
+                        switch (addrType) {
+                            case PduHeaders.FROM:
+                                headers.setEncodedStringValue(
+                                        new EncodedStringValue(c.getInt(1), getBytes(addr)),
+                                        addrType);
+                                break;
+                            case PduHeaders.TO:
+                            case PduHeaders.CC:
+                            case PduHeaders.BCC:
+                                headers.appendEncodedStringValue(
+                                        new EncodedStringValue(c.getInt(1), getBytes(addr)),
+                                        addrType);
+                                break;
+                            default:
+                                Log.e(TAG, "Unknown address type: " + addrType);
+                                break;
+                        }
+                    }
+                }
+            } finally {
+                c.close();
+            }
+        }
+    }
+
+    /**
+     * Load a PDU from a given cursor
+     *
+     * @param c The cursor
+     * @return A parsed PDU from the database row
+     */
+    public GenericPdu load(final Cursor c) throws MmsException {
+        final PduHeaders headers = new PduHeaders();
+        final long msgId = c.getLong(PDU_COLUMN_ID);
+        // Fill in the headers from the PDU columns
+        loadHeadersFromCursor(c, headers);
+        // Load address information of the MM.
+        loadAddress(msgId, headers);
+        // Load parts for the PDU body
+        final int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
+        final PduBody body = loadBody(msgId, msgType);
+        return createPdu(msgType, headers, body);
+    }
+
+    /**
+     * Load a PDU from storage by given Uri.
+     *
+     * @param uri            The Uri of the PDU to be loaded.
+     * @return A generic PDU object, it may be cast to dedicated PDU.
+     * @throws MmsException Failed to load some fields of a PDU.
+     */
+    public GenericPdu load(final Uri uri) throws MmsException {
+        GenericPdu pdu = null;
+        PduCacheEntry cacheEntry = null;
+        int msgBox = 0;
+        final long threadId = -1;
+        try {
+            synchronized (PDU_CACHE_INSTANCE) {
+                if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                    if (LOCAL_LOGV) {
+                        LogUtil.v(TAG, "load: " + uri + " blocked by isUpdating()");
+                    }
+                    try {
+                        PDU_CACHE_INSTANCE.wait();
+                    } catch (final InterruptedException e) {
+                        Log.e(TAG, "load: ", e);
+                    }
+                }
+
+                // Check if the pdu is already loaded
+                cacheEntry = PDU_CACHE_INSTANCE.get(uri);
+                if (cacheEntry != null) {
+                    return cacheEntry.getPdu();
+                }
+
+                // Tell the cache to indicate to other callers that this item
+                // is currently being updated.
+                PDU_CACHE_INSTANCE.setUpdating(uri, true);
+            }
+
+            final Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,
+                    PDU_PROJECTION, null, null, null);
+            final PduHeaders headers = new PduHeaders();
+            final long msgId = ContentUris.parseId(uri);
+
+            try {
+                if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) {
+                    return null;  // MMS not found
+                }
+
+                msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX);
+                //threadId = c.getLong(PDU_COLUMN_THREAD_ID);
+                loadHeadersFromCursor(c, headers);
+            } finally {
+                if (c != null) {
+                    c.close();
+                }
+            }
+
+            // Check whether 'msgId' has been assigned a valid value.
+            if (msgId == -1L) {
+                throw new MmsException("Error! ID of the message: -1.");
+            }
+
+            // Load address information of the MM.
+            loadAddress(msgId, headers);
+
+            final int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
+            final PduBody body = loadBody(msgId, msgType);
+            pdu = createPdu(msgType, headers, body);
+        } finally {
+            synchronized (PDU_CACHE_INSTANCE) {
+                if (pdu != null) {
+                    Assert.isNull(PDU_CACHE_INSTANCE.get(uri), "Pdu exists for " + uri);
+                    // Update the cache entry with the real info
+                    cacheEntry = new PduCacheEntry(pdu, msgBox, threadId);
+                    PDU_CACHE_INSTANCE.put(uri, cacheEntry);
+                }
+                PDU_CACHE_INSTANCE.setUpdating(uri, false);
+                PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead
+            }
+        }
+        return pdu;
+    }
+
+    private void loadHeadersFromCursor(final Cursor c, final PduHeaders headers)
+            throws InvalidHeaderValueException {
+        for (int i = ENCODED_STRING_COLUMN_INDEX_MAP.size(); --i >= 0; ) {
+            setEncodedStringValueToHeaders(
+                    c, ENCODED_STRING_COLUMN_INDEX_MAP.valueAt(i), headers,
+                    ENCODED_STRING_COLUMN_INDEX_MAP.keyAt(i));
+        }
+        for (int i = TEXT_STRING_COLUMN_INDEX_MAP.size(); --i >= 0; ) {
+            setTextStringToHeaders(
+                    c, TEXT_STRING_COLUMN_INDEX_MAP.valueAt(i), headers,
+                    TEXT_STRING_COLUMN_INDEX_MAP.keyAt(i));
+        }
+        for (int i = OCTET_COLUMN_INDEX_MAP.size(); --i >= 0; ) {
+            setOctetToHeaders(
+                    c, OCTET_COLUMN_INDEX_MAP.valueAt(i), headers,
+                    OCTET_COLUMN_INDEX_MAP.keyAt(i));
+        }
+        for (int i = LONG_COLUMN_INDEX_MAP.size(); --i >= 0; ) {
+            setLongToHeaders(
+                    c, LONG_COLUMN_INDEX_MAP.valueAt(i), headers,
+                    LONG_COLUMN_INDEX_MAP.keyAt(i));
+        }
+    }
+
+    private GenericPdu createPdu(final int msgType, final PduHeaders headers, final PduBody body)
+            throws MmsException {
+        switch (msgType) {
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                return new NotificationInd(headers);
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+                return new DeliveryInd(headers);
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
+                return new ReadOrigInd(headers);
+            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                return new RetrieveConf(headers, body);
+            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                return new SendReq(headers, body);
+            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
+                return new AcknowledgeInd(headers);
+            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
+                return new NotifyRespInd(headers);
+            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
+                return new ReadRecInd(headers);
+            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
+            case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
+            case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
+            case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
+            case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
+            case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
+            case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
+            case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
+            case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
+            case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
+            case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
+            case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
+            case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
+            case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
+            case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
+            case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
+                throw new MmsException(
+                        "Unsupported PDU type: " + Integer.toHexString(msgType));
+
+            default:
+                throw new MmsException(
+                        "Unrecognized PDU type: " + Integer.toHexString(msgType));
+        }
+    }
+
+    private PduBody loadBody(final long msgId, final int msgType) throws MmsException {
+        final PduBody body = new PduBody();
+
+        // For PDU which type is M_retrieve.conf or Send.req, we should
+        // load multiparts and put them into the body of the PDU.
+        if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
+                || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
+            final PduPart[] parts = loadParts(msgId);
+            if (parts != null) {
+                final int partsNum = parts.length;
+                for (int i = 0; i < partsNum; i++) {
+                    body.addPart(parts[i]);
+                }
+            }
+        }
+
+        return body;
+    }
+
+    private void persistAddress(
+            final long msgId, final int type, final EncodedStringValue[] array) {
+        final ContentValues values = new ContentValues(3);
+
+        for (final EncodedStringValue addr : array) {
+            values.clear(); // Clear all values first.
+            values.put(Addr.ADDRESS, toIsoString(addr.getTextString()));
+            values.put(Addr.CHARSET, addr.getCharacterSet());
+            values.put(Addr.TYPE, type);
+
+            final Uri uri = Uri.parse("content://mms/" + msgId + "/addr");
+            SqliteWrapper.insert(mContext, mContentResolver, uri, values);
+        }
+    }
+
+    private static String getPartContentType(final PduPart part) {
+        return part.getContentType() == null ? null : toIsoString(part.getContentType());
+    }
+
+    private static void getValues(final PduPart part, final ContentValues values) {
+        byte[] bytes = part.getFilename();
+        if (bytes != null) {
+            values.put(Part.FILENAME, new String(bytes));
+        }
+
+        bytes = part.getName();
+        if (bytes != null) {
+            values.put(Part.NAME, new String(bytes));
+        }
+
+        bytes = part.getContentDisposition();
+        if (bytes != null) {
+            values.put(Part.CONTENT_DISPOSITION, toIsoString(bytes));
+        }
+
+        bytes = part.getContentId();
+        if (bytes != null) {
+            values.put(Part.CONTENT_ID, toIsoString(bytes));
+        }
+
+        bytes = part.getContentLocation();
+        if (bytes != null) {
+            values.put(Part.CONTENT_LOCATION, toIsoString(bytes));
+        }
+    }
+
+    public Uri persistPart(final PduPart part, final long msgId,
+            final Map<Uri, InputStream> preOpenedFiles) throws MmsException {
+        final Uri uri = Uri.parse("content://mms/" + msgId + "/part");
+        final ContentValues values = new ContentValues(8);
+
+        final int charset = part.getCharset();
+        if (charset != 0) {
+            values.put(Part.CHARSET, charset);
+        }
+
+        String contentType = getPartContentType(part);
+        final byte[] data = part.getData();
+
+        if (LOCAL_LOGV) {
+            LogUtil.v(TAG, "PduPersister.persistPart part: " + uri + " contentType: " +
+                    contentType);
+        }
+
+        if (contentType != null) {
+            // There is no "image/jpg" in Android (and it's an invalid mimetype).
+            // Change it to "image/jpeg"
+            if (ContentType.IMAGE_JPG.equals(contentType)) {
+                contentType = ContentType.IMAGE_JPEG;
+            }
+
+            // On somes phones, a vcard comes in as text/plain instead of text/v-card.
+            // Fix it if necessary.
+            if (ContentType.TEXT_PLAIN.equals(contentType) && data != null) {
+                // There might be a more efficient way to just check the beginning of the string
+                // without encoding the whole thing, but we're concerned that with various
+                // characters sets, just comparing the byte data to BEGIN_VCARD would not be
+                // reliable.
+                final String encodedDataString = new EncodedStringValue(charset, data).getString();
+                if (encodedDataString != null && encodedDataString.startsWith(BEGIN_VCARD)) {
+                    contentType = ContentType.TEXT_VCARD;
+                    part.setContentType(contentType.getBytes());
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "PduPersister.persistPart part: " + uri + " contentType: " +
+                                contentType + " changing to vcard");
+                    }
+                }
+            }
+
+            values.put(Part.CONTENT_TYPE, contentType);
+            // To ensure the SMIL part is always the first part.
+            if (ContentType.APP_SMIL.equals(contentType)) {
+                values.put(Part.SEQ, -1);
+            }
+        } else {
+            throw new MmsException("MIME type of the part must be set.");
+        }
+
+        getValues(part, values);
+
+        Uri res = null;
+
+        try {
+            res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
+        } catch (IllegalStateException e) {
+            // Currently the MMS provider throws an IllegalStateException when it's out of space
+            LogUtil.e(TAG, "SqliteWrapper.insert threw: ", e);
+        }
+
+        if (res == null) {
+            throw new MmsException("Failed to persist part, return null.");
+        }
+
+        persistData(part, res, contentType, preOpenedFiles);
+        // After successfully store the data, we should update
+        // the dataUri of the part.
+        part.setDataUri(res);
+
+        return res;
+    }
+
+    /**
+     * Save data of the part into storage. The source data may be given
+     * by a byte[] or a Uri. If it's a byte[], directly save it
+     * into storage, otherwise load source data from the dataUri and then
+     * save it. If the data is an image, we may scale down it according
+     * to user preference.
+     *
+     * @param part           The PDU part which contains data to be saved.
+     * @param uri            The URI of the part.
+     * @param contentType    The MIME type of the part.
+     * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
+     * @throws MmsException Cannot find source data or error occurred
+     *                      while saving the data.
+     */
+    private void persistData(final PduPart part, final Uri uri,
+            final String contentType, final Map<Uri, InputStream> preOpenedFiles)
+            throws MmsException {
+        OutputStream os = null;
+        InputStream is = null;
+        DrmConvertSession drmConvertSession = null;
+        Uri dataUri = null;
+        String path = null;
+
+        try {
+            final byte[] data = part.getData();
+            final int charset = part.getCharset();
+            if (ContentType.TEXT_PLAIN.equals(contentType)
+                    || ContentType.APP_SMIL.equals(contentType)
+                    || ContentType.TEXT_HTML.equals(contentType)) {
+                // Some phone could send MMS with a text part having empty data
+                // Let's just skip those parts.
+                // EncodedStringValue() throws NPE if data is empty
+                if (data != null) {
+                    final ContentValues cv = new ContentValues();
+                    cv.put(Mms.Part.TEXT, new EncodedStringValue(charset, data).getString());
+                    if (mContentResolver.update(uri, cv, null, null) != 1) {
+                        throw new MmsException("unable to update " + uri.toString());
+                    }
+                }
+            } else {
+                final boolean isDrm = DownloadDrmHelper.isDrmConvertNeeded(contentType);
+                if (isDrm) {
+                    if (uri != null) {
+                        try {
+                            path = convertUriToPath(mContext, uri);
+                            if (LOCAL_LOGV) {
+                                LogUtil.v(TAG, "drm uri: " + uri + " path: " + path);
+                            }
+                            final File f = new File(path);
+                            final long len = f.length();
+                            if (LOCAL_LOGV) {
+                                LogUtil.v(TAG, "drm path: " + path + " len: " + len);
+                            }
+                            if (len > 0) {
+                                // we're not going to re-persist and re-encrypt an already
+                                // converted drm file
+                                return;
+                            }
+                        } catch (final Exception e) {
+                            Log.e(TAG, "Can't get file info for: " + part.getDataUri(), e);
+                        }
+                    }
+                    // We haven't converted the file yet, start the conversion
+                    drmConvertSession = DrmConvertSession.open(mContext, contentType);
+                    if (drmConvertSession == null) {
+                        throw new MmsException("Mimetype " + contentType +
+                                " can not be converted.");
+                    }
+                }
+                // uri can look like:
+                // content://mms/part/98
+                os = mContentResolver.openOutputStream(uri);
+                if (os == null) {
+                    throw new MmsException("Failed to create output stream on " + uri);
+                }
+                if (data == null) {
+                    dataUri = part.getDataUri();
+                    if ((dataUri == null) || (dataUri.equals(uri))) {
+                        Log.w(TAG, "Can't find data for this part.");
+                        return;
+                    }
+                    // dataUri can look like:
+                    // content://com.google.android.gallery3d.provider/picasa/item/5720646660183715
+                    if (preOpenedFiles != null && preOpenedFiles.containsKey(dataUri)) {
+                        is = preOpenedFiles.get(dataUri);
+                    }
+                    if (is == null) {
+                        is = mContentResolver.openInputStream(dataUri);
+                    }
+                    if (is == null) {
+                        throw new MmsException("Failed to create input stream on " + dataUri);
+                    }
+                    if (LOCAL_LOGV) {
+                        LogUtil.v(TAG, "Saving data to: " + uri);
+                    }
+
+                    final byte[] buffer = new byte[8192];
+                    for (int len = 0; (len = is.read(buffer)) != -1; ) {
+                        if (!isDrm) {
+                            os.write(buffer, 0, len);
+                        } else {
+                            final byte[] convertedData = drmConvertSession.convert(buffer, len);
+                            if (convertedData != null) {
+                                os.write(convertedData, 0, convertedData.length);
+                            } else {
+                                throw new MmsException("Error converting drm data.");
+                            }
+                        }
+                    }
+                } else {
+                    if (LOCAL_LOGV) {
+                        LogUtil.v(TAG, "Saving data to: " + uri);
+                    }
+                    if (!isDrm) {
+                        os.write(data);
+                    } else {
+                        dataUri = uri;
+                        final byte[] convertedData = drmConvertSession.convert(data, data.length);
+                        if (convertedData != null) {
+                            os.write(convertedData, 0, convertedData.length);
+                        } else {
+                            throw new MmsException("Error converting drm data.");
+                        }
+                    }
+                }
+            }
+        } catch (final SQLiteException e) {
+            Log.e(TAG, "Failed with SQLiteException.", e);
+            throw new MmsException(e);
+        } catch (final FileNotFoundException e) {
+            Log.e(TAG, "Failed to open Input/Output stream.", e);
+            throw new MmsException(e);
+        } catch (final IOException e) {
+            Log.e(TAG, "Failed to read/write data.", e);
+            throw new MmsException(e);
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (final IOException e) {
+                    Log.e(TAG, "IOException while closing: " + os, e);
+                } // Ignore
+            }
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (final IOException e) {
+                    Log.e(TAG, "IOException while closing: " + is, e);
+                } // Ignore
+            }
+            if (drmConvertSession != null) {
+                drmConvertSession.close(path);
+
+                // Reset the permissions on the encrypted part file so everyone has only read
+                // permission.
+                final File f = new File(path);
+                final ContentValues values = new ContentValues(0);
+                SqliteWrapper.update(mContext, mContentResolver,
+                        Uri.parse("content://mms/resetFilePerm/" + f.getName()),
+                        values, null, null);
+            }
+        }
+    }
+
+    /**
+     * This method expects uri in the following format
+     *     content://media/<table_name>/<row_index> (or)
+     *     file://sdcard/test.mp4
+     *     http://test.com/test.mp4
+     *
+     * Here <table_name> shall be "video" or "audio" or "images"
+     * <row_index> the index of the content in given table
+     */
+    public static String convertUriToPath(final Context context, final Uri uri) {
+        String path = null;
+        if (null != uri) {
+            final String scheme = uri.getScheme();
+            if (null == scheme || scheme.equals("") || UriUtil.isFileUri(uri)) {
+                path = uri.getPath();
+
+            } else if (scheme.equals("http")) {
+                path = uri.toString();
+
+            } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
+                final String[] projection = new String[] {MediaStore.MediaColumns.DATA};
+                Cursor cursor = null;
+                try {
+                    cursor = context.getContentResolver().query(uri, projection, null,
+                            null, null);
+                    if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
+                        throw new IllegalArgumentException("Given Uri could not be found" +
+                                " in media store");
+                    }
+                    final int pathIndex =
+                            cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
+                    path = cursor.getString(pathIndex);
+                } catch (final SQLiteException e) {
+                    throw new IllegalArgumentException("Given Uri is not formatted in a way " +
+                            "so that it can be found in media store.");
+                } finally {
+                    if (null != cursor) {
+                        cursor.close();
+                    }
+                }
+            } else {
+                throw new IllegalArgumentException("Given Uri scheme is not supported");
+            }
+        }
+        return path;
+    }
+
+    private void updateAddress(
+            final long msgId, final int type, final EncodedStringValue[] array) {
+        // Delete old address information and then insert new ones.
+        SqliteWrapper.delete(mContext, mContentResolver,
+                Uri.parse("content://mms/" + msgId + "/addr"),
+                Addr.TYPE + "=" + type, null);
+
+        persistAddress(msgId, type, array);
+    }
+
+    /**
+     * Update headers of a SendReq.
+     *
+     * @param uri The PDU which need to be updated.
+     * @param pdu New headers.
+     * @throws MmsException Bad URI or updating failed.
+     */
+    public void updateHeaders(final Uri uri, final SendReq sendReq) {
+        synchronized (PDU_CACHE_INSTANCE) {
+            // If the cache item is getting updated, wait until it's done updating before
+            // purging it.
+            if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                if (LOCAL_LOGV) {
+                    LogUtil.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()");
+                }
+                try {
+                    PDU_CACHE_INSTANCE.wait();
+                } catch (final InterruptedException e) {
+                    Log.e(TAG, "updateHeaders: ", e);
+                }
+            }
+        }
+        PDU_CACHE_INSTANCE.purge(uri);
+
+        final ContentValues values = new ContentValues(10);
+        final byte[] contentType = sendReq.getContentType();
+        if (contentType != null) {
+            values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
+        }
+
+        final long date = sendReq.getDate();
+        if (date != -1) {
+            values.put(Mms.DATE, date);
+        }
+
+        final int deliveryReport = sendReq.getDeliveryReport();
+        if (deliveryReport != 0) {
+            values.put(Mms.DELIVERY_REPORT, deliveryReport);
+        }
+
+        final long expiry = sendReq.getExpiry();
+        if (expiry != -1) {
+            values.put(Mms.EXPIRY, expiry);
+        }
+
+        final byte[] msgClass = sendReq.getMessageClass();
+        if (msgClass != null) {
+            values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass));
+        }
+
+        final int priority = sendReq.getPriority();
+        if (priority != 0) {
+            values.put(Mms.PRIORITY, priority);
+        }
+
+        final int readReport = sendReq.getReadReport();
+        if (readReport != 0) {
+            values.put(Mms.READ_REPORT, readReport);
+        }
+
+        final byte[] transId = sendReq.getTransactionId();
+        if (transId != null) {
+            values.put(Mms.TRANSACTION_ID, toIsoString(transId));
+        }
+
+        final EncodedStringValue subject = sendReq.getSubject();
+        if (subject != null) {
+            values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
+            values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
+        } else {
+            values.put(Mms.SUBJECT, "");
+        }
+
+        final long messageSize = sendReq.getMessageSize();
+        if (messageSize > 0) {
+            values.put(Mms.MESSAGE_SIZE, messageSize);
+        }
+
+        final PduHeaders headers = sendReq.getPduHeaders();
+        final HashSet<String> recipients = new HashSet<String>();
+        for (final int addrType : ADDRESS_FIELDS) {
+            EncodedStringValue[] array = null;
+            if (addrType == PduHeaders.FROM) {
+                final EncodedStringValue v = headers.getEncodedStringValue(addrType);
+                if (v != null) {
+                    array = new EncodedStringValue[1];
+                    array[0] = v;
+                }
+            } else {
+                array = headers.getEncodedStringValues(addrType);
+            }
+
+            if (array != null) {
+                final long msgId = ContentUris.parseId(uri);
+                updateAddress(msgId, addrType, array);
+                if (addrType == PduHeaders.TO) {
+                    for (final EncodedStringValue v : array) {
+                        if (v != null) {
+                            recipients.add(v.getString());
+                        }
+                    }
+                }
+            }
+        }
+        if (!recipients.isEmpty()) {
+            final long threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients);
+            values.put(Mms.THREAD_ID, threadId);
+        }
+
+        SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
+    }
+
+
+    private void updatePart(final Uri uri, final PduPart part,
+            final Map<Uri, InputStream> preOpenedFiles)
+            throws MmsException {
+        final ContentValues values = new ContentValues(7);
+
+        final int charset = part.getCharset();
+        if (charset != 0) {
+            values.put(Part.CHARSET, charset);
+        }
+
+        String contentType = null;
+        if (part.getContentType() != null) {
+            contentType = toIsoString(part.getContentType());
+            values.put(Part.CONTENT_TYPE, contentType);
+        } else {
+            throw new MmsException("MIME type of the part must be set.");
+        }
+
+        getValues(part, values);
+
+        SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
+
+        // Only update the data when:
+        // 1. New binary data supplied or
+        // 2. The Uri of the part is different from the current one.
+        if ((part.getData() != null)
+                || (!uri.equals(part.getDataUri()))) {
+            persistData(part, uri, contentType, preOpenedFiles);
+        }
+    }
+
+    /**
+     * Update all parts of a PDU.
+     *
+     * @param uri            The PDU which need to be updated.
+     * @param body           New message body of the PDU.
+     * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
+     * @throws MmsException Bad URI or updating failed.
+     */
+    public void updateParts(final Uri uri, final PduBody body,
+            final Map<Uri, InputStream> preOpenedFiles)
+            throws MmsException {
+        try {
+            PduCacheEntry cacheEntry;
+            synchronized (PDU_CACHE_INSTANCE) {
+                if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                    if (LOCAL_LOGV) {
+                        LogUtil.v(TAG, "updateParts: " + uri + " blocked by isUpdating()");
+                    }
+                    try {
+                        PDU_CACHE_INSTANCE.wait();
+                    } catch (final InterruptedException e) {
+                        Log.e(TAG, "updateParts: ", e);
+                    }
+                    cacheEntry = PDU_CACHE_INSTANCE.get(uri);
+                    if (cacheEntry != null) {
+                        ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
+                    }
+                }
+                // Tell the cache to indicate to other callers that this item
+                // is currently being updated.
+                PDU_CACHE_INSTANCE.setUpdating(uri, true);
+            }
+
+            final ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
+            final ArrayMap<Uri, PduPart> toBeUpdated = new ArrayMap<Uri, PduPart>();
+
+            final int partsNum = body.getPartsNum();
+            final StringBuilder filter = new StringBuilder().append('(');
+            for (int i = 0; i < partsNum; i++) {
+                final PduPart part = body.getPart(i);
+                final Uri partUri = part.getDataUri();
+                if ((partUri == null) || TextUtils.isEmpty(partUri.getAuthority())
+                        || !partUri.getAuthority().startsWith("mms")) {
+                    toBeCreated.add(part);
+                } else {
+                    toBeUpdated.put(partUri, part);
+
+                    // Don't use 'i > 0' to determine whether we should append
+                    // 'AND' since 'i = 0' may be skipped in another branch.
+                    if (filter.length() > 1) {
+                        filter.append(" AND ");
+                    }
+
+                    filter.append(Part._ID);
+                    filter.append("!=");
+                    DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
+                }
+            }
+            filter.append(')');
+
+            final long msgId = ContentUris.parseId(uri);
+
+            // Remove the parts which doesn't exist anymore.
+            SqliteWrapper.delete(mContext, mContentResolver,
+                    Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
+                    filter.length() > 2 ? filter.toString() : null, null);
+
+            // Create new parts which didn't exist before.
+            for (final PduPart part : toBeCreated) {
+                persistPart(part, msgId, preOpenedFiles);
+            }
+
+            // Update the modified parts.
+            for (final Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
+                updatePart(e.getKey(), e.getValue(), preOpenedFiles);
+            }
+        } finally {
+            synchronized (PDU_CACHE_INSTANCE) {
+                PDU_CACHE_INSTANCE.setUpdating(uri, false);
+                PDU_CACHE_INSTANCE.notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Persist a PDU object to specific location in the storage.
+     *
+     * @param pdu             The PDU object to be stored.
+     * @param uri             Where to store the given PDU object.
+     * @param subId           Subscription id associated with this message.
+     * @param subPhoneNumber TODO
+     * @param preOpenedFiles  if not null, a map of preopened InputStreams for the parts.
+     * @return A Uri which can be used to access the stored PDU.
+     */
+    public Uri persist(final GenericPdu pdu, final Uri uri, final int subId,
+            final String subPhoneNumber, final Map<Uri, InputStream> preOpenedFiles)
+            throws MmsException {
+        if (uri == null) {
+            throw new MmsException("Uri may not be null.");
+        }
+        long msgId = -1;
+        try {
+            msgId = ContentUris.parseId(uri);
+        } catch (final NumberFormatException e) {
+            // the uri ends with "inbox" or something else like that
+        }
+        final boolean existingUri = msgId != -1;
+
+        if (!existingUri && MESSAGE_BOX_MAP.get(uri) == null) {
+            throw new MmsException(
+                    "Bad destination, must be one of "
+                            + "content://mms/inbox, content://mms/sent, "
+                            + "content://mms/drafts, content://mms/outbox, "
+                            + "content://mms/temp."
+            );
+        }
+        synchronized (PDU_CACHE_INSTANCE) {
+            // If the cache item is getting updated, wait until it's done updating before
+            // purging it.
+            if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                if (LOCAL_LOGV) {
+                    LogUtil.v(TAG, "persist: " + uri + " blocked by isUpdating()");
+                }
+                try {
+                    PDU_CACHE_INSTANCE.wait();
+                } catch (final InterruptedException e) {
+                    Log.e(TAG, "persist1: ", e);
+                }
+            }
+        }
+        PDU_CACHE_INSTANCE.purge(uri);
+
+        final PduHeaders header = pdu.getPduHeaders();
+        PduBody body = null;
+        ContentValues values = new ContentValues();
+
+        // Mark new messages as seen in the telephony database so that we don't have to
+        // do a global "set all messages as seen" since that occasionally seems to be
+        // problematic (i.e. very slow).  See bug 18189471.
+        values.put(Mms.SEEN, 1);
+
+        //Set<Entry<Integer, String>> set;
+
+        for (int i = ENCODED_STRING_COLUMN_NAME_MAP.size(); --i >= 0; ) {
+            final int field = ENCODED_STRING_COLUMN_NAME_MAP.keyAt(i);
+            final EncodedStringValue encodedString = header.getEncodedStringValue(field);
+            if (encodedString != null) {
+                final String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field);
+                values.put(ENCODED_STRING_COLUMN_NAME_MAP.valueAt(i),
+                        toIsoString(encodedString.getTextString()));
+                values.put(charsetColumn, encodedString.getCharacterSet());
+            }
+        }
+
+        for (int i = TEXT_STRING_COLUMN_NAME_MAP.size(); --i >= 0; ) {
+            final byte[] text = header.getTextString(TEXT_STRING_COLUMN_NAME_MAP.keyAt(i));
+            if (text != null) {
+                values.put(TEXT_STRING_COLUMN_NAME_MAP.valueAt(i), toIsoString(text));
+            }
+        }
+
+        for (int i = OCTET_COLUMN_NAME_MAP.size(); --i >= 0; ) {
+            final int b = header.getOctet(OCTET_COLUMN_NAME_MAP.keyAt(i));
+            if (b != 0) {
+                values.put(OCTET_COLUMN_NAME_MAP.valueAt(i), b);
+            }
+        }
+
+        for (int i = LONG_COLUMN_NAME_MAP.size(); --i >= 0; ) {
+            final long l = header.getLongInteger(LONG_COLUMN_NAME_MAP.keyAt(i));
+            if (l != -1L) {
+                values.put(LONG_COLUMN_NAME_MAP.valueAt(i), l);
+            }
+        }
+
+        final SparseArray<EncodedStringValue[]> addressMap =
+                new SparseArray<EncodedStringValue[]>(ADDRESS_FIELDS.length);
+        // Save address information.
+        for (final int addrType : ADDRESS_FIELDS) {
+            EncodedStringValue[] array = null;
+            if (addrType == PduHeaders.FROM) {
+                final EncodedStringValue v = header.getEncodedStringValue(addrType);
+                if (v != null) {
+                    array = new EncodedStringValue[1];
+                    array[0] = v;
+                }
+            } else {
+                array = header.getEncodedStringValues(addrType);
+            }
+            addressMap.put(addrType, array);
+        }
+
+        final HashSet<String> recipients = new HashSet<String>();
+        final int msgType = pdu.getMessageType();
+        // Here we only allocate thread ID for M-Notification.ind,
+        // M-Retrieve.conf and M-Send.req.
+        // Some of other PDU types may be allocated a thread ID outside
+        // this scope.
+        if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
+                || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
+                || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
+            switch (msgType) {
+                case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
+                case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
+                    loadRecipients(PduHeaders.FROM, recipients, addressMap);
+
+                    // For received messages (whether group MMS is enabled or not) we want to
+                    // associate this message with the thread composed of all the recipients
+                    // EXCLUDING our own number. This includes the person who sent the message
+                    // (the FROM field above) in addition to the other people the message was
+                    // addressed TO (or CC fields to address group messaging compatibility issues
+                    // with devices that place numbers in this field). Typically our own number is
+                    // in the TO/CC field so we have to remove it in checkAndLoadToCcRecipients.
+                    checkAndLoadToCcRecipients(recipients, addressMap, subPhoneNumber);
+                    break;
+                case PduHeaders.MESSAGE_TYPE_SEND_REQ:
+                    loadRecipients(PduHeaders.TO, recipients, addressMap);
+                    break;
+            }
+            long threadId = -1L;
+            if (!recipients.isEmpty()) {
+                // Given all the recipients associated with this message, find (or create) the
+                // correct thread.
+                threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients);
+            } else {
+                LogUtil.w(TAG, "PduPersister.persist No recipients; persisting PDU to thread: "
+                        + threadId);
+            }
+            values.put(Mms.THREAD_ID, threadId);
+        }
+
+        // Save parts first to avoid inconsistent message is loaded
+        // while saving the parts.
+        final long placeholderId = System.currentTimeMillis(); // Placeholder ID of the msg.
+
+        // Figure out if this PDU is a text-only message
+        boolean textOnly = true;
+
+        // Get body if the PDU is a RetrieveConf or SendReq.
+        if (pdu instanceof MultimediaMessagePdu) {
+            body = ((MultimediaMessagePdu) pdu).getBody();
+            // Start saving parts if necessary.
+            if (body != null) {
+                final int partsNum = body.getPartsNum();
+                if (LOCAL_LOGV) {
+                    LogUtil.v(TAG, "PduPersister.persist partsNum: " + partsNum);
+                }
+                if (partsNum > 2) {
+                    // For a text-only message there will be two parts: 1-the SMIL, 2-the text.
+                    // Down a few lines below we're checking to make sure we've only got SMIL or
+                    // text. We also have to check then we don't have more than two parts.
+                    // Otherwise, a slideshow with two text slides would be marked as textOnly.
+                    textOnly = false;
+                }
+                for (int i = 0; i < partsNum; i++) {
+                    final PduPart part = body.getPart(i);
+                    persistPart(part, placeholderId, preOpenedFiles);
+
+                    // If we've got anything besides text/plain or SMIL part, then we've got
+                    // an mms message with some other type of attachment.
+                    final String contentType = getPartContentType(part);
+                    if (LOCAL_LOGV) {
+                        LogUtil.v(TAG, "PduPersister.persist part: " + i + " contentType: " +
+                                contentType);
+                    }
+                    if (contentType != null && !ContentType.APP_SMIL.equals(contentType)
+                            && !ContentType.TEXT_PLAIN.equals(contentType)) {
+                        textOnly = false;
+                    }
+                }
+            }
+        }
+        // Record whether this mms message is a simple plain text or not. This is a hint for the
+        // UI.
+        if (OsUtil.isAtLeastJB_MR1()) {
+            values.put(Mms.TEXT_ONLY, textOnly ? 1 : 0);
+        }
+
+        if (OsUtil.isAtLeastL_MR1()) {
+            values.put(Mms.SUBSCRIPTION_ID, subId);
+        } else {
+            Assert.equals(ParticipantData.DEFAULT_SELF_SUB_ID, subId);
+        }
+
+        Uri res = null;
+        if (existingUri) {
+            res = uri;
+            SqliteWrapper.update(mContext, mContentResolver, res, values, null, null);
+        } else {
+            res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
+            if (res == null) {
+                throw new MmsException("persist() failed: return null.");
+            }
+            // Get the real ID of the PDU and update all parts which were
+            // saved with the placeholder ID.
+            msgId = ContentUris.parseId(res);
+        }
+
+        values = new ContentValues(1);
+        values.put(Part.MSG_ID, msgId);
+        SqliteWrapper.update(mContext, mContentResolver,
+                Uri.parse("content://mms/" + placeholderId + "/part"),
+                values, null, null);
+        // We should return the longest URI of the persisted PDU, for
+        // example, if input URI is "content://mms/inbox" and the _ID of
+        // persisted PDU is '8', we should return "content://mms/inbox/8"
+        // instead of "content://mms/8".
+        // TODO: Should the MmsProvider be responsible for this???
+        if (!existingUri) {
+            res = Uri.parse(uri + "/" + msgId);
+        }
+
+        // Save address information.
+        for (final int addrType : ADDRESS_FIELDS) {
+            final EncodedStringValue[] array = addressMap.get(addrType);
+            if (array != null) {
+                persistAddress(msgId, addrType, array);
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * For a given address type, extract the recipients from the headers.
+     *
+     * @param addressType     can be PduHeaders.FROM or PduHeaders.TO
+     * @param recipients      a HashSet that is loaded with the recipients from the FROM or TO
+     *                        headers
+     * @param addressMap      a HashMap of the addresses from the ADDRESS_FIELDS header
+     */
+    private void loadRecipients(final int addressType, final HashSet<String> recipients,
+            final SparseArray<EncodedStringValue[]> addressMap) {
+        final EncodedStringValue[] array = addressMap.get(addressType);
+        if (array == null) {
+            return;
+        }
+        for (final EncodedStringValue v : array) {
+            if (v != null) {
+                final String number = v.getString();
+                if (!recipients.contains(number)) {
+                    // Only add numbers which aren't already included.
+                    recipients.add(number);
+                }
+            }
+        }
+    }
+
+    /**
+     * For a given address type, extract the recipients from the headers.
+     *
+     * @param recipients      a HashSet that is loaded with the recipients from the FROM or TO
+     *                        headers
+     * @param addressMap      a HashMap of the addresses from the ADDRESS_FIELDS header
+     * @param selfNumber      self phone number
+     */
+    private void checkAndLoadToCcRecipients(final HashSet<String> recipients,
+            final SparseArray<EncodedStringValue[]> addressMap, final String selfNumber) {
+        final EncodedStringValue[] arrayTo = addressMap.get(PduHeaders.TO);
+        final EncodedStringValue[] arrayCc = addressMap.get(PduHeaders.CC);
+        final ArrayList<String> numbers = new ArrayList<String>();
+        if (arrayTo != null) {
+            for (final EncodedStringValue v : arrayTo) {
+                if (v != null) {
+                    numbers.add(v.getString());
+                }
+            }
+        }
+        if (arrayCc != null) {
+            for (final EncodedStringValue v : arrayCc) {
+                if (v != null) {
+                    numbers.add(v.getString());
+                }
+            }
+        }
+
+        // If selfNumber is unavailable and there is only a single address in all TO and CC, we can
+        // skip adding it into recipients as assuming it is my own phone number.
+        final boolean isSelfNumberUnavailable = TextUtils.isEmpty(selfNumber);
+        if (isSelfNumberUnavailable && numbers.size() == 1) {
+            return;
+        }
+
+        for (final String number : numbers) {
+            // Only add numbers which aren't my own number.
+            if (isSelfNumberUnavailable || !PhoneNumberUtils.compare(number, selfNumber)) {
+                if (!recipients.contains(number)) {
+                    // Only add numbers which aren't already included.
+                    recipients.add(number);
+                }
+            }
+        }
+    }
+
+    /**
+     * Move a PDU object from one location to another.
+     *
+     * @param from Specify the PDU object to be moved.
+     * @param to   The destination location, should be one of the following:
+     *             "content://mms/inbox", "content://mms/sent",
+     *             "content://mms/drafts", "content://mms/outbox",
+     *             "content://mms/trash".
+     * @return New Uri of the moved PDU.
+     * @throws MmsException Error occurred while moving the message.
+     */
+    public Uri move(final Uri from, final Uri to) throws MmsException {
+        // Check whether the 'msgId' has been assigned a valid value.
+        final long msgId = ContentUris.parseId(from);
+        if (msgId == -1L) {
+            throw new MmsException("Error! ID of the message: -1.");
+        }
+
+        // Get corresponding int value of destination box.
+        final Integer msgBox = MESSAGE_BOX_MAP.get(to);
+        if (msgBox == null) {
+            throw new MmsException(
+                    "Bad destination, must be one of "
+                            + "content://mms/inbox, content://mms/sent, "
+                            + "content://mms/drafts, content://mms/outbox, "
+                            + "content://mms/temp."
+            );
+        }
+
+        final ContentValues values = new ContentValues(1);
+        values.put(Mms.MESSAGE_BOX, msgBox);
+        SqliteWrapper.update(mContext, mContentResolver, from, values, null, null);
+        return ContentUris.withAppendedId(to, msgId);
+    }
+
+    /**
+     * Wrap a byte[] into a String.
+     */
+    public static String toIsoString(final byte[] bytes) {
+        try {
+            return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
+        } catch (final UnsupportedEncodingException e) {
+            // Impossible to reach here!
+            Log.e(TAG, "ISO_8859_1 must be supported!", e);
+            return "";
+        }
+    }
+
+    /**
+     * Unpack a given String into a byte[].
+     */
+    public static byte[] getBytes(final String data) {
+        try {
+            return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
+        } catch (final UnsupportedEncodingException e) {
+            // Impossible to reach here!
+            Log.e(TAG, "ISO_8859_1 must be supported!", e);
+            return new byte[0];
+        }
+    }
+
+    /**
+     * Remove all objects in the temporary path.
+     */
+    public void release() {
+        final Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI);
+        SqliteWrapper.delete(mContext, mContentResolver, uri, null, null);
+    }
+
+    /**
+     * Find all messages to be sent or downloaded before certain time.
+     */
+    public Cursor getPendingMessages(final long dueTime) {
+        final Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon();
+        uriBuilder.appendQueryParameter("protocol", "mms");
+
+        final String selection = PendingMessages.ERROR_TYPE + " < ?"
+                + " AND " + PendingMessages.DUE_TIME + " <= ?";
+
+        final String[] selectionArgs = new String[] {
+                String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT),
+                String.valueOf(dueTime)
+        };
+
+        return SqliteWrapper.query(mContext, mContentResolver,
+                uriBuilder.build(), null, selection, selectionArgs,
+                PendingMessages.DUE_TIME);
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/QuotedPrintable.java b/src/com/android/messaging/mmslib/pdu/QuotedPrintable.java
new file mode 100644
index 0000000..1ce9dc1
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/QuotedPrintable.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import java.io.ByteArrayOutputStream;
+
+public class QuotedPrintable {
+    private static byte ESCAPE_CHAR = '=';
+
+    /**
+     * Decodes an array quoted-printable characters into an array of original bytes.
+     * Escaped characters are converted back to their original representation.
+     *
+     * <p>
+     * This function implements a subset of
+     * quoted-printable encoding specification (rule #1 and rule #2)
+     * as defined in RFC 1521.
+     * </p>
+     *
+     * @param bytes array of quoted-printable characters
+     * @return array of original bytes,
+     *         null if quoted-printable decoding is unsuccessful.
+     */
+    public static final byte[] decodeQuotedPrintable(byte[] bytes) {
+        if (bytes == null) {
+            return null;
+        }
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        for (int i = 0; i < bytes.length; i++) {
+            int b = bytes[i];
+            if (b == ESCAPE_CHAR) {
+                try {
+                    if ('\r' == (char) bytes[i + 1] &&
+                            '\n' == (char) bytes[i + 2]) {
+                        i += 2;
+                        continue;
+                    }
+                    int u = Character.digit((char) bytes[++i], 16);
+                    int l = Character.digit((char) bytes[++i], 16);
+                    if (u == -1 || l == -1) {
+                        return null;
+                    }
+                    buffer.write((char) ((u << 4) + l));
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    return null;
+                }
+            } else {
+                buffer.write(b);
+            }
+        }
+        return buffer.toByteArray();
+    }
+}
diff --git a/src/com/android/messaging/mmslib/pdu/ReadOrigInd.java b/src/com/android/messaging/mmslib/pdu/ReadOrigInd.java
new file mode 100644
index 0000000..198e4c3
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/ReadOrigInd.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+public class ReadOrigInd extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public ReadOrigInd() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_READ_ORIG_IND);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    ReadOrigInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-MMS-Read-status value.
+     *
+     * @return the value
+     */
+    public int getReadStatus() {
+        return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Set X-MMS-Read-status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/ReadRecInd.java b/src/com/android/messaging/mmslib/pdu/ReadRecInd.java
new file mode 100644
index 0000000..c1a9ae4
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/ReadRecInd.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+public class ReadRecInd extends GenericPdu {
+    /**
+     * Constructor, used when composing a M-ReadRec.ind pdu.
+     *
+     * @param from       the from value
+     * @param messageId  the message ID value
+     * @param mmsVersion current viersion of mms
+     * @param readStatus the read status value
+     * @param to         the to value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     * @throws NullPointerException if messageId or to is null.
+     */
+    public ReadRecInd(EncodedStringValue from,
+            byte[] messageId,
+            int mmsVersion,
+            int readStatus,
+            EncodedStringValue[] to) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
+        setFrom(from);
+        setMessageId(messageId);
+        setMmsVersion(mmsVersion);
+        setTo(to);
+        setReadStatus(readStatus);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    ReadRecInd(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Date value.
+     *
+     * @return the value
+     */
+    public long getDate() {
+        return mPduHeaders.getLongInteger(PduHeaders.DATE);
+    }
+
+    /**
+     * Set Date value.
+     *
+     * @param value the value
+     */
+    public void setDate(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.DATE);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get To value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getTo() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
+    }
+
+    /**
+     * Set To value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-MMS-Read-status value.
+     *
+     * @return the value
+     */
+    public int getReadStatus() {
+        return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
+    }
+
+    /**
+     * Set X-MMS-Read-status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/RetrieveConf.java b/src/com/android/messaging/mmslib/pdu/RetrieveConf.java
new file mode 100644
index 0000000..9e0faed
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/RetrieveConf.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+/**
+ * M-Retrive.conf Pdu.
+ */
+public class RetrieveConf extends MultimediaMessagePdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public RetrieveConf() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    RetrieveConf(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Constructor with given headers and body
+     *
+     * @param headers Headers for this PDU.
+     * @param body    Body of this PDu.
+     */
+    RetrieveConf(PduHeaders headers, PduBody body) {
+        super(headers, body);
+    }
+
+    /**
+     * Get CC value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getCc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
+    }
+
+    /**
+     * Add a "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addCc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
+    }
+
+    /**
+     * Get Content-type value.
+     *
+     * @return the value
+     */
+    public byte[] getContentType() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Set Content-type value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentType(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Get From value.
+     * From-value = Value-length
+     *      (Address-present-token Encoded-string-value | Insert-address-token)
+     *
+     * @return the value
+     */
+    public EncodedStringValue getFrom() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
+    }
+
+    /**
+     * Set From value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setFrom(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-Mms-Read-Report value.
+     *
+     * @return the value
+     */
+    public int getReadReport() {
+        return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Read-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Get X-Mms-Retrieve-Status value.
+     *
+     * @return the value
+     */
+    public int getRetrieveStatus() {
+        /*
+         * If the header is not there, assuming it is OK status.
+         * Some carriers may choose to not send this header.
+         */
+        return mPduHeaders.hasHeader(PduHeaders.RETRIEVE_STATUS) ?
+                mPduHeaders.getOctet(PduHeaders.RETRIEVE_STATUS) : PduHeaders.RETRIEVE_STATUS_OK;
+    }
+
+    /**
+     * Set X-Mms-Retrieve-Status value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setRetrieveStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.RETRIEVE_STATUS);
+    }
+
+    /**
+     * Get X-Mms-Retrieve-Text value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue getRetrieveText() {
+        return mPduHeaders.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT);
+    }
+
+    /**
+     * Set X-Mms-Retrieve-Text value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setRetrieveText(EncodedStringValue value) {
+        mPduHeaders.setEncodedStringValue(value, PduHeaders.RETRIEVE_TEXT);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id.
+     *
+     * @return the value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getContentClass() {return 0x00;}
+     *     public void setApplicId(byte value) {}
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public byte getDistributionIndicator() {return 0x00;}
+     *     public void setDistributionIndicator(byte value) {}
+     *
+     *     public PreviouslySentByValue getPreviouslySentBy() {return null;}
+     *     public void setPreviouslySentBy(PreviouslySentByValue value) {}
+     *
+     *     public PreviouslySentDateValue getPreviouslySentDate() {}
+     *     public void setPreviouslySentDate(PreviouslySentDateValue value) {}
+     *
+     *     public MmFlagsValue getMmFlags() {return null;}
+     *     public void setMmFlags(MmFlagsValue value) {}
+     *
+     *     public MmStateValue getMmState() {return null;}
+     *     public void getMmState(MmStateValue value) {}
+     *
+     *     public byte[] getReplaceId() {return 0x00;}
+     *     public void setReplaceId(byte[] value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/SendConf.java b/src/com/android/messaging/mmslib/pdu/SendConf.java
new file mode 100644
index 0000000..cf1399e
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/SendConf.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007 Esmertec AG.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+public class SendConf extends GenericPdu {
+    /**
+     * Empty constructor.
+     * Since the Pdu corresponding to this class is constructed
+     * by the Proxy-Relay server, this class is only instantiated
+     * by the Pdu Parser.
+     *
+     * @throws InvalidHeaderValueException if error occurs.
+     */
+    public SendConf() throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_SEND_CONF);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    SendConf(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Get Message-ID value.
+     *
+     * @return the value
+     */
+    public byte[] getMessageId() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Set Message-ID value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
+    }
+
+    /**
+     * Get X-Mms-Response-Status.
+     *
+     * @return the value
+     */
+    public int getResponseStatus() {
+        return mPduHeaders.getOctet(PduHeaders.RESPONSE_STATUS);
+    }
+
+    /**
+     * Set X-Mms-Response-Status.
+     *
+     * @param value the values
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setResponseStatus(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.RESPONSE_STATUS);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *    public byte[] getContentLocation() {return null;}
+     *    public void setContentLocation(byte[] value) {}
+     *
+     *    public EncodedStringValue getResponseText() {return null;}
+     *    public void setResponseText(EncodedStringValue value) {}
+     *
+     *    public byte getStoreStatus() {return 0x00;}
+     *    public void setStoreStatus(byte value) {}
+     *
+     *    public byte[] getStoreStatusText() {return null;}
+     *    public void setStoreStatusText(byte[] value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/pdu/SendReq.java b/src/com/android/messaging/mmslib/pdu/SendReq.java
new file mode 100644
index 0000000..d173c0b
--- /dev/null
+++ b/src/com/android/messaging/mmslib/pdu/SendReq.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.pdu;
+
+import android.util.Log;
+
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+
+public class SendReq extends MultimediaMessagePdu {
+    private static final String TAG = "SendReq";
+
+    public SendReq() {
+        super();
+
+        try {
+            setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
+            setMmsVersion(PduHeaders.CURRENT_MMS_VERSION);
+            // TODO: Content-type must be decided according to whether
+            // SMIL part present.
+            setContentType("application/vnd.wap.multipart.related".getBytes());
+            setFrom(new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()));
+            setTransactionId(generateTransactionId());
+        } catch (InvalidHeaderValueException e) {
+            // Impossible to reach here since all headers we set above are valid.
+            Log.e(TAG, "Unexpected InvalidHeaderValueException.", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    private byte[] generateTransactionId() {
+        String transactionId = "T" + Long.toHexString(System.currentTimeMillis());
+        return transactionId.getBytes();
+    }
+
+    /**
+     * Constructor, used when composing a M-Send.req pdu.
+     *
+     * @param contentType   the content type value
+     * @param from          the from value
+     * @param mmsVersion    current viersion of mms
+     * @param transactionId the transaction-id value
+     * @throws InvalidHeaderValueException if parameters are invalid.
+     *                                     NullPointerException if contentType, form or
+     *                                     transactionId is null.
+     */
+    public SendReq(byte[] contentType,
+            EncodedStringValue from,
+            int mmsVersion,
+            byte[] transactionId) throws InvalidHeaderValueException {
+        super();
+        setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
+        setContentType(contentType);
+        setFrom(from);
+        setMmsVersion(mmsVersion);
+        setTransactionId(transactionId);
+    }
+
+    /**
+     * Constructor with given headers.
+     *
+     * @param headers Headers for this PDU.
+     */
+    SendReq(PduHeaders headers) {
+        super(headers);
+    }
+
+    /**
+     * Constructor with given headers and body
+     *
+     * @param headers Headers for this PDU.
+     * @param body    Body of this PDu.
+     */
+    SendReq(PduHeaders headers, PduBody body) {
+        super(headers, body);
+    }
+
+    /**
+     * Get Bcc value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getBcc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.BCC);
+    }
+
+    /**
+     * Add a "BCC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addBcc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.BCC);
+    }
+
+    /**
+     * Set "BCC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setBcc(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.BCC);
+    }
+
+    /**
+     * Get CC value.
+     *
+     * @return the value
+     */
+    public EncodedStringValue[] getCc() {
+        return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
+    }
+
+    /**
+     * Add a "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void addCc(EncodedStringValue value) {
+        mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
+    }
+
+    /**
+     * Set "CC" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setCc(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.CC);
+    }
+
+    /**
+     * Get Content-type value.
+     *
+     * @return the value
+     */
+    public byte[] getContentType() {
+        return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Set Content-type value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setContentType(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
+    }
+
+    /**
+     * Get X-Mms-Delivery-Report value.
+     *
+     * @return the value
+     */
+    public int getDeliveryReport() {
+        return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Delivery-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setDeliveryReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
+    }
+
+    /**
+     * Get X-Mms-Expiry value.
+     *
+     * Expiry-value = Value-length
+     *      (Absolute-token Date-value | Relative-token Delta-seconds-value)
+     *
+     * @return the value
+     */
+    public long getExpiry() {
+        return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Set X-Mms-Expiry value.
+     *
+     * @param value the value
+     */
+    public void setExpiry(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
+    }
+
+    /**
+     * Get X-Mms-MessageSize value.
+     *
+     * Expiry-value = size of message
+     *
+     * @return the value
+     */
+    public long getMessageSize() {
+        return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Set X-Mms-MessageSize value.
+     *
+     * @param value the value
+     */
+    public void setMessageSize(long value) {
+        mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
+    }
+
+    /**
+     * Get X-Mms-Message-Class value.
+     * Message-class-value = Class-identifier | Token-text
+     * Class-identifier = Personal | Advertisement | Informational | Auto
+     *
+     * @return the value
+     */
+    public byte[] getMessageClass() {
+        return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Set X-Mms-Message-Class value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setMessageClass(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
+    }
+
+    /**
+     * Get X-Mms-Read-Report value.
+     *
+     * @return the value
+     */
+    public int getReadReport() {
+        return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set X-Mms-Read-Report value.
+     *
+     * @param value the value
+     * @throws InvalidHeaderValueException if the value is invalid.
+     */
+    public void setReadReport(int value) throws InvalidHeaderValueException {
+        mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
+    }
+
+    /**
+     * Set "To" value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTo(EncodedStringValue[] value) {
+        mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
+    }
+
+    /**
+     * Get X-Mms-Transaction-Id field value.
+     *
+     * @return the X-Mms-Report-Allowed value
+     */
+    public byte[] getTransactionId() {
+        return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
+    }
+
+    /**
+     * Set X-Mms-Transaction-Id field value.
+     *
+     * @param value the value
+     * @throws NullPointerException if the value is null.
+     */
+    public void setTransactionId(byte[] value) {
+        mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
+    }
+
+    /*
+     * Optional, not supported header fields:
+     *
+     *     public byte getAdaptationAllowed() {return 0};
+     *     public void setAdaptationAllowed(btye value) {};
+     *
+     *     public byte[] getApplicId() {return null;}
+     *     public void setApplicId(byte[] value) {}
+     *
+     *     public byte[] getAuxApplicId() {return null;}
+     *     public void getAuxApplicId(byte[] value) {}
+     *
+     *     public byte getContentClass() {return 0x00;}
+     *     public void setApplicId(byte value) {}
+     *
+     *     public long getDeliveryTime() {return 0};
+     *     public void setDeliveryTime(long value) {};
+     *
+     *     public byte getDrmContent() {return 0x00;}
+     *     public void setDrmContent(byte value) {}
+     *
+     *     public MmFlagsValue getMmFlags() {return null;}
+     *     public void setMmFlags(MmFlagsValue value) {}
+     *
+     *     public MmStateValue getMmState() {return null;}
+     *     public void getMmState(MmStateValue value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getReplyCharging() {return 0x00;}
+     *     public void setReplyCharging(byte value) {}
+     *
+     *     public byte getReplyChargingDeadline() {return 0x00;}
+     *     public void setReplyChargingDeadline(byte value) {}
+     *
+     *     public byte[] getReplyChargingId() {return 0x00;}
+     *     public void setReplyChargingId(byte[] value) {}
+     *
+     *     public long getReplyChargingSize() {return 0;}
+     *     public void setReplyChargingSize(long value) {}
+     *
+     *     public byte[] getReplyApplicId() {return 0x00;}
+     *     public void setReplyApplicId(byte[] value) {}
+     *
+     *     public byte getStore() {return 0x00;}
+     *     public void setStore(byte value) {}
+     */
+}
diff --git a/src/com/android/messaging/mmslib/util/AbstractCache.java b/src/com/android/messaging/mmslib/util/AbstractCache.java
new file mode 100644
index 0000000..a4d678a
--- /dev/null
+++ b/src/com/android/messaging/mmslib/util/AbstractCache.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 Esmertec AG.
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.util;
+
+import androidx.collection.SimpleArrayMap;
+import android.util.Log;
+
+public abstract class AbstractCache<K, V> {
+    private static final String TAG = "AbstractCache";
+    private static final boolean LOCAL_LOGV = false;
+
+    private static final int MAX_CACHED_ITEMS = 500;
+
+    private final SimpleArrayMap<K, CacheEntry<V>> mCacheMap;
+
+    protected AbstractCache() {
+        mCacheMap = new SimpleArrayMap<K, CacheEntry<V>>();
+    }
+
+    public boolean put(K key, V value) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Trying to put " + key + " into cache.");
+        }
+
+        if (mCacheMap.size() >= MAX_CACHED_ITEMS) {
+            // TODO: Should remove the oldest or least hit cached entry
+            // and then cache the new one.
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Failed! size limitation reached.");
+            }
+            return false;
+        }
+
+        if (key != null) {
+            CacheEntry<V> cacheEntry = new CacheEntry<V>();
+            cacheEntry.value = value;
+            mCacheMap.put(key, cacheEntry);
+
+            if (LOCAL_LOGV) {
+                Log.v(TAG, key + " cached, " + mCacheMap.size() + " items total.");
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public V get(K key) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Trying to get " + key + " from cache.");
+        }
+
+        if (key != null) {
+            CacheEntry<V> cacheEntry = mCacheMap.get(key);
+            if (cacheEntry != null) {
+                cacheEntry.hit++;
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, key + " hit " + cacheEntry.hit + " times.");
+                }
+                return cacheEntry.value;
+            }
+        }
+        return null;
+    }
+
+    public V purge(K key) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Trying to purge " + key);
+        }
+
+        CacheEntry<V> v = mCacheMap.remove(key);
+
+        if (LOCAL_LOGV) {
+            Log.v(TAG, mCacheMap.size() + " items cached.");
+        }
+
+        return v != null ? v.value : null;
+    }
+
+    public void purgeAll() {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Purging cache, " + mCacheMap.size()
+                    + " items dropped.");
+        }
+        mCacheMap.clear();
+    }
+
+    public int size() {
+        return mCacheMap.size();
+    }
+
+    private static class CacheEntry<V> {
+
+        int hit;
+
+        V value;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/util/DownloadDrmHelper.java b/src/com/android/messaging/mmslib/util/DownloadDrmHelper.java
new file mode 100644
index 0000000..c38b179
--- /dev/null
+++ b/src/com/android/messaging/mmslib/util/DownloadDrmHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.messaging.mmslib.util;
+
+import android.content.Context;
+import android.drm.DrmManagerClient;
+import android.util.Log;
+
+public class DownloadDrmHelper {
+    private static final String TAG = "DownloadDrmHelper";
+
+    /** The MIME type of special DRM files */
+    public static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
+
+    /** The extensions of special DRM files */
+    public static final String EXTENSION_DRM_MESSAGE = ".dm";
+
+    public static final String EXTENSION_INTERNAL_FWDL = ".fl";
+
+    /**
+     * Checks if the Media Type is a DRM Media Type
+     *
+     * @param drmManagerClient A DrmManagerClient
+     * @param mimetype         Media Type to check
+     * @return True if the Media Type is DRM else false
+     */
+    public static boolean isDrmMimeType(Context context, String mimetype) {
+        boolean result = false;
+        if (context != null) {
+            try {
+                DrmManagerClient drmClient = new DrmManagerClient(context);
+                if (drmClient != null && mimetype != null && mimetype.length() > 0) {
+                    result = drmClient.canHandle("", mimetype);
+                }
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG,
+                        "DrmManagerClient instance could not be created, context is Illegal.");
+            } catch (IllegalStateException e) {
+                Log.w(TAG, "DrmManagerClient didn't initialize properly.");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks if the Media Type needs to be DRM converted
+     *
+     * @param mimetype Media type of the content
+     * @return True if convert is needed else false
+     */
+    public static boolean isDrmConvertNeeded(String mimetype) {
+        return MIMETYPE_DRM_MESSAGE.equals(mimetype);
+    }
+
+    /**
+     * Modifies the file extension for a DRM Forward Lock file NOTE: This
+     * function shouldn't be called if the file shouldn't be DRM converted
+     */
+    public static String modifyDrmFwLockFileExtension(String filename) {
+        if (filename != null) {
+            int extensionIndex;
+            extensionIndex = filename.lastIndexOf(".");
+            if (extensionIndex != -1) {
+                filename = filename.substring(0, extensionIndex);
+            }
+            filename = filename.concat(EXTENSION_INTERNAL_FWDL);
+        }
+        return filename;
+    }
+
+    /**
+     * Gets the original mime type of DRM protected content.
+     *
+     * @param context        The context
+     * @param path           Path to the file
+     * @param containingMime The current mime type of of the file i.e. the
+     *                       containing mime type
+     * @return The original mime type of the file if DRM protected else the
+     *         currentMime
+     */
+    public static String getOriginalMimeType(Context context, String path, String containingMime) {
+        String result = containingMime;
+        DrmManagerClient drmClient = new DrmManagerClient(context);
+        try {
+            if (drmClient.canHandle(path, null)) {
+                result = drmClient.getOriginalMimeType(path);
+            }
+        } catch (IllegalArgumentException ex) {
+            Log.w(TAG,
+                    "Can't get original mime type since path is null or empty string.");
+        } catch (IllegalStateException ex) {
+            Log.w(TAG, "DrmManagerClient didn't initialize properly.");
+        }
+        return result;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/util/DrmConvertSession.java b/src/com/android/messaging/mmslib/util/DrmConvertSession.java
new file mode 100644
index 0000000..604e391
--- /dev/null
+++ b/src/com/android/messaging/mmslib/util/DrmConvertSession.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.android.messaging.mmslib.util;
+
+import android.content.Context;
+import android.drm.DrmConvertedStatus;
+import android.drm.DrmManagerClient;
+import android.util.Log;
+
+import com.android.messaging.mmslib.Downloads;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+
+public class DrmConvertSession {
+    private DrmManagerClient mDrmClient;
+    private int mConvertSessionId;
+    private static final String TAG = "DrmConvertSession";
+
+    private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) {
+        mDrmClient = drmClient;
+        mConvertSessionId = convertSessionId;
+    }
+
+    /**
+     * Start of converting a file.
+     *
+     * @param context  The context of the application running the convert session.
+     * @param mimeType Mimetype of content that shall be converted.
+     * @return A convert session or null in case an error occurs.
+     */
+    public static DrmConvertSession open(Context context, String mimeType) {
+        DrmManagerClient drmClient = null;
+        int convertSessionId = -1;
+        if (context != null && mimeType != null && !mimeType.equals("")) {
+            try {
+                drmClient = new DrmManagerClient(context);
+                try {
+                    convertSessionId = drmClient.openConvertSession(mimeType);
+                } catch (IllegalArgumentException e) {
+                    Log.w(TAG, "Conversion of Mimetype: " + mimeType
+                            + " is not supported.", e);
+                } catch (IllegalStateException e) {
+                    Log.w(TAG, "Could not access Open DrmFramework.", e);
+                }
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG,
+                        "DrmManagerClient instance could not be created, context is Illegal.");
+            } catch (IllegalStateException e) {
+                Log.w(TAG, "DrmManagerClient didn't initialize properly.");
+            }
+        }
+
+        if (drmClient == null || convertSessionId < 0) {
+            return null;
+        } else {
+            return new DrmConvertSession(drmClient, convertSessionId);
+        }
+    }
+
+    /**
+     * Convert a buffer of data to protected format.
+     *
+     * @param buffer Buffer filled with data to convert.
+     * @param size   The number of bytes that shall be converted.
+     * @return A Buffer filled with converted data, if execution is ok, in all
+     * other case null.
+     */
+    public byte[] convert(byte[] inBuffer, int size) {
+        byte[] result = null;
+        if (inBuffer != null) {
+            DrmConvertedStatus convertedStatus = null;
+            try {
+                if (size != inBuffer.length) {
+                    byte[] buf = new byte[size];
+                    System.arraycopy(inBuffer, 0, buf, 0, size);
+                    convertedStatus = mDrmClient.convertData(mConvertSessionId, buf);
+                } else {
+                    convertedStatus = mDrmClient.convertData(mConvertSessionId, inBuffer);
+                }
+
+                if (convertedStatus != null &&
+                        convertedStatus.statusCode == DrmConvertedStatus.STATUS_OK &&
+                        convertedStatus.convertedData != null) {
+                    result = convertedStatus.convertedData;
+                }
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG, "Buffer with data to convert is illegal. Convertsession: "
+                        + mConvertSessionId, e);
+            } catch (IllegalStateException e) {
+                Log.w(TAG, "Could not convert data. Convertsession: " +
+                        mConvertSessionId, e);
+            }
+        } else {
+            throw new IllegalArgumentException("Parameter inBuffer is null");
+        }
+        return result;
+    }
+
+    /**
+     * Ends a conversion session of a file.
+     *
+     * @param fileName The filename of the converted file.
+     * @return Downloads.Impl.STATUS_SUCCESS if execution is ok.
+     *         Downloads.Impl.STATUS_FILE_ERROR in case converted file can not
+     *         be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem
+     *         occurs when accessing drm framework.
+     *         Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred.
+     */
+    public int close(String filename) {
+        DrmConvertedStatus convertedStatus = null;
+        int result = Downloads.Impl.STATUS_UNKNOWN_ERROR;
+        if (mDrmClient != null && mConvertSessionId >= 0) {
+            try {
+                convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId);
+                if (convertedStatus == null ||
+                        convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
+                        convertedStatus.convertedData == null) {
+                    result = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
+                } else {
+                    RandomAccessFile rndAccessFile = null;
+                    try {
+                        rndAccessFile = new RandomAccessFile(filename, "rw");
+                        rndAccessFile.seek(convertedStatus.offset);
+                        rndAccessFile.write(convertedStatus.convertedData);
+                        result = Downloads.Impl.STATUS_SUCCESS;
+                    } catch (FileNotFoundException e) {
+                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        Log.w(TAG, "File: " + filename + " could not be found.", e);
+                    } catch (IOException e) {
+                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        Log.w(TAG, "Could not access File: " + filename + " .", e);
+                    } catch (IllegalArgumentException e) {
+                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        Log.w(TAG, "Could not open file in mode: rw", e);
+                    } catch (SecurityException e) {
+                        Log.w(TAG, "Access to File: " + filename +
+                                " was denied denied by SecurityManager.", e);
+                    } finally {
+                        if (rndAccessFile != null) {
+                            try {
+                                rndAccessFile.close();
+                            } catch (IOException e) {
+                                result = Downloads.Impl.STATUS_FILE_ERROR;
+                                Log.w(TAG, "Failed to close File:" + filename
+                                        + ".", e);
+                            }
+                        }
+                    }
+                }
+            } catch (IllegalStateException e) {
+                Log.w(TAG, "Could not close convertsession. Convertsession: " +
+                        mConvertSessionId, e);
+            }
+        }
+        return result;
+    }
+}
diff --git a/src/com/android/messaging/mmslib/util/PduCache.java b/src/com/android/messaging/mmslib/util/PduCache.java
new file mode 100644
index 0000000..939e4bd
--- /dev/null
+++ b/src/com/android/messaging/mmslib/util/PduCache.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2008 Esmertec AG.
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.util;
+
+import android.content.ContentUris;
+import android.content.UriMatcher;
+import android.net.Uri;
+import android.provider.Telephony.Mms;
+import androidx.collection.SimpleArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.util.HashSet;
+
+public final class PduCache extends AbstractCache<Uri, PduCacheEntry> {
+    private static final String TAG = "PduCache";
+    private static final boolean LOCAL_LOGV = false;
+
+    private static final int MMS_ALL             = 0;
+    private static final int MMS_ALL_ID          = 1;
+    private static final int MMS_INBOX           = 2;
+    private static final int MMS_INBOX_ID        = 3;
+    private static final int MMS_SENT            = 4;
+    private static final int MMS_SENT_ID         = 5;
+    private static final int MMS_DRAFTS          = 6;
+    private static final int MMS_DRAFTS_ID       = 7;
+    private static final int MMS_OUTBOX          = 8;
+    private static final int MMS_OUTBOX_ID       = 9;
+    private static final int MMS_CONVERSATION    = 10;
+    private static final int MMS_CONVERSATION_ID = 11;
+
+    private static final UriMatcher URI_MATCHER;
+    private static final SparseArray<Integer> MATCH_TO_MSGBOX_ID_MAP;
+
+    private static PduCache sInstance;
+
+    static {
+        URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
+        URI_MATCHER.addURI("mms", null,         MMS_ALL);
+        URI_MATCHER.addURI("mms", "#",          MMS_ALL_ID);
+        URI_MATCHER.addURI("mms", "inbox",      MMS_INBOX);
+        URI_MATCHER.addURI("mms", "inbox/#",    MMS_INBOX_ID);
+        URI_MATCHER.addURI("mms", "sent",       MMS_SENT);
+        URI_MATCHER.addURI("mms", "sent/#",     MMS_SENT_ID);
+        URI_MATCHER.addURI("mms", "drafts",     MMS_DRAFTS);
+        URI_MATCHER.addURI("mms", "drafts/#",   MMS_DRAFTS_ID);
+        URI_MATCHER.addURI("mms", "outbox",     MMS_OUTBOX);
+        URI_MATCHER.addURI("mms", "outbox/#",   MMS_OUTBOX_ID);
+        URI_MATCHER.addURI("mms-sms", "conversations",   MMS_CONVERSATION);
+        URI_MATCHER.addURI("mms-sms", "conversations/#", MMS_CONVERSATION_ID);
+
+        MATCH_TO_MSGBOX_ID_MAP = new SparseArray<Integer>();
+        MATCH_TO_MSGBOX_ID_MAP.put(MMS_INBOX,  Mms.MESSAGE_BOX_INBOX);
+        MATCH_TO_MSGBOX_ID_MAP.put(MMS_SENT,   Mms.MESSAGE_BOX_SENT);
+        MATCH_TO_MSGBOX_ID_MAP.put(MMS_DRAFTS, Mms.MESSAGE_BOX_DRAFTS);
+        MATCH_TO_MSGBOX_ID_MAP.put(MMS_OUTBOX, Mms.MESSAGE_BOX_OUTBOX);
+    }
+
+    private final SparseArray<HashSet<Uri>> mMessageBoxes;
+    private final SimpleArrayMap<Long, HashSet<Uri>> mThreads;
+    private final HashSet<Uri> mUpdating;
+
+    private PduCache() {
+        mMessageBoxes = new SparseArray<HashSet<Uri>>();
+        mThreads = new SimpleArrayMap<Long, HashSet<Uri>>();
+        mUpdating = new HashSet<Uri>();
+    }
+
+    public static final synchronized PduCache getInstance() {
+        if (sInstance == null) {
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Constructing new PduCache instance.");
+            }
+            sInstance = new PduCache();
+        }
+        return sInstance;
+    }
+
+    @Override
+    public synchronized boolean put(Uri uri, PduCacheEntry entry) {
+        int msgBoxId = entry.getMessageBox();
+        HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId);
+        if (msgBox == null) {
+            msgBox = new HashSet<Uri>();
+            mMessageBoxes.put(msgBoxId, msgBox);
+        }
+
+        long threadId = entry.getThreadId();
+        HashSet<Uri> thread = mThreads.get(threadId);
+        if (thread == null) {
+            thread = new HashSet<Uri>();
+            mThreads.put(threadId, thread);
+        }
+
+        Uri finalKey = normalizeKey(uri);
+        boolean result = super.put(finalKey, entry);
+        if (result) {
+            msgBox.add(finalKey);
+            thread.add(finalKey);
+        }
+        setUpdating(uri, false);
+        return result;
+    }
+
+    public synchronized void setUpdating(Uri uri, boolean updating) {
+        if (updating) {
+            mUpdating.add(uri);
+        } else {
+            mUpdating.remove(uri);
+        }
+    }
+
+    public synchronized boolean isUpdating(Uri uri) {
+        return mUpdating.contains(uri);
+    }
+
+    @Override
+    public synchronized PduCacheEntry purge(Uri uri) {
+        int match = URI_MATCHER.match(uri);
+        switch (match) {
+            case MMS_ALL_ID:
+                return purgeSingleEntry(uri);
+            case MMS_INBOX_ID:
+            case MMS_SENT_ID:
+            case MMS_DRAFTS_ID:
+            case MMS_OUTBOX_ID:
+                String msgId = uri.getLastPathSegment();
+                return purgeSingleEntry(Uri.withAppendedPath(Mms.CONTENT_URI, msgId));
+            // Implicit batch of purge, return null.
+            case MMS_ALL:
+            case MMS_CONVERSATION:
+                purgeAll();
+                return null;
+            case MMS_INBOX:
+            case MMS_SENT:
+            case MMS_DRAFTS:
+            case MMS_OUTBOX:
+                purgeByMessageBox(MATCH_TO_MSGBOX_ID_MAP.get(match));
+                return null;
+            case MMS_CONVERSATION_ID:
+                purgeByThreadId(ContentUris.parseId(uri));
+                return null;
+            default:
+                return null;
+        }
+    }
+
+    private PduCacheEntry purgeSingleEntry(Uri key) {
+        mUpdating.remove(key);
+        PduCacheEntry entry = super.purge(key);
+        if (entry != null) {
+            removeFromThreads(key, entry);
+            removeFromMessageBoxes(key, entry);
+            return entry;
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized void purgeAll() {
+        super.purgeAll();
+
+        mMessageBoxes.clear();
+        mThreads.clear();
+        mUpdating.clear();
+    }
+
+    /**
+     * @param uri The Uri to be normalized.
+     * @return Uri The normalized key of cached entry.
+     */
+    private Uri normalizeKey(Uri uri) {
+        int match = URI_MATCHER.match(uri);
+        Uri normalizedKey = null;
+
+        switch (match) {
+            case MMS_ALL_ID:
+                normalizedKey = uri;
+                break;
+            case MMS_INBOX_ID:
+            case MMS_SENT_ID:
+            case MMS_DRAFTS_ID:
+            case MMS_OUTBOX_ID:
+                String msgId = uri.getLastPathSegment();
+                normalizedKey = Uri.withAppendedPath(Mms.CONTENT_URI, msgId);
+                break;
+            default:
+                return null;
+        }
+
+        if (LOCAL_LOGV) {
+            Log.v(TAG, uri + " -> " + normalizedKey);
+        }
+        return normalizedKey;
+    }
+
+    private void purgeByMessageBox(Integer msgBoxId) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Purge cache in message box: " + msgBoxId);
+        }
+
+        if (msgBoxId != null) {
+            HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId);
+            mMessageBoxes.remove(msgBoxId);
+            if (msgBox != null) {
+                for (Uri key : msgBox) {
+                    mUpdating.remove(key);
+                    PduCacheEntry entry = super.purge(key);
+                    if (entry != null) {
+                        removeFromThreads(key, entry);
+                    }
+                }
+            }
+        }
+    }
+
+    private void removeFromThreads(Uri key, PduCacheEntry entry) {
+        HashSet<Uri> thread = mThreads.get(entry.getThreadId());
+        if (thread != null) {
+            thread.remove(key);
+        }
+    }
+
+    private void purgeByThreadId(long threadId) {
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Purge cache in thread: " + threadId);
+        }
+
+        HashSet<Uri> thread = mThreads.remove(threadId);
+        if (thread != null) {
+            for (Uri key : thread) {
+                mUpdating.remove(key);
+                PduCacheEntry entry = super.purge(key);
+                if (entry != null) {
+                    removeFromMessageBoxes(key, entry);
+                }
+            }
+        }
+    }
+
+    private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) {
+        HashSet<Uri> msgBox = mThreads.get(Long.valueOf(entry.getMessageBox()));
+        if (msgBox != null) {
+            msgBox.remove(key);
+        }
+    }
+}
diff --git a/src/com/android/messaging/mmslib/util/PduCacheEntry.java b/src/com/android/messaging/mmslib/util/PduCacheEntry.java
new file mode 100644
index 0000000..b287f00
--- /dev/null
+++ b/src/com/android/messaging/mmslib/util/PduCacheEntry.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Esmertec AG.
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.mmslib.util;
+
+import com.android.messaging.mmslib.pdu.GenericPdu;
+
+public final class PduCacheEntry {
+    private final GenericPdu mPdu;
+    private final int mMessageBox;
+    private final long mThreadId;
+
+    public PduCacheEntry(GenericPdu pdu, int msgBox, long threadId) {
+        mPdu = pdu;
+        mMessageBox = msgBox;
+        mThreadId = threadId;
+    }
+
+    public GenericPdu getPdu() {
+        return mPdu;
+    }
+
+    public int getMessageBox() {
+        return mMessageBox;
+    }
+
+    public long getThreadId() {
+        return mThreadId;
+    }
+}
diff --git a/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java b/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java
new file mode 100644
index 0000000..9e09a2a
--- /dev/null
+++ b/src/com/android/messaging/receiver/AbortMmsWapPushReceiver.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Telephony;
+
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * This receiver is used to abort MMS WAP broadcasts pre-KLP when SMS is enabled.
+ */
+public class AbortMmsWapPushReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction())
+                && ContentType.MMS_MESSAGE.equals(intent.getType())) {
+            // If we are enabled, it's our job to stop the broadcast from continuing. This
+            // receiver is not used on KLP but we do an extra check here just to make sure.
+            if (!OsUtil.isAtLeastKLP() && PhoneUtils.getDefault().isSmsEnabled()) {
+                abortBroadcast();
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/receiver/AbortSmsReceiver.java b/src/com/android/messaging/receiver/AbortSmsReceiver.java
new file mode 100644
index 0000000..f4491d8
--- /dev/null
+++ b/src/com/android/messaging/receiver/AbortSmsReceiver.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * This receiver is used to abort SMS broadcasts pre-KLP when SMS is enabled.
+ */
+public final class AbortSmsReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        // If we are enabled, it's our job to stop the broadcast from continuing. This
+        // receiver is not used on KLP but we do an extra check here just to make sure.
+        if (!OsUtil.isAtLeastKLP() && PhoneUtils.getDefault().isSmsEnabled()) {
+            if (!SmsReceiver.shouldIgnoreMessage(intent)) {
+                abortBroadcast();
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java b/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java
new file mode 100644
index 0000000..be0d296
--- /dev/null
+++ b/src/com/android/messaging/receiver/BootAndPackageReplacedReceiver.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.messaging.BugleApplication;
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.action.UpdateMessageNotificationAction;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Receives notification of boot completion and package replacement
+ */
+public class BootAndPackageReplacedReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())
+                || Intent.ACTION_MY_PACKAGE_REPLACED.equals(intent.getAction())) {
+            // Repost unseen notifications
+            Factory.get().getApplicationPrefs().putLong(
+                    BuglePrefsKeys.LATEST_NOTIFICATION_MESSAGE_TIMESTAMP, Long.MIN_VALUE);
+            UpdateMessageNotificationAction.updateMessageNotification();
+
+            BugleApplication.updateAppConfig(context);
+        } else {
+            LogUtil.i(LogUtil.BUGLE_TAG, "BootAndPackageReplacedReceiver got unexpected action: "
+                    + intent.getAction());
+        }
+    }
+}
+
diff --git a/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java b/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java
new file mode 100644
index 0000000..d5153a0
--- /dev/null
+++ b/src/com/android/messaging/receiver/DefaultSmsSubscriptionChangeReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.messaging.datamodel.ParticipantRefresh;
+
+/**
+ * Responds to default SMS subscription selection changes from system Settings.
+ */
+public class DefaultSmsSubscriptionChangeReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+         ParticipantRefresh.refreshSelfParticipants();
+    }
+}
diff --git a/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java b/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java
new file mode 100644
index 0000000..a5c247c
--- /dev/null
+++ b/src/com/android/messaging/receiver/MmsWapPushDeliverReceiver.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Telephony;
+
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Class that handles MMS WAP push intent from telephony on KLP+ Devices.
+ */
+public class MmsWapPushDeliverReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION.equals(intent.getAction())
+                && ContentType.MMS_MESSAGE.equals(intent.getType())) {
+            // Always convert negative subIds into -1
+            int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem(
+                    intent, MmsWapPushReceiver.EXTRA_SUBSCRIPTION);
+            byte[] data = intent.getByteArrayExtra(MmsWapPushReceiver.EXTRA_DATA);
+            MmsWapPushReceiver.mmsReceived(subId, data);
+        }
+    }
+}
diff --git a/src/com/android/messaging/receiver/MmsWapPushReceiver.java b/src/com/android/messaging/receiver/MmsWapPushReceiver.java
new file mode 100644
index 0000000..29cf0db
--- /dev/null
+++ b/src/com/android/messaging/receiver/MmsWapPushReceiver.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Telephony;
+
+import com.android.messaging.datamodel.action.ReceiveMmsMessageAction;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Class that handles MMS WAP push intent from telephony on pre-KLP Devices.
+ */
+public class MmsWapPushReceiver extends BroadcastReceiver {
+    static final String EXTRA_SUBSCRIPTION = "subscription";
+    static final String EXTRA_DATA = "data";
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction())
+                && ContentType.MMS_MESSAGE.equals(intent.getType())) {
+            if (PhoneUtils.getDefault().isSmsEnabled()) {
+                // Always convert negative subIds into -1
+                final int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem(
+                        intent, MmsWapPushReceiver.EXTRA_SUBSCRIPTION);
+                final byte[] data = intent.getByteArrayExtra(MmsWapPushReceiver.EXTRA_DATA);
+                mmsReceived(subId, data);
+            }
+        }
+    }
+
+    static void mmsReceived(final int subId, final byte[] data) {
+        if (!PhoneUtils.getDefault().isSmsEnabled()) {
+            return;
+        }
+
+        final ReceiveMmsMessageAction action = new ReceiveMmsMessageAction(subId, data);
+        action.start();
+    }
+}
+
diff --git a/src/com/android/messaging/receiver/NotificationReceiver.java b/src/com/android/messaging/receiver/NotificationReceiver.java
new file mode 100644
index 0000000..bbb847d
--- /dev/null
+++ b/src/com/android/messaging/receiver/NotificationReceiver.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.action.MarkAsSeenAction;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.ConversationIdSet;
+import com.android.messaging.util.LogUtil;
+
+// NotificationReceiver is used to handle delete intents from notifications. When a user
+// clears all notifications or swipes a bugle notification away, the intent we pass in as
+// the delete intent will get handled here.
+public class NotificationReceiver extends BroadcastReceiver {
+    // Logging
+    public static final String TAG = LogUtil.BUGLE_TAG;
+    public static final boolean VERBOSE = false;
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (VERBOSE) {
+            LogUtil.v(TAG, "NotificationReceiver.onReceive: intent " + intent);
+        }
+        if (intent.getAction().equals(UIIntents.ACTION_RESET_NOTIFICATIONS)) {
+            final String conversationIdSetString =
+                    intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID_SET);
+            final int notificationTargets = intent.getIntExtra(
+                    UIIntents.UI_INTENT_EXTRA_NOTIFICATIONS_UPDATE, BugleNotifications.UPDATE_ALL);
+            if (conversationIdSetString == null) {
+                BugleNotifications.markAllMessagesAsSeen();
+            } else {
+                for (final String conversationId :
+                        ConversationIdSet.createSet(conversationIdSetString)) {
+                    MarkAsSeenAction.markAsSeen(conversationId);
+                    BugleNotifications.resetLastMessageDing(conversationId);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/receiver/SendStatusReceiver.java b/src/com/android/messaging/receiver/SendStatusReceiver.java
new file mode 100644
index 0000000..8d2e10f
--- /dev/null
+++ b/src/com/android/messaging/receiver/SendStatusReceiver.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Telephony.Sms;
+import android.telephony.SmsMessage;
+
+import com.android.messaging.datamodel.action.ProcessDeliveryReportAction;
+import com.android.messaging.datamodel.action.ProcessDownloadedMmsAction;
+import com.android.messaging.datamodel.action.ProcessSentMessageAction;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.sms.SmsSender;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * The SMS sent and delivery intent receiver.
+ *
+ * This class just simply forwards the intents to proper recipients for actual handling.
+ */
+public class SendStatusReceiver extends BroadcastReceiver {
+    public static final String MESSAGE_SENT_ACTION =
+            "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_SENT";
+    public static final String MESSAGE_DELIVERED_ACTION =
+            "com.android.messaging.receiver.SendStatusReceiver.MESSAGE_DELIVERED";
+    public static final String MMS_SENT_ACTION =
+            "com.android.messaging.receiver.SendStatusReceiver.MMS_SENT";
+    public static final String MMS_DOWNLOADED_ACTION =
+            "com.android.messaging.receiver.SendStatusReceiver.MMS_DOWNLOADED";
+
+    // Defined by platform, but no constant provided. See docs for SmsManager.sendTextMessage.
+    public static final String EXTRA_ERROR_CODE = "errorCode";
+
+    public static final String EXTRA_PART_ID = "partId";
+    public static final String EXTRA_SUB_ID = "subId";
+
+    public static final int NO_ERROR_CODE = -1;
+    public static final int NO_PART_ID = -1;
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        // This will be called on the main thread (so it should exit quickly)
+        final String action = intent.getAction();
+        final int resultCode = getResultCode();
+        if (MESSAGE_SENT_ACTION.equals(action)) {
+            final Uri requestId = intent.getData();
+            SmsSender.setResult(
+                    requestId,
+                    resultCode,
+                    intent.getIntExtra(EXTRA_ERROR_CODE, NO_ERROR_CODE),
+                    intent.getIntExtra(EXTRA_PART_ID, NO_PART_ID),
+                    intent.getIntExtra(EXTRA_SUB_ID, ParticipantData.DEFAULT_SELF_SUB_ID));
+        } else if (MMS_SENT_ACTION.equals(action)) {
+            final Uri messageUri = intent.getData();
+            ProcessSentMessageAction.processMmsSent(resultCode, messageUri,
+                    intent.getExtras());
+        } else if (MMS_DOWNLOADED_ACTION.equals(action)) {
+            ProcessDownloadedMmsAction.processMessageDownloaded(resultCode,
+                    intent.getExtras());
+        } else if (MESSAGE_DELIVERED_ACTION.equals(action)) {
+            final SmsMessage smsMessage = MmsUtils.getSmsMessageFromDeliveryReport(intent);
+            final Uri smsMessageUri = intent.getData();
+            if (smsMessage == null) {
+                LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: empty report message");
+                return;
+            }
+            int status = Sms.STATUS_COMPLETE;
+            try {
+                final String format = intent.getStringExtra("format");
+                status = smsMessage.getStatus();
+                // Simple matching up CDMA status with GSM status.
+                if ("3gpp2".equals(format)) {
+                    final int errorClass = (status >> 24) & 0x03;
+                    final int statusCode = (status >> 16) & 0x3f;
+                    switch (errorClass) {
+                        case 0: /*ERROR_NONE*/
+                            if (statusCode == 0x02 /*STATUS_DELIVERED*/) {
+                                status = Sms.STATUS_COMPLETE;
+                            } else status = Sms.STATUS_PENDING;
+                            break;
+                        case 2: /*ERROR_TEMPORARY*/
+                            // TODO: Need to check whether SC still trying to deliver the SMS to
+                            // destination and will send the report again?
+                            status = Sms.STATUS_PENDING;
+                            break;
+                        case 3: /*ERROR_PERMANENT*/
+                            status = Sms.STATUS_FAILED;
+                            break;
+                        default:
+                            status = Sms.STATUS_PENDING;
+                    }
+                }
+            } catch (final NullPointerException e) {
+                // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access
+                // the methods on it although the SmsMessage itself is not null.
+                LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: NPE inside SmsMessage");
+                return;
+            }
+            ProcessDeliveryReportAction.deliveryReportReceived(smsMessageUri, status);
+        }
+    }
+}
diff --git a/src/com/android/messaging/receiver/SmsDeliverReceiver.java b/src/com/android/messaging/receiver/SmsDeliverReceiver.java
new file mode 100644
index 0000000..6a9b66c
--- /dev/null
+++ b/src/com/android/messaging/receiver/SmsDeliverReceiver.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Class that receives incoming SMS messages on KLP+ Devices.
+ */
+public final class SmsDeliverReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        SmsReceiver.deliverSmsIntent(context, intent);
+    }
+}
diff --git a/src/com/android/messaging/receiver/SmsReceiver.java b/src/com/android/messaging/receiver/SmsReceiver.java
new file mode 100644
index 0000000..f1f9bcd
--- /dev/null
+++ b/src/com/android/messaging/receiver/SmsReceiver.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.provider.Telephony;
+import android.provider.Telephony.Sms;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationCompat.Builder;
+import androidx.core.app.NotificationCompat.Style;
+import androidx.core.app.NotificationManagerCompat;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.BugleNotifications;
+import com.android.messaging.datamodel.MessageNotificationState;
+import com.android.messaging.datamodel.NoConfirmationSmsSendService;
+import com.android.messaging.datamodel.action.ReceiveSmsMessageAction;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PendingIntentConstants;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Class that receives incoming SMS messages through android.provider.Telephony.SMS_RECEIVED
+ *
+ * This class serves two purposes:
+ * - Process phone verification SMS messages
+ * - Handle SMS messages when the user has enabled us to be the default SMS app (Pre-KLP)
+ */
+public final class SmsReceiver extends BroadcastReceiver {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static ArrayList<Pattern> sIgnoreSmsPatterns;
+
+    /**
+     * Enable or disable the SmsReceiver as appropriate. Pre-KLP we use this receiver for
+     * receiving incoming SMS messages. For KLP+ this receiver is not used when running as the
+     * primary user and the SmsDeliverReceiver is used for receiving incoming SMS messages.
+     * When running as a secondary user, this receiver is still used to trigger the incoming
+     * notification.
+     */
+    public static void updateSmsReceiveHandler(final Context context) {
+        boolean smsReceiverEnabled;
+        boolean mmsWapPushReceiverEnabled;
+        boolean respondViaMessageEnabled;
+        boolean broadcastAbortEnabled;
+
+        if (OsUtil.isAtLeastKLP()) {
+            // When we're running as the secondary user, we don't get the new SMS_DELIVER intent,
+            // only the primary user receives that. As secondary, we need to go old-school and
+            // listen for the SMS_RECEIVED intent. For the secondary user, use this SmsReceiver
+            // for both sms and mms notification. For the primary user on KLP (and above), we don't
+            // use the SmsReceiver.
+            smsReceiverEnabled = OsUtil.isSecondaryUser();
+            // On KLP use the new deliver event for mms
+            mmsWapPushReceiverEnabled = false;
+            // On KLP we need to always enable this handler to show in the list of sms apps
+            respondViaMessageEnabled = true;
+            // On KLP we don't need to abort the broadcast
+            broadcastAbortEnabled = false;
+        } else {
+            // On JB we use the sms receiver for both sms/mms delivery
+            final boolean carrierSmsEnabled = PhoneUtils.getDefault().isSmsEnabled();
+            smsReceiverEnabled = carrierSmsEnabled;
+
+            // On JB we use the mms receiver when sms/mms is enabled
+            mmsWapPushReceiverEnabled = carrierSmsEnabled;
+            // On JB this is dynamic to make sure we don't show in dialer if sms is disabled
+            respondViaMessageEnabled = carrierSmsEnabled;
+            // On JB we need to abort broadcasts if SMS is enabled
+            broadcastAbortEnabled = carrierSmsEnabled;
+        }
+
+        final PackageManager packageManager = context.getPackageManager();
+        final boolean logv = LogUtil.isLoggable(TAG, LogUtil.VERBOSE);
+        if (smsReceiverEnabled) {
+            if (logv) {
+                LogUtil.v(TAG, "Enabling SMS message receiving");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, SmsReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+
+        } else {
+            if (logv) {
+                LogUtil.v(TAG, "Disabling SMS message receiving");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, SmsReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+        }
+        if (mmsWapPushReceiverEnabled) {
+            if (logv) {
+                LogUtil.v(TAG, "Enabling MMS message receiving");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, MmsWapPushReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+        } else {
+            if (logv) {
+                LogUtil.v(TAG, "Disabling MMS message receiving");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, MmsWapPushReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+        }
+        if (broadcastAbortEnabled) {
+            if (logv) {
+                LogUtil.v(TAG, "Enabling SMS/MMS broadcast abort");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, AbortSmsReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, AbortMmsWapPushReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+        } else {
+            if (logv) {
+                LogUtil.v(TAG, "Disabling SMS/MMS broadcast abort");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, AbortSmsReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, AbortMmsWapPushReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+        }
+        if (respondViaMessageEnabled) {
+            if (logv) {
+                LogUtil.v(TAG, "Enabling respond via message intent");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, NoConfirmationSmsSendService.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+        } else {
+            if (logv) {
+                LogUtil.v(TAG, "Disabling respond via message intent");
+            }
+            packageManager.setComponentEnabledSetting(
+                    new ComponentName(context, NoConfirmationSmsSendService.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+        }
+    }
+
+    private static final String EXTRA_ERROR_CODE = "errorCode";
+    private static final String EXTRA_SUB_ID = "subscription";
+
+    public static void deliverSmsIntent(final Context context, final Intent intent) {
+        final android.telephony.SmsMessage[] messages = getMessagesFromIntent(intent);
+
+        // Check messages for validity
+        if (messages == null || messages.length < 1) {
+            LogUtil.e(TAG, "processReceivedSms: null or zero or ignored message");
+            return;
+        }
+
+        final int errorCode =
+                intent.getIntExtra(EXTRA_ERROR_CODE, SendStatusReceiver.NO_ERROR_CODE);
+        // Always convert negative subIds into -1
+        int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem(
+                intent, EXTRA_SUB_ID);
+        deliverSmsMessages(context, subId, errorCode, messages);
+        if (MmsUtils.isDumpSmsEnabled()) {
+            final String format = intent.getStringExtra("format");
+            DebugUtils.dumpSms(messages[0].getTimestampMillis(), messages, format);
+        }
+    }
+
+    public static void deliverSmsMessages(final Context context, final int subId,
+            final int errorCode, final android.telephony.SmsMessage[] messages) {
+        final ContentValues messageValues =
+                MmsUtils.parseReceivedSmsMessage(context, messages, errorCode);
+
+        LogUtil.v(TAG, "SmsReceiver.deliverSmsMessages");
+
+        final long nowInMillis =  System.currentTimeMillis();
+        final long receivedTimestampMs = MmsUtils.getMessageDate(messages[0], nowInMillis);
+
+        messageValues.put(Sms.Inbox.DATE, receivedTimestampMs);
+        // Default to unread and unseen for us but ReceiveSmsMessageAction will override
+        // seen for the telephony db.
+        messageValues.put(Sms.Inbox.READ, 0);
+        messageValues.put(Sms.Inbox.SEEN, 0);
+        if (OsUtil.isAtLeastL_MR1()) {
+            messageValues.put(Sms.SUBSCRIPTION_ID, subId);
+        }
+
+        if (messages[0].getMessageClass() == android.telephony.SmsMessage.MessageClass.CLASS_0 ||
+                DebugUtils.debugClassZeroSmsEnabled()) {
+            Factory.get().getUIIntents().launchClassZeroActivity(context, messageValues);
+        } else {
+            final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(messageValues);
+            action.start();
+        }
+    }
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        LogUtil.v(TAG, "SmsReceiver.onReceive " + intent);
+        // On KLP+ we only take delivery of SMS messages in SmsDeliverReceiver.
+        if (PhoneUtils.getDefault().isSmsEnabled()) {
+            final String action = intent.getAction();
+            if (OsUtil.isSecondaryUser() &&
+                    (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action) ||
+                            // TODO: update this with the actual constant from Telephony
+                            "android.provider.Telephony.MMS_DOWNLOADED".equals(action))) {
+                postNewMessageSecondaryUserNotification();
+            } else if (!OsUtil.isAtLeastKLP()) {
+                deliverSmsIntent(context, intent);
+            }
+        }
+    }
+
+    private static class SecondaryUserNotificationState extends MessageNotificationState {
+        SecondaryUserNotificationState() {
+            super(null);
+        }
+
+        @Override
+        protected Style build(Builder builder) {
+            return null;
+        }
+
+        @Override
+        public boolean getNotificationVibrate() {
+            return true;
+        }
+    }
+
+    public static void postNewMessageSecondaryUserNotification() {
+        final Context context = Factory.get().getApplicationContext();
+        final Resources resources = context.getResources();
+        final PendingIntent pendingIntent = UIIntents.get()
+                .getPendingIntentForSecondaryUserNewMessageNotification(context);
+
+        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+        builder.setContentTitle(resources.getString(R.string.secondary_user_new_message_title))
+                .setTicker(resources.getString(R.string.secondary_user_new_message_ticker))
+                .setSmallIcon(R.drawable.ic_sms_light)
+        // Returning PRIORITY_HIGH causes L to put up a HUD notification. Without it, the ticker
+        // isn't displayed.
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setContentIntent(pendingIntent);
+
+        final NotificationCompat.BigTextStyle bigTextStyle =
+                new NotificationCompat.BigTextStyle(builder);
+        bigTextStyle.bigText(resources.getString(R.string.secondary_user_new_message_title));
+        final Notification notification = bigTextStyle.build();
+
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+
+        int defaults = Notification.DEFAULT_LIGHTS;
+        if (BugleNotifications.shouldVibrate(new SecondaryUserNotificationState())) {
+            defaults |= Notification.DEFAULT_VIBRATE;
+        }
+        notification.defaults = defaults;
+
+        notificationManager.notify(getNotificationTag(),
+                PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID, notification);
+    }
+
+    /**
+     * Cancel the notification
+     */
+    public static void cancelSecondaryUserNotification() {
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+        notificationManager.cancel(getNotificationTag(),
+                PendingIntentConstants.SMS_SECONDARY_USER_NOTIFICATION_ID);
+    }
+
+    private static String getNotificationTag() {
+        return Factory.get().getApplicationContext().getPackageName() + ":secondaryuser";
+    }
+
+    /**
+     * Compile all of the patterns we check for to ignore system SMS messages.
+     */
+    private static void compileIgnoreSmsPatterns() {
+        // Get the pattern set from GServices
+        final String smsIgnoreRegex = BugleGservices.get().getString(
+                BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX,
+                BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT);
+        if (smsIgnoreRegex != null) {
+            final String[] ignoreSmsExpressions = smsIgnoreRegex.split("\n");
+            if (ignoreSmsExpressions.length != 0) {
+                sIgnoreSmsPatterns = new ArrayList<Pattern>();
+                for (int i = 0; i < ignoreSmsExpressions.length; i++) {
+                    try {
+                        sIgnoreSmsPatterns.add(Pattern.compile(ignoreSmsExpressions[i]));
+                    } catch (PatternSyntaxException e) {
+                        LogUtil.e(TAG, "compileIgnoreSmsPatterns: Skipping bad expression: " +
+                                ignoreSmsExpressions[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the SMS messages from the specified SMS intent.
+     * @return the messages. If there is an error or the message should be ignored, return null.
+     */
+    public static android.telephony.SmsMessage[] getMessagesFromIntent(Intent intent) {
+        final android.telephony.SmsMessage[] messages = Sms.Intents.getMessagesFromIntent(intent);
+
+        // Check messages for validity
+        if (messages == null || messages.length < 1) {
+            return null;
+        }
+        // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access
+        // the methods on it although the SmsMessage itself is not null. So do this check
+        // before we do anything on the parsed SmsMessages.
+        try {
+            final String messageBody = messages[0].getDisplayMessageBody();
+            if (messageBody != null) {
+                // Compile patterns if necessary
+                if (sIgnoreSmsPatterns == null) {
+                    compileIgnoreSmsPatterns();
+                }
+                // Check against filters
+                for (final Pattern pattern : sIgnoreSmsPatterns) {
+                    if (pattern.matcher(messageBody).matches()) {
+                        return null;
+                    }
+                }
+            }
+        } catch (final NullPointerException e) {
+            LogUtil.e(TAG, "shouldIgnoreMessage: NPE inside SmsMessage");
+            return null;
+        }
+        return messages;
+    }
+
+
+    /**
+     * Check the specified SMS intent to see if the message should be ignored
+     * @return true if the message should be ignored
+     */
+    public static boolean shouldIgnoreMessage(Intent intent) {
+        return getMessagesFromIntent(intent) == null;
+    }
+}
diff --git a/src/com/android/messaging/receiver/StorageStatusReceiver.java b/src/com/android/messaging/receiver/StorageStatusReceiver.java
new file mode 100644
index 0000000..bee899c
--- /dev/null
+++ b/src/com/android/messaging/receiver/StorageStatusReceiver.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.messaging.sms.SmsStorageStatusManager;
+
+/**
+ * Receiver that listens on storage status changes
+ */
+public class StorageStatusReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) {
+            SmsStorageStatusManager.handleStorageLow();
+        } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) {
+            SmsStorageStatusManager.handleStorageOk();
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/ApnDatabase.java b/src/com/android/messaging/sms/ApnDatabase.java
new file mode 100644
index 0000000..a8d0d0c
--- /dev/null
+++ b/src/com/android/messaging/sms/ApnDatabase.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.provider.Telephony;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.collect.Lists;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * Database helper class for looking up APNs.  This database has a single table
+ * which stores the APNs that are initially created from an xml file.
+ */
+public class ApnDatabase extends SQLiteOpenHelper {
+    private static final int DB_VERSION = 3; // added sub_id columns
+
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final boolean DEBUG = false;
+
+    private static Context sContext;
+    private static ApnDatabase sApnDatabase;
+
+    private static final String APN_DATABASE_NAME = "apn.db";
+
+    /** table for carrier APN's */
+    public static final String APN_TABLE = "apn";
+
+    // APN table
+    private static final String APN_TABLE_SQL =
+            "CREATE TABLE " + APN_TABLE +
+                    "(_id INTEGER PRIMARY KEY," +
+                    Telephony.Carriers.NAME + " TEXT," +
+                    Telephony.Carriers.NUMERIC + " TEXT," +
+                    Telephony.Carriers.MCC + " TEXT," +
+                    Telephony.Carriers.MNC + " TEXT," +
+                    Telephony.Carriers.APN + " TEXT," +
+                    Telephony.Carriers.USER + " TEXT," +
+                    Telephony.Carriers.SERVER + " TEXT," +
+                    Telephony.Carriers.PASSWORD + " TEXT," +
+                    Telephony.Carriers.PROXY + " TEXT," +
+                    Telephony.Carriers.PORT + " TEXT," +
+                    Telephony.Carriers.MMSPROXY + " TEXT," +
+                    Telephony.Carriers.MMSPORT + " TEXT," +
+                    Telephony.Carriers.MMSC + " TEXT," +
+                    Telephony.Carriers.AUTH_TYPE + " INTEGER," +
+                    Telephony.Carriers.TYPE + " TEXT," +
+                    Telephony.Carriers.CURRENT + " INTEGER," +
+                    Telephony.Carriers.PROTOCOL + " TEXT," +
+                    Telephony.Carriers.ROAMING_PROTOCOL + " TEXT," +
+                    Telephony.Carriers.CARRIER_ENABLED + " BOOLEAN," +
+                    Telephony.Carriers.BEARER + " INTEGER," +
+                    Telephony.Carriers.MVNO_TYPE + " TEXT," +
+                    Telephony.Carriers.MVNO_MATCH_DATA + " TEXT," +
+                    Telephony.Carriers.SUBSCRIPTION_ID + " INTEGER DEFAULT " +
+                            ParticipantData.DEFAULT_SELF_SUB_ID + ");";
+
+    public static final String[] APN_PROJECTION = {
+            Telephony.Carriers.TYPE,            // 0
+            Telephony.Carriers.MMSC,            // 1
+            Telephony.Carriers.MMSPROXY,        // 2
+            Telephony.Carriers.MMSPORT,         // 3
+            Telephony.Carriers._ID,             // 4
+            Telephony.Carriers.CURRENT,         // 5
+            Telephony.Carriers.NUMERIC,         // 6
+            Telephony.Carriers.NAME,            // 7
+            Telephony.Carriers.MCC,             // 8
+            Telephony.Carriers.MNC,             // 9
+            Telephony.Carriers.APN,             // 10
+            Telephony.Carriers.SUBSCRIPTION_ID  // 11
+    };
+
+    public static final int COLUMN_TYPE         = 0;
+    public static final int COLUMN_MMSC         = 1;
+    public static final int COLUMN_MMSPROXY     = 2;
+    public static final int COLUMN_MMSPORT      = 3;
+    public static final int COLUMN_ID           = 4;
+    public static final int COLUMN_CURRENT      = 5;
+    public static final int COLUMN_NUMERIC      = 6;
+    public static final int COLUMN_NAME         = 7;
+    public static final int COLUMN_MCC          = 8;
+    public static final int COLUMN_MNC          = 9;
+    public static final int COLUMN_APN          = 10;
+    public static final int COLUMN_SUB_ID       = 11;
+
+    public static final String[] APN_FULL_PROJECTION = {
+            Telephony.Carriers.NAME,
+            Telephony.Carriers.MCC,
+            Telephony.Carriers.MNC,
+            Telephony.Carriers.APN,
+            Telephony.Carriers.USER,
+            Telephony.Carriers.SERVER,
+            Telephony.Carriers.PASSWORD,
+            Telephony.Carriers.PROXY,
+            Telephony.Carriers.PORT,
+            Telephony.Carriers.MMSC,
+            Telephony.Carriers.MMSPROXY,
+            Telephony.Carriers.MMSPORT,
+            Telephony.Carriers.AUTH_TYPE,
+            Telephony.Carriers.TYPE,
+            Telephony.Carriers.PROTOCOL,
+            Telephony.Carriers.ROAMING_PROTOCOL,
+            Telephony.Carriers.CARRIER_ENABLED,
+            Telephony.Carriers.BEARER,
+            Telephony.Carriers.MVNO_TYPE,
+            Telephony.Carriers.MVNO_MATCH_DATA,
+            Telephony.Carriers.CURRENT,
+            Telephony.Carriers.SUBSCRIPTION_ID,
+    };
+
+    private static final String CURRENT_SELECTION = Telephony.Carriers.CURRENT + " NOT NULL";
+
+    /**
+     * ApnDatabase is initialized asynchronously from the application.onCreate
+     * To ensure that it works in a testing environment it needs to never access the factory context
+     */
+    public static void initializeAppContext(final Context context) {
+        sContext = context;
+    }
+
+    private ApnDatabase() {
+        super(sContext, APN_DATABASE_NAME, null, DB_VERSION);
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase constructor");
+        }
+    }
+
+    public static ApnDatabase getApnDatabase() {
+        if (sApnDatabase == null) {
+            sApnDatabase = new ApnDatabase();
+        }
+        return sApnDatabase;
+    }
+
+    public static boolean doesDatabaseExist() {
+        final File dbFile = sContext.getDatabasePath(APN_DATABASE_NAME);
+        return dbFile.exists();
+    }
+
+    @Override
+    public void onCreate(final SQLiteDatabase db) {
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase onCreate");
+        }
+        // Build the table using defaults (apn info bundled with the app)
+        rebuildTables(db);
+    }
+
+    /**
+     * Get a copy of user changes in the old table
+     *
+     * @return The list of user changed apns
+     */
+    public static List<ContentValues> loadUserDataFromOldTable(final SQLiteDatabase db) {
+        Cursor cursor = null;
+        try {
+            cursor = db.query(APN_TABLE,
+                    APN_FULL_PROJECTION, CURRENT_SELECTION,
+                    null/*selectionArgs*/,
+                    null/*groupBy*/, null/*having*/, null/*orderBy*/);
+            if (cursor != null) {
+                final List<ContentValues> result = Lists.newArrayList();
+                while (cursor.moveToNext()) {
+                    final ContentValues row = cursorToValues(cursor);
+                    if (row != null) {
+                        result.add(row);
+                    }
+                }
+                return result;
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.w(TAG, "ApnDatabase.loadUserDataFromOldTable: no old user data: " + e, e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    private static final String[] ID_PROJECTION = new String[]{Telephony.Carriers._ID};
+
+    private static final String ID_SELECTION = Telephony.Carriers._ID + "=?";
+
+    /**
+     * Store use changes of old table into the new apn table
+     *
+     * @param data The user changes
+     */
+    public static void saveUserDataFromOldTable(
+            final SQLiteDatabase db, final List<ContentValues> data) {
+        if (data == null || data.size() < 1) {
+            return;
+        }
+        for (final ContentValues row : data) {
+            // Build query from the row data. It is an exact match, column by column,
+            // except the CURRENT column
+            final StringBuilder selectionBuilder = new StringBuilder();
+            final ArrayList<String> selectionArgs = Lists.newArrayList();
+            for (final String key : row.keySet()) {
+                if (!Telephony.Carriers.CURRENT.equals(key)) {
+                    if (selectionBuilder.length() > 0) {
+                        selectionBuilder.append(" AND ");
+                    }
+                    final String value = row.getAsString(key);
+                    if (TextUtils.isEmpty(value)) {
+                        selectionBuilder.append(key).append(" IS NULL");
+                    } else {
+                        selectionBuilder.append(key).append("=?");
+                        selectionArgs.add(value);
+                    }
+                }
+            }
+            Cursor cursor = null;
+            try {
+                cursor = db.query(APN_TABLE,
+                        ID_PROJECTION,
+                        selectionBuilder.toString(),
+                        selectionArgs.toArray(new String[0]),
+                        null/*groupBy*/, null/*having*/, null/*orderBy*/);
+                if (cursor != null && cursor.moveToFirst()) {
+                    db.update(APN_TABLE, row, ID_SELECTION, new String[]{cursor.getString(0)});
+                } else {
+                    // User APN does not exist, insert into the new table
+                    row.put(Telephony.Carriers.NUMERIC,
+                            PhoneUtils.canonicalizeMccMnc(
+                                    row.getAsString(Telephony.Carriers.MCC),
+                                    row.getAsString(Telephony.Carriers.MNC))
+                    );
+                    db.insert(APN_TABLE, null/*nullColumnHack*/, row);
+                }
+            } catch (final SQLiteException e) {
+                LogUtil.e(TAG, "ApnDatabase.saveUserDataFromOldTable: query error " + e, e);
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+    }
+
+    // Convert Cursor to ContentValues
+    private static ContentValues cursorToValues(final Cursor cursor) {
+        final int columnCount = cursor.getColumnCount();
+        if (columnCount > 0) {
+            final ContentValues result = new ContentValues();
+            for (int i = 0; i < columnCount; i++) {
+                final String name = cursor.getColumnName(i);
+                final String value = cursor.getString(i);
+                result.put(name, value);
+            }
+            return result;
+        }
+        return null;
+    }
+
+    @Override
+    public void onOpen(final SQLiteDatabase db) {
+        super.onOpen(db);
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase onOpen");
+        }
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase close");
+        }
+    }
+
+    private void rebuildTables(final SQLiteDatabase db) {
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase rebuildTables");
+        }
+        db.execSQL("DROP TABLE IF EXISTS " + APN_TABLE + ";");
+        db.execSQL(APN_TABLE_SQL);
+        loadApnTable(db);
+    }
+
+    @Override
+    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase onUpgrade");
+        }
+        rebuildTables(db);
+    }
+
+    @Override
+    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        if (DEBUG) {
+            LogUtil.d(TAG, "ApnDatabase onDowngrade");
+        }
+        rebuildTables(db);
+    }
+
+    /**
+     * Load APN table from app resources
+     */
+    private static void loadApnTable(final SQLiteDatabase db) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "ApnDatabase loadApnTable");
+        }
+        final Resources r = sContext.getResources();
+        final XmlResourceParser parser = r.getXml(R.xml.apns);
+        final ApnsXmlProcessor processor = ApnsXmlProcessor.get(parser);
+        processor.setApnHandler(new ApnsXmlProcessor.ApnHandler() {
+            @Override
+            public void process(final ContentValues apnValues) {
+                db.insert(APN_TABLE, null/*nullColumnHack*/, apnValues);
+            }
+        });
+        try {
+            processor.process();
+        } catch (final Exception e) {
+            Log.e(TAG, "Got exception while loading APN database.", e);
+        } finally {
+            parser.close();
+        }
+    }
+
+    public static void forceBuildAndLoadApnTables() {
+        final SQLiteDatabase db = getApnDatabase().getWritableDatabase();
+        db.execSQL("DROP TABLE IF EXISTS " + APN_TABLE);
+        // Table(s) always need for JB MR1 for APN support for MMS because JB MR1 throws
+        // a SecurityException when trying to access the carriers table (which holds the
+        // APNs). Some JB MR2 devices also throw the security exception, so we're building
+        // the table for JB MR2, too.
+        db.execSQL(APN_TABLE_SQL);
+
+        loadApnTable(db);
+    }
+
+    /**
+     * Clear all tables
+     */
+    public static void clearTables() {
+        final SQLiteDatabase db = getApnDatabase().getWritableDatabase();
+        db.execSQL("DROP TABLE IF EXISTS " + APN_TABLE);
+        db.execSQL(APN_TABLE_SQL);
+    }
+}
diff --git a/src/com/android/messaging/sms/ApnsXmlProcessor.java b/src/com/android/messaging/sms/ApnsXmlProcessor.java
new file mode 100644
index 0000000..976896c
--- /dev/null
+++ b/src/com/android/messaging/sms/ApnsXmlProcessor.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.ContentValues;
+import android.provider.Telephony;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.collect.Maps;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Map;
+
+/*
+ * XML processor for the following files:
+ * 1. res/xml/apns.xml
+ * 2. res/xml/mms_config.xml (or related overlay files)
+ */
+class ApnsXmlProcessor {
+    public interface ApnHandler {
+        public void process(ContentValues apnValues);
+    }
+
+    public interface MmsConfigHandler {
+        public void process(String mccMnc, String key, String value, String type);
+    }
+
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final Map<String, String> APN_ATTRIBUTE_MAP = Maps.newHashMap();
+    static {
+        APN_ATTRIBUTE_MAP.put("mcc", Telephony.Carriers.MCC);
+        APN_ATTRIBUTE_MAP.put("mnc", Telephony.Carriers.MNC);
+        APN_ATTRIBUTE_MAP.put("carrier", Telephony.Carriers.NAME);
+        APN_ATTRIBUTE_MAP.put("apn", Telephony.Carriers.APN);
+        APN_ATTRIBUTE_MAP.put("mmsc", Telephony.Carriers.MMSC);
+        APN_ATTRIBUTE_MAP.put("mmsproxy", Telephony.Carriers.MMSPROXY);
+        APN_ATTRIBUTE_MAP.put("mmsport", Telephony.Carriers.MMSPORT);
+        APN_ATTRIBUTE_MAP.put("type", Telephony.Carriers.TYPE);
+        APN_ATTRIBUTE_MAP.put("user", Telephony.Carriers.USER);
+        APN_ATTRIBUTE_MAP.put("password", Telephony.Carriers.PASSWORD);
+        APN_ATTRIBUTE_MAP.put("authtype", Telephony.Carriers.AUTH_TYPE);
+        APN_ATTRIBUTE_MAP.put("mvno_match_data", Telephony.Carriers.MVNO_MATCH_DATA);
+        APN_ATTRIBUTE_MAP.put("mvno_type", Telephony.Carriers.MVNO_TYPE);
+        APN_ATTRIBUTE_MAP.put("protocol", Telephony.Carriers.PROTOCOL);
+        APN_ATTRIBUTE_MAP.put("bearer", Telephony.Carriers.BEARER);
+        APN_ATTRIBUTE_MAP.put("server", Telephony.Carriers.SERVER);
+        APN_ATTRIBUTE_MAP.put("roaming_protocol", Telephony.Carriers.ROAMING_PROTOCOL);
+        APN_ATTRIBUTE_MAP.put("proxy", Telephony.Carriers.PROXY);
+        APN_ATTRIBUTE_MAP.put("port", Telephony.Carriers.PORT);
+        APN_ATTRIBUTE_MAP.put("carrier_enabled", Telephony.Carriers.CARRIER_ENABLED);
+    }
+
+    private static final String TAG_APNS = "apns";
+    private static final String TAG_APN = "apn";
+    private static final String TAG_MMS_CONFIG = "mms_config";
+
+    // Handler to process one apn
+    private ApnHandler mApnHandler;
+    // Handler to process one mms_config key/value pair
+    private MmsConfigHandler mMmsConfigHandler;
+
+    private final StringBuilder mLogStringBuilder = new StringBuilder();
+
+    private final XmlPullParser mInputParser;
+
+    private ApnsXmlProcessor(XmlPullParser parser) {
+        mInputParser = parser;
+        mApnHandler = null;
+        mMmsConfigHandler = null;
+    }
+
+    public static ApnsXmlProcessor get(XmlPullParser parser) {
+        Assert.notNull(parser);
+        return new ApnsXmlProcessor(parser);
+    }
+
+    public ApnsXmlProcessor setApnHandler(ApnHandler handler) {
+        mApnHandler = handler;
+        return this;
+    }
+
+    public ApnsXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) {
+        mMmsConfigHandler = handler;
+        return this;
+    }
+
+    /**
+     * Move XML parser forward to next event type or the end of doc
+     *
+     * @param eventType
+     * @return The final event type we meet
+     * @throws XmlPullParserException
+     * @throws IOException
+     */
+    private int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException {
+        for (;;) {
+            int nextEvent = mInputParser.next();
+            if (nextEvent == eventType
+                    || nextEvent == XmlPullParser.END_DOCUMENT) {
+                return nextEvent;
+            }
+        }
+    }
+
+    public void process() {
+        try {
+            // Find the first element
+            if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("ApnsXmlProcessor: expecting start tag @"
+                        + xmlParserDebugContext());
+            }
+            // A single ContentValues object for holding the parsing result of
+            // an apn element
+            final ContentValues values = new ContentValues();
+            String tagName = mInputParser.getName();
+            // Top level tag can be "apns" (apns.xml)
+            // or "mms_config" (mms_config.xml)
+            if (TAG_APNS.equals(tagName)) {
+                // For "apns", there could be "apn" or both "apn" and "mms_config"
+                for (;;) {
+                    if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
+                        break;
+                    }
+                    tagName = mInputParser.getName();
+                    if (TAG_APN.equals(tagName)) {
+                        processApn(values);
+                    } else if (TAG_MMS_CONFIG.equals(tagName)) {
+                        processMmsConfig();
+                    }
+                }
+            } else if (TAG_MMS_CONFIG.equals(tagName)) {
+                // mms_config.xml resource
+                processMmsConfig();
+            }
+        } catch (IOException e) {
+            LogUtil.e(TAG, "ApnsXmlProcessor: I/O failure " + e, e);
+        } catch (XmlPullParserException e) {
+            LogUtil.e(TAG, "ApnsXmlProcessor: parsing failure " + e, e);
+        }
+    }
+
+    private Integer parseInt(String text, Integer defaultValue, String logHint) {
+        Integer value = defaultValue;
+        try {
+            value = Integer.parseInt(text);
+        } catch (Exception e) {
+            LogUtil.e(TAG,
+                    "Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
+        }
+        return value;
+    }
+
+    private Boolean parseBoolean(String text, Boolean defaultValue, String logHint) {
+        Boolean value = defaultValue;
+        try {
+            value = Boolean.parseBoolean(text);
+        } catch (Exception e) {
+            LogUtil.e(TAG,
+                    "Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
+        }
+        return value;
+    }
+
+    private static String xmlParserEventString(int event) {
+        switch (event) {
+            case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
+            case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT";
+            case XmlPullParser.START_TAG: return "START_TAG";
+            case XmlPullParser.END_TAG: return "END_TAG";
+            case XmlPullParser.TEXT: return "TEXT";
+        }
+        return Integer.toString(event);
+    }
+
+    /**
+     * @return The debugging information of the parser's current position
+     */
+    private String xmlParserDebugContext() {
+        mLogStringBuilder.setLength(0);
+        if (mInputParser != null) {
+            try {
+                final int eventType = mInputParser.getEventType();
+                mLogStringBuilder.append(xmlParserEventString(eventType));
+                if (eventType == XmlPullParser.START_TAG
+                        || eventType == XmlPullParser.END_TAG
+                        || eventType == XmlPullParser.TEXT) {
+                    mLogStringBuilder.append('<').append(mInputParser.getName());
+                    for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
+                        mLogStringBuilder.append(' ')
+                            .append(mInputParser.getAttributeName(i))
+                            .append('=')
+                            .append(mInputParser.getAttributeValue(i));
+                    }
+                    mLogStringBuilder.append("/>");
+                }
+                return mLogStringBuilder.toString();
+            } catch (XmlPullParserException e) {
+                LogUtil.e(TAG, "xmlParserDebugContext: " + e, e);
+            }
+        }
+        return "Unknown";
+    }
+
+    /**
+     * Process one apn
+     *
+     * @param apnValues Where we store the parsed apn
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    private void processApn(ContentValues apnValues) throws IOException, XmlPullParserException {
+        Assert.notNull(apnValues);
+        apnValues.clear();
+        // Collect all the attributes
+        for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
+            final String key = APN_ATTRIBUTE_MAP.get(mInputParser.getAttributeName(i));
+            if (key != null) {
+                apnValues.put(key, mInputParser.getAttributeValue(i));
+            }
+        }
+        // Set numeric to be canonicalized mcc/mnc like "310120", always 6 digits
+        final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc(
+                apnValues.getAsString(Telephony.Carriers.MCC),
+                apnValues.getAsString(Telephony.Carriers.MNC));
+        apnValues.put(Telephony.Carriers.NUMERIC, canonicalMccMnc);
+        // Some of the values should not be string type, converting them to desired types
+        final String authType = apnValues.getAsString(Telephony.Carriers.AUTH_TYPE);
+        if (authType != null) {
+            apnValues.put(Telephony.Carriers.AUTH_TYPE, parseInt(authType, -1, "apn authtype"));
+        }
+        final String carrierEnabled = apnValues.getAsString(Telephony.Carriers.CARRIER_ENABLED);
+        if (carrierEnabled != null) {
+            apnValues.put(Telephony.Carriers.CARRIER_ENABLED,
+                    parseBoolean(carrierEnabled, null, "apn carrierEnabled"));
+        }
+        final String bearer = apnValues.getAsString(Telephony.Carriers.BEARER);
+        if (bearer != null) {
+            apnValues.put(Telephony.Carriers.BEARER, parseInt(bearer, 0, "apn bearer"));
+        }
+        // We are at the end tag
+        if (mInputParser.next() != XmlPullParser.END_TAG) {
+            throw new XmlPullParserException("Apn: expecting end tag @"
+                    + xmlParserDebugContext());
+        }
+        // We are done parsing one APN, call the handler
+        if (mApnHandler != null) {
+            mApnHandler.process(apnValues);
+        }
+    }
+
+    /**
+     * Process one mms_config.
+     *
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    private void processMmsConfig()
+            throws IOException, XmlPullParserException {
+        // Get the mcc and mnc attributes
+        final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc(
+                mInputParser.getAttributeValue(null, "mcc"),
+                mInputParser.getAttributeValue(null, "mnc"));
+        // We are at the start tag
+        for (;;) {
+            int nextEvent;
+            // Skipping spaces
+            while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT) {
+            }
+            if (nextEvent == XmlPullParser.START_TAG) {
+                // Parse one mms config key/value
+                processMmsConfigKeyValue(canonicalMccMnc);
+            } else if (nextEvent == XmlPullParser.END_TAG) {
+                break;
+            } else {
+                throw new XmlPullParserException("MmsConfig: expecting start or end tag @"
+                        + xmlParserDebugContext());
+            }
+        }
+    }
+
+    /**
+     * Process one mms_config key/value pair
+     *
+     * @param mccMnc The mcc and mnc of this mms_config
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    private void processMmsConfigKeyValue(String mccMnc)
+            throws IOException, XmlPullParserException {
+        final String key = mInputParser.getAttributeValue(null, "name");
+        // We are at the start tag, the name of the tag is the type
+        // e.g. <int name="key">value</int>
+        final String type = mInputParser.getName();
+        int nextEvent = mInputParser.next();
+        String value = null;
+        if (nextEvent == XmlPullParser.TEXT) {
+            value = mInputParser.getText();
+            nextEvent = mInputParser.next();
+        }
+        if (nextEvent != XmlPullParser.END_TAG) {
+            throw new XmlPullParserException("ApnsXmlProcessor: expecting end tag @"
+                    + xmlParserDebugContext());
+        }
+        // We are done parsing one mms_config key/value, call the handler
+        if (mMmsConfigHandler != null) {
+            mMmsConfigHandler.process(mccMnc, key, value, type);
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/BugleApnSettingsLoader.java b/src/com/android/messaging/sms/BugleApnSettingsLoader.java
new file mode 100644
index 0000000..36820ff
--- /dev/null
+++ b/src/com/android/messaging/sms/BugleApnSettingsLoader.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.Telephony;
+import androidx.appcompat.mms.ApnSettingsLoader;
+import androidx.appcompat.mms.MmsManager;
+import android.text.TextUtils;
+import android.util.SparseArray;
+
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * APN loader for default SMS SIM
+ *
+ * This loader tries to load APNs from 3 sources in order:
+ * 1. Gservices setting
+ * 2. System APN table
+ * 3. Local APN table
+ */
+public class BugleApnSettingsLoader implements ApnSettingsLoader {
+    /**
+     * The base implementation of an APN
+     */
+    private static class BaseApn implements Apn {
+        /**
+         * Create a base APN from parameters
+         *
+         * @param typesIn the APN type field
+         * @param mmscIn the APN mmsc field
+         * @param proxyIn the APN mmsproxy field
+         * @param portIn the APN mmsport field
+         * @return an instance of base APN, or null if any of the parameter is invalid
+         */
+        public static BaseApn from(final String typesIn, final String mmscIn, final String proxyIn,
+                final String portIn) {
+            if (!isValidApnType(trimWithNullCheck(typesIn), APN_TYPE_MMS)) {
+                return null;
+            }
+            String mmsc = trimWithNullCheck(mmscIn);
+            if (TextUtils.isEmpty(mmsc)) {
+                return null;
+            }
+            mmsc = trimV4AddrZeros(mmsc);
+            try {
+                new URI(mmsc);
+            } catch (final URISyntaxException e) {
+                return null;
+            }
+            String mmsProxy = trimWithNullCheck(proxyIn);
+            int mmsProxyPort = 80;
+            if (!TextUtils.isEmpty(mmsProxy)) {
+                mmsProxy = trimV4AddrZeros(mmsProxy);
+                final String portString = trimWithNullCheck(portIn);
+                if (portString != null) {
+                    try {
+                        mmsProxyPort = Integer.parseInt(portString);
+                    } catch (final NumberFormatException e) {
+                        // Ignore, just use 80 to try
+                    }
+                }
+            }
+            return new BaseApn(mmsc, mmsProxy, mmsProxyPort);
+        }
+
+        private final String mMmsc;
+        private final String mMmsProxy;
+        private final int mMmsProxyPort;
+
+        public BaseApn(final String mmsc, final String proxy, final int port) {
+            mMmsc = mmsc;
+            mMmsProxy = proxy;
+            mMmsProxyPort = port;
+        }
+
+        @Override
+        public String getMmsc() {
+            return mMmsc;
+        }
+
+        @Override
+        public String getMmsProxy() {
+            return mMmsProxy;
+        }
+
+        @Override
+        public int getMmsProxyPort() {
+            return mMmsProxyPort;
+        }
+
+        @Override
+        public void setSuccess() {
+            // Do nothing
+        }
+
+        public boolean equals(final BaseApn other) {
+            return TextUtils.equals(mMmsc, other.getMmsc()) &&
+                    TextUtils.equals(mMmsProxy, other.getMmsProxy()) &&
+                    mMmsProxyPort == other.getMmsProxyPort();
+        }
+    }
+
+    /**
+     * The APN represented by the local APN table row
+     */
+    private static class DatabaseApn implements Apn {
+        private static final ContentValues CURRENT_NULL_VALUE;
+        private static final ContentValues CURRENT_SET_VALUE;
+        static {
+            CURRENT_NULL_VALUE = new ContentValues(1);
+            CURRENT_NULL_VALUE.putNull(Telephony.Carriers.CURRENT);
+            CURRENT_SET_VALUE = new ContentValues(1);
+            CURRENT_SET_VALUE.put(Telephony.Carriers.CURRENT, "1"); // 1 for auto selected APN
+        }
+        private static final String CLEAR_UPDATE_SELECTION = Telephony.Carriers.CURRENT + " =?";
+        private static final String[] CLEAR_UPDATE_SELECTION_ARGS = new String[] { "1" };
+        private static final String SET_UPDATE_SELECTION = Telephony.Carriers._ID + " =?";
+
+        /**
+         * Create an APN loaded from local database
+         *
+         * @param apns the in-memory APN list
+         * @param typesIn the APN type field
+         * @param mmscIn the APN mmsc field
+         * @param proxyIn the APN mmsproxy field
+         * @param portIn the APN mmsport field
+         * @param rowId the APN's row ID in database
+         * @param current the value of CURRENT column in database
+         * @return an in-memory APN instance for database APN row, null if parameter invalid
+         */
+        public static DatabaseApn from(final List<Apn> apns, final String typesIn,
+                final String mmscIn, final String proxyIn, final String portIn,
+                final long rowId, final int current) {
+            if (apns == null) {
+                return null;
+            }
+            final BaseApn base = BaseApn.from(typesIn, mmscIn, proxyIn, portIn);
+            if (base == null) {
+                return null;
+            }
+            for (final ApnSettingsLoader.Apn apn : apns) {
+                if (apn instanceof DatabaseApn && ((DatabaseApn) apn).equals(base)) {
+                    return null;
+                }
+            }
+            return new DatabaseApn(apns, base, rowId, current);
+        }
+
+        private final List<Apn> mApns;
+        private final BaseApn mBase;
+        private final long mRowId;
+        private int mCurrent;
+
+        public DatabaseApn(final List<Apn> apns, final BaseApn base, final long rowId,
+                final int current) {
+            mApns = apns;
+            mBase = base;
+            mRowId = rowId;
+            mCurrent = current;
+        }
+
+        @Override
+        public String getMmsc() {
+            return mBase.getMmsc();
+        }
+
+        @Override
+        public String getMmsProxy() {
+            return mBase.getMmsProxy();
+        }
+
+        @Override
+        public int getMmsProxyPort() {
+            return mBase.getMmsProxyPort();
+        }
+
+        @Override
+        public void setSuccess() {
+            moveToListHead();
+            setCurrentInDatabase();
+        }
+
+        /**
+         * Try to move this APN to the head of in-memory list
+         */
+        private void moveToListHead() {
+            // If this is being marked as a successful APN, move it to the top of the list so
+            // next time it will be tried first
+            boolean moved = false;
+            synchronized (mApns) {
+                if (mApns.get(0) != this) {
+                    mApns.remove(this);
+                    mApns.add(0, this);
+                    moved = true;
+                }
+            }
+            if (moved) {
+                LogUtil.d(LogUtil.BUGLE_TAG, "Set APN ["
+                        + "MMSC=" + getMmsc() + ", "
+                        + "PROXY=" + getMmsProxy() + ", "
+                        + "PORT=" + getMmsProxyPort() + "] to be first");
+            }
+        }
+
+        /**
+         * Try to set the APN to be CURRENT in its database table
+         */
+        private void setCurrentInDatabase() {
+            synchronized (this) {
+                if (mCurrent > 0) {
+                    // Already current
+                    return;
+                }
+                mCurrent = 1;
+            }
+            LogUtil.d(LogUtil.BUGLE_TAG, "Set APN @" + mRowId + " to be CURRENT in local db");
+            final SQLiteDatabase database = ApnDatabase.getApnDatabase().getWritableDatabase();
+            database.beginTransaction();
+            try {
+                // clear the previous current=1 apn
+                // we don't clear current=2 apn since it is manually selected by user
+                // and we should not override it.
+                database.update(ApnDatabase.APN_TABLE, CURRENT_NULL_VALUE,
+                        CLEAR_UPDATE_SELECTION, CLEAR_UPDATE_SELECTION_ARGS);
+                // set this one to be current (1)
+                database.update(ApnDatabase.APN_TABLE, CURRENT_SET_VALUE, SET_UPDATE_SELECTION,
+                        new String[] { Long.toString(mRowId) });
+                database.setTransactionSuccessful();
+            } finally {
+                database.endTransaction();
+            }
+        }
+
+        public boolean equals(final BaseApn other) {
+            if (other == null) {
+                return false;
+            }
+            return mBase.equals(other);
+        }
+    }
+
+    /**
+     * APN_TYPE_ALL is a special type to indicate that this APN entry can
+     * service all data connections.
+     */
+    public static final String APN_TYPE_ALL = "*";
+    /** APN type for MMS traffic */
+    public static final String APN_TYPE_MMS = "mms";
+
+    private static final String[] APN_PROJECTION_SYSTEM = {
+            Telephony.Carriers.TYPE,
+            Telephony.Carriers.MMSC,
+            Telephony.Carriers.MMSPROXY,
+            Telephony.Carriers.MMSPORT,
+    };
+    private static final String[] APN_PROJECTION_LOCAL = {
+            Telephony.Carriers.TYPE,
+            Telephony.Carriers.MMSC,
+            Telephony.Carriers.MMSPROXY,
+            Telephony.Carriers.MMSPORT,
+            Telephony.Carriers.CURRENT,
+            Telephony.Carriers._ID,
+    };
+    private static final int COLUMN_TYPE         = 0;
+    private static final int COLUMN_MMSC         = 1;
+    private static final int COLUMN_MMSPROXY     = 2;
+    private static final int COLUMN_MMSPORT      = 3;
+    private static final int COLUMN_CURRENT      = 4;
+    private static final int COLUMN_ID           = 5;
+
+    private static final String SELECTION_APN = Telephony.Carriers.APN + "=?";
+    private static final String SELECTION_CURRENT = Telephony.Carriers.CURRENT + " IS NOT NULL";
+    private static final String SELECTION_NUMERIC = Telephony.Carriers.NUMERIC + "=?";
+    private static final String ORDER_BY = Telephony.Carriers.CURRENT + " DESC";
+
+    private final Context mContext;
+
+    // Cached APNs for subIds
+    private final SparseArray<List<ApnSettingsLoader.Apn>> mApnsCache;
+
+    public BugleApnSettingsLoader(final Context context) {
+        mContext = context;
+        mApnsCache = new SparseArray<>();
+    }
+
+    @Override
+    public List<ApnSettingsLoader.Apn> get(final String apnName) {
+        final int subId = PhoneUtils.getDefault().getEffectiveSubId(
+                ParticipantData.DEFAULT_SELF_SUB_ID);
+        List<ApnSettingsLoader.Apn> apns;
+        boolean didLoad = false;
+        synchronized (this) {
+            apns = mApnsCache.get(subId);
+            if (apns == null) {
+                apns = new ArrayList<>();
+                mApnsCache.put(subId, apns);
+                loadLocked(subId, apnName, apns);
+                didLoad = true;
+            }
+        }
+        if (didLoad) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Loaded " + apns.size() + " APNs");
+        }
+        return apns;
+    }
+
+    private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
+        // Try Gservices first
+        loadFromGservices(apns);
+        if (apns.size() > 0) {
+            return;
+        }
+        // Try system APN table
+        loadFromSystem(subId, apnName, apns);
+        if (apns.size() > 0) {
+            return;
+        }
+        // Try local APN table
+        loadFromLocalDatabase(apnName, apns);
+        if (apns.size() <= 0) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Failed to load any APN");
+        }
+    }
+
+    /**
+     * Load from Gservices if APN setting is set in Gservices
+     *
+     * @param apns the list used to return results
+     */
+    private void loadFromGservices(final List<Apn> apns) {
+        final BugleGservices gservices = BugleGservices.get();
+        final String mmsc = gservices.getString(BugleGservicesKeys.MMS_MMSC, null);
+        if (TextUtils.isEmpty(mmsc)) {
+            return;
+        }
+        LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from gservices");
+        final String proxy = gservices.getString(BugleGservicesKeys.MMS_PROXY_ADDRESS, null);
+        final int port = gservices.getInt(BugleGservicesKeys.MMS_PROXY_PORT, -1);
+        final Apn apn = BaseApn.from("mms", mmsc, proxy, Integer.toString(port));
+        if (apn != null) {
+            apns.add(apn);
+        }
+    }
+
+    /**
+     * Load matching APNs from telephony provider.
+     * We try different combinations of the query to work around some platform quirks.
+     *
+     * @param subId the SIM subId
+     * @param apnName the APN name to match
+     * @param apns the list used to return results
+     */
+    private void loadFromSystem(final int subId, final String apnName, final List<Apn> apns) {
+        Uri uri;
+        if (OsUtil.isAtLeastL_MR1() && subId != MmsManager.DEFAULT_SUB_ID) {
+            uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId);
+        } else {
+            uri = Telephony.Carriers.CONTENT_URI;
+        }
+        Cursor cursor = null;
+        try {
+            for (; ; ) {
+                // Try different combinations of queries. Some would work on some platforms.
+                // So we query each combination until we find one returns non-empty result.
+                cursor = querySystem(uri, true/*checkCurrent*/, apnName);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, false/*checkCurrent*/, apnName);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, true/*checkCurrent*/, null/*apnName*/);
+                if (cursor != null) {
+                    break;
+                }
+                cursor = querySystem(uri, false/*checkCurrent*/, null/*apnName*/);
+                break;
+            }
+        } catch (final SecurityException e) {
+            // Can't access platform APN table, return directly
+            return;
+        }
+        if (cursor == null) {
+            return;
+        }
+        try {
+            if (cursor.moveToFirst()) {
+                final ApnSettingsLoader.Apn apn = BaseApn.from(
+                        cursor.getString(COLUMN_TYPE),
+                        cursor.getString(COLUMN_MMSC),
+                        cursor.getString(COLUMN_MMSPROXY),
+                        cursor.getString(COLUMN_MMSPORT));
+                if (apn != null) {
+                    apns.add(apn);
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Query system APN table
+     *
+     * @param uri The APN query URL to use
+     * @param checkCurrent If add "CURRENT IS NOT NULL" condition
+     * @param apnName The optional APN name for query condition
+     * @return A cursor of the query result. If a cursor is returned as not null, it is
+     *         guaranteed to contain at least one row.
+     */
+    private Cursor querySystem(final Uri uri, final boolean checkCurrent, String apnName) {
+        LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from system, "
+                + "checkCurrent=" + checkCurrent + " apnName=" + apnName);
+        final StringBuilder selectionBuilder = new StringBuilder();
+        String[] selectionArgs = null;
+        if (checkCurrent) {
+            selectionBuilder.append(SELECTION_CURRENT);
+        }
+        apnName = trimWithNullCheck(apnName);
+        if (!TextUtils.isEmpty(apnName)) {
+            if (selectionBuilder.length() > 0) {
+                selectionBuilder.append(" AND ");
+            }
+            selectionBuilder.append(SELECTION_APN);
+            selectionArgs = new String[] { apnName };
+        }
+        try {
+            final Cursor cursor = SqliteWrapper.query(
+                    mContext,
+                    mContext.getContentResolver(),
+                    uri,
+                    APN_PROJECTION_SYSTEM,
+                    selectionBuilder.toString(),
+                    selectionArgs,
+                    null/*sortOrder*/);
+            if (cursor == null || cursor.getCount() < 1) {
+                if (cursor != null) {
+                    cursor.close();
+                }
+                LogUtil.w(LogUtil.BUGLE_TAG, "Query " + uri + " with apn " + apnName + " and "
+                        + (checkCurrent ? "checking CURRENT" : "not checking CURRENT")
+                        + " returned empty");
+                return null;
+            }
+            return cursor;
+        } catch (final SQLiteException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "APN table query exception: " + e);
+        } catch (final SecurityException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Platform restricts APN table access: " + e);
+            throw e;
+        }
+        return null;
+    }
+
+    /**
+     * Load matching APNs from local APN table.
+     * We try both using the APN name and not using the APN name.
+     *
+     * @param apnName the APN name
+     * @param apns the list of results to return
+     */
+    private void loadFromLocalDatabase(final String apnName, final List<Apn> apns) {
+        LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from local APN table");
+        final SQLiteDatabase database = ApnDatabase.getApnDatabase().getWritableDatabase();
+        final String mccMnc = PhoneUtils.getMccMncString(PhoneUtils.getDefault().getMccMnc());
+        Cursor cursor = null;
+        cursor = queryLocalDatabase(database, mccMnc, apnName);
+        if (cursor == null) {
+            cursor = queryLocalDatabase(database, mccMnc, null/*apnName*/);
+        }
+        if (cursor == null) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Could not find any APN in local table");
+            return;
+        }
+        try {
+            while (cursor.moveToNext()) {
+                final Apn apn = DatabaseApn.from(apns,
+                        cursor.getString(COLUMN_TYPE),
+                        cursor.getString(COLUMN_MMSC),
+                        cursor.getString(COLUMN_MMSPROXY),
+                        cursor.getString(COLUMN_MMSPORT),
+                        cursor.getLong(COLUMN_ID),
+                        cursor.getInt(COLUMN_CURRENT));
+                if (apn != null) {
+                    apns.add(apn);
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Make a query of local APN table based on MCC/MNC and APN name, sorted by CURRENT
+     * column in descending order
+     *
+     * @param db the local database
+     * @param numeric the MCC/MNC string
+     * @param apnName the optional APN name to match
+     * @return the cursor of the query, null if no result
+     */
+    private static Cursor queryLocalDatabase(final SQLiteDatabase db, final String numeric,
+            final String apnName) {
+        final String selection;
+        final String[] selectionArgs;
+        if (TextUtils.isEmpty(apnName)) {
+            selection = SELECTION_NUMERIC;
+            selectionArgs = new String[] { numeric };
+        } else {
+            selection = SELECTION_NUMERIC + " AND " + SELECTION_APN;
+            selectionArgs = new String[] { numeric, apnName };
+        }
+        Cursor cursor = null;
+        try {
+            cursor = db.query(ApnDatabase.APN_TABLE, APN_PROJECTION_LOCAL, selection, selectionArgs,
+                    null/*groupBy*/, null/*having*/, ORDER_BY, null/*limit*/);
+        } catch (final SQLiteException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Local APN table does not exist. Try rebuilding.", e);
+            ApnDatabase.forceBuildAndLoadApnTables();
+            cursor = db.query(ApnDatabase.APN_TABLE, APN_PROJECTION_LOCAL, selection, selectionArgs,
+                    null/*groupBy*/, null/*having*/, ORDER_BY, null/*limit*/);
+        }
+        if (cursor == null || cursor.getCount() < 1) {
+            if (cursor != null) {
+                cursor.close();
+            }
+            LogUtil.w(LogUtil.BUGLE_TAG, "Query local APNs with apn " + apnName
+                    + " returned empty");
+            return null;
+        }
+        return cursor;
+    }
+
+    private static String trimWithNullCheck(final String value) {
+        return value != null ? value.trim() : null;
+    }
+
+    /**
+     * Trim leading zeros from IPv4 address strings
+     * Our base libraries will interpret that as octel..
+     * Must leave non v4 addresses and host names alone.
+     * For example, 192.168.000.010 -> 192.168.0.10
+     *
+     * @param addr a string representing an ip addr
+     * @return a string propertly trimmed
+     */
+    private static String trimV4AddrZeros(final String addr) {
+        if (addr == null) {
+            return null;
+        }
+        final String[] octets = addr.split("\\.");
+        if (octets.length != 4) {
+            return addr;
+        }
+        final StringBuilder builder = new StringBuilder(16);
+        String result = null;
+        for (int i = 0; i < 4; i++) {
+            try {
+                if (octets[i].length() > 3) {
+                    return addr;
+                }
+                builder.append(Integer.parseInt(octets[i]));
+            } catch (final NumberFormatException e) {
+                return addr;
+            }
+            if (i < 3) {
+                builder.append('.');
+            }
+        }
+        result = builder.toString();
+        return result;
+    }
+
+    /**
+     * Check if the APN contains the APN type we want
+     *
+     * @param types The string encodes a list of supported types
+     * @param requestType The type we want
+     * @return true if the input types string contains the requestType
+     */
+    public static boolean isValidApnType(final String types, final String requestType) {
+        // If APN type is unspecified, assume APN_TYPE_ALL.
+        if (TextUtils.isEmpty(types)) {
+            return true;
+        }
+        for (final String t : types.split(",")) {
+            if (t.equals(requestType) || t.equals(APN_TYPE_ALL)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get the ID of first APN to try
+     */
+    public static String getFirstTryApn(final SQLiteDatabase database, final String mccMnc) {
+        String key = null;
+        Cursor cursor = null;
+        try {
+            cursor = queryLocalDatabase(database, mccMnc, null/*apnName*/);
+            if (cursor.moveToFirst()) {
+                key = cursor.getString(ApnDatabase.COLUMN_ID);
+            }
+        } catch (final Exception e) {
+            // Nothing to do
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return key;
+    }
+}
diff --git a/src/com/android/messaging/sms/BugleCarrierConfigValuesLoader.java b/src/com/android/messaging/sms/BugleCarrierConfigValuesLoader.java
new file mode 100644
index 0000000..51f17cb
--- /dev/null
+++ b/src/com/android/messaging/sms/BugleCarrierConfigValuesLoader.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
+import androidx.appcompat.mms.CarrierConfigValuesLoader;
+import android.util.SparseArray;
+
+import com.android.messaging.R;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Carrier configuration loader
+ *
+ * Loader tries to load from resources. If there is MMS API available, also
+ * load from system.
+ */
+public class BugleCarrierConfigValuesLoader implements CarrierConfigValuesLoader {
+    /*
+     * Key types
+     */
+    public static final String KEY_TYPE_INT = "int";
+    public static final String KEY_TYPE_BOOL = "bool";
+    public static final String KEY_TYPE_STRING = "string";
+
+    private final Context mContext;
+
+    // Cached values for subIds
+    private final SparseArray<Bundle> mValuesCache;
+
+    public BugleCarrierConfigValuesLoader(final Context context) {
+        mContext = context;
+        mValuesCache = new SparseArray<>();
+    }
+
+    @Override
+    public Bundle get(int subId) {
+        subId = PhoneUtils.getDefault().getEffectiveSubId(subId);
+        Bundle values;
+        String loadSource = null;
+        synchronized (this) {
+            values = mValuesCache.get(subId);
+            if (values == null) {
+                values = new Bundle();
+                mValuesCache.put(subId, values);
+                loadSource = loadLocked(subId, values);
+            }
+        }
+        if (loadSource != null) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Carrier configs loaded: " + values
+                    + " from " + loadSource + " for subId=" + subId);
+        }
+        return values;
+    }
+
+    /**
+     * Clear the cache for reloading
+     */
+    public void reset() {
+        synchronized (this) {
+            mValuesCache.clear();
+        }
+    }
+
+    /**
+     * Loading carrier config values
+     *
+     * @param subId which SIM to load for
+     * @param values the result to add to
+     * @return the source of the config, could be "resources" or "resources+system"
+     */
+    private String loadLocked(final int subId, final Bundle values) {
+        // Load from resources in earlier platform
+        loadFromResources(subId, values);
+        if (OsUtil.isAtLeastL()) {
+            // Load from system to override if system API exists
+            loadFromSystem(subId, values);
+            return "resources+system";
+        }
+        return "resources";
+    }
+
+    /**
+     * Load from system, using MMS API
+     *
+     * @param subId which SIM to load for
+     * @param values the result to add to
+     */
+    private static void loadFromSystem(final int subId, final Bundle values) {
+        try {
+            final Bundle systemValues =
+                    PhoneUtils.get(subId).getSmsManager().getCarrierConfigValues();
+            if (systemValues != null) {
+                values.putAll(systemValues);
+            }
+        } catch (final Exception e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Calling system getCarrierConfigValues exception", e);
+        }
+    }
+
+    /**
+     * Load from SIM-dependent resources
+     *
+     * @param subId which SIM to load for
+     * @param values the result to add to
+     */
+    private void loadFromResources(final int subId, final Bundle values) {
+        // Get a subscription-dependent context for loading the mms_config.xml
+        final Context subContext = getSubDepContext(mContext, subId);
+        // Load and parse the XML
+        XmlResourceParser parser = null;
+        try {
+            parser = subContext.getResources().getXml(R.xml.mms_config);
+            final ApnsXmlProcessor processor = ApnsXmlProcessor.get(parser);
+            processor.setMmsConfigHandler(new ApnsXmlProcessor.MmsConfigHandler() {
+                @Override
+                public void process(final String mccMnc, final String key, final String value,
+                        final String type) {
+                    update(values, type, key, value);
+                }
+            });
+            processor.process();
+        } catch (final Resources.NotFoundException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Can not find mms_config.xml");
+        } finally {
+            if (parser != null) {
+                parser.close();
+            }
+        }
+    }
+
+    /**
+     * Get a subscription's Context so we can load resources from it
+     *
+     * @param context the sub-independent Context
+     * @param subId the SIM's subId
+     * @return the sub-dependent Context
+     */
+    private static Context getSubDepContext(final Context context, final int subId) {
+        if (!OsUtil.isAtLeastL_MR1()) {
+            return context;
+        }
+        final int[] mccMnc = PhoneUtils.get(subId).getMccMnc();
+        final int mcc = mccMnc[0];
+        final int mnc = mccMnc[1];
+        final Configuration subConfig = new Configuration();
+        if (mcc == 0 && mnc == 0) {
+            Configuration config = context.getResources().getConfiguration();
+            subConfig.mcc = config.mcc;
+            subConfig.mnc = config.mnc;
+        } else {
+            subConfig.mcc = mcc;
+            subConfig.mnc = mnc;
+        }
+        return context.createConfigurationContext(subConfig);
+    }
+
+    /**
+     * Add or update a carrier config key/value pair to the Bundle
+     *
+     * @param values the result Bundle to add to
+     * @param type the value type
+     * @param key the key
+     * @param value the value
+     */
+    public static void update(final Bundle values, final String type, final String key,
+            final String value) {
+        try {
+            if (KEY_TYPE_INT.equals(type)) {
+                values.putInt(key, Integer.parseInt(value));
+            } else if (KEY_TYPE_BOOL.equals(type)) {
+                values.putBoolean(key, Boolean.parseBoolean(value));
+            } else if (KEY_TYPE_STRING.equals(type)){
+                values.putString(key, value);
+            }
+        } catch (final NumberFormatException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Add carrier values: "
+                    + "invalid " + key + "," + value + "," + type);
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/BugleUserAgentInfoLoader.java b/src/com/android/messaging/sms/BugleUserAgentInfoLoader.java
new file mode 100644
index 0000000..2b1dcd6
--- /dev/null
+++ b/src/com/android/messaging/sms/BugleUserAgentInfoLoader.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.Context;
+import androidx.appcompat.mms.UserAgentInfoLoader;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.VersionUtil;
+
+/**
+ * User agent and UA profile URL loader
+ */
+public class BugleUserAgentInfoLoader implements UserAgentInfoLoader {
+    private static final String DEFAULT_USER_AGENT_PREFIX = "Bugle/";
+
+    private Context mContext;
+    private boolean mLoaded;
+
+    private String mUserAgent;
+    private String mUAProfUrl;
+
+    public BugleUserAgentInfoLoader(final Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public String getUserAgent() {
+        load();
+        return mUserAgent;
+    }
+
+    @Override
+    public String getUAProfUrl() {
+        load();
+        return mUAProfUrl;
+    }
+
+    private void load() {
+        if (mLoaded) {
+            return;
+        }
+        boolean didLoad = false;
+        synchronized (this) {
+            if (!mLoaded) {
+                loadLocked();
+                mLoaded = true;
+                didLoad = true;
+            }
+        }
+        if (didLoad) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Loaded user agent info: "
+                    + "UA=" + mUserAgent + ", UAProfUrl=" + mUAProfUrl);
+        }
+    }
+
+    private void loadLocked() {
+        if (OsUtil.isAtLeastKLP()) {
+            // load the MMS User agent and UaProfUrl from TelephonyManager APIs
+            final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
+                    Context.TELEPHONY_SERVICE);
+            mUserAgent = telephonyManager.getMmsUserAgent();
+            mUAProfUrl = telephonyManager.getMmsUAProfUrl();
+        }
+        // if user agent string isn't set, use the format "Bugle/<app_version>".
+        if (TextUtils.isEmpty(mUserAgent)) {
+            final String simpleVersionName = VersionUtil.getInstance(mContext).getSimpleName();
+            mUserAgent = DEFAULT_USER_AGENT_PREFIX + simpleVersionName;
+        }
+        // if the UAProfUrl isn't set, get it from Gservices
+        if (TextUtils.isEmpty(mUAProfUrl)) {
+            mUAProfUrl = BugleGservices.get().getString(
+                    BugleGservicesKeys.MMS_UA_PROFILE_URL,
+                    BugleGservicesKeys.MMS_UA_PROFILE_URL_DEFAULT);
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/DatabaseMessages.java b/src/com/android/messaging/sms/DatabaseMessages.java
new file mode 100644
index 0000000..0f662e5
--- /dev/null
+++ b/src/com/android/messaging/sms/DatabaseMessages.java
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Sms;
+import android.text.TextUtils;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.media.VideoThumbnailRequest;
+import com.android.messaging.mmslib.pdu.CharacterSets;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaMetadataRetrieverWrapper;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.collect.Lists;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class contains various SMS/MMS database entities from telephony provider
+ */
+public class DatabaseMessages {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    public abstract static class DatabaseMessage {
+        public abstract int getProtocol();
+        public abstract String getUri();
+        public abstract long getTimestampInMillis();
+
+        @Override
+        public boolean equals(final Object other) {
+            if (other == null || !(other instanceof DatabaseMessage)) {
+                return false;
+            }
+            final DatabaseMessage otherDbMsg = (DatabaseMessage) other;
+            // No need to check timestamp since we only need this when we compare
+            // messages at the same timestamp
+            return TextUtils.equals(getUri(), otherDbMsg.getUri());
+        }
+
+        @Override
+        public int hashCode() {
+            // No need to check timestamp since we only need this when we compare
+            // messages at the same timestamp
+            return getUri().hashCode();
+        }
+    }
+
+    /**
+     * SMS message
+     */
+    public static class SmsMessage extends DatabaseMessage implements Parcelable {
+        private static int sIota = 0;
+        public static final int INDEX_ID = sIota++;
+        public static final int INDEX_TYPE = sIota++;
+        public static final int INDEX_ADDRESS = sIota++;
+        public static final int INDEX_BODY = sIota++;
+        public static final int INDEX_DATE = sIota++;
+        public static final int INDEX_THREAD_ID = sIota++;
+        public static final int INDEX_STATUS = sIota++;
+        public static final int INDEX_READ = sIota++;
+        public static final int INDEX_SEEN = sIota++;
+        public static final int INDEX_DATE_SENT = sIota++;
+        public static final int INDEX_SUB_ID = sIota++;
+
+        private static String[] sProjection;
+
+        public static String[] getProjection() {
+            if (sProjection == null) {
+                String[] projection = new String[] {
+                        Sms._ID,
+                        Sms.TYPE,
+                        Sms.ADDRESS,
+                        Sms.BODY,
+                        Sms.DATE,
+                        Sms.THREAD_ID,
+                        Sms.STATUS,
+                        Sms.READ,
+                        Sms.SEEN,
+                        Sms.DATE_SENT,
+                        Sms.SUBSCRIPTION_ID,
+                    };
+                if (!MmsUtils.hasSmsDateSentColumn()) {
+                    projection[INDEX_DATE_SENT] = Sms.DATE;
+                }
+                if (!OsUtil.isAtLeastL_MR1()) {
+                    Assert.equals(INDEX_SUB_ID, projection.length - 1);
+                    String[] withoutSubId = new String[projection.length - 1];
+                    System.arraycopy(projection, 0, withoutSubId, 0, withoutSubId.length);
+                    projection = withoutSubId;
+                }
+
+                sProjection = projection;
+            }
+
+            return sProjection;
+        }
+
+        public String mUri;
+        public String mAddress;
+        public String mBody;
+        private long mRowId;
+        public long mTimestampInMillis;
+        public long mTimestampSentInMillis;
+        public int mType;
+        public long mThreadId;
+        public int mStatus;
+        public boolean mRead;
+        public boolean mSeen;
+        public int mSubId;
+
+        private SmsMessage() {
+        }
+
+        /**
+         * Load from a cursor of a query that returns the SMS to import
+         *
+         * @param cursor
+         */
+        private void load(final Cursor cursor) {
+            mRowId = cursor.getLong(INDEX_ID);
+            mAddress = cursor.getString(INDEX_ADDRESS);
+            mBody = cursor.getString(INDEX_BODY);
+            mTimestampInMillis = cursor.getLong(INDEX_DATE);
+            // Before ICS, there is no "date_sent" so use copy of "date" value
+            mTimestampSentInMillis = cursor.getLong(INDEX_DATE_SENT);
+            mType = cursor.getInt(INDEX_TYPE);
+            mThreadId = cursor.getLong(INDEX_THREAD_ID);
+            mStatus = cursor.getInt(INDEX_STATUS);
+            mRead = cursor.getInt(INDEX_READ) == 0 ? false : true;
+            mSeen = cursor.getInt(INDEX_SEEN) == 0 ? false : true;
+            mUri = ContentUris.withAppendedId(Sms.CONTENT_URI, mRowId).toString();
+            mSubId = PhoneUtils.getDefault().getSubIdFromTelephony(cursor, INDEX_SUB_ID);
+        }
+
+        /**
+         * Get a new SmsMessage by loading from the cursor of a query
+         * that returns the SMS to import
+         *
+         * @param cursor
+         * @return
+         */
+        public static SmsMessage get(final Cursor cursor) {
+            final SmsMessage msg = new SmsMessage();
+            msg.load(cursor);
+            return msg;
+        }
+
+        @Override
+        public String getUri() {
+            return mUri;
+        }
+
+        public int getSubId() {
+            return mSubId;
+        }
+
+        @Override
+        public int getProtocol() {
+            return MessageData.PROTOCOL_SMS;
+        }
+
+        @Override
+        public long getTimestampInMillis() {
+            return mTimestampInMillis;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private SmsMessage(final Parcel in) {
+            mUri = in.readString();
+            mRowId = in.readLong();
+            mTimestampInMillis = in.readLong();
+            mTimestampSentInMillis = in.readLong();
+            mType = in.readInt();
+            mThreadId = in.readLong();
+            mStatus = in.readInt();
+            mRead = in.readInt() != 0;
+            mSeen = in.readInt() != 0;
+            mSubId = in.readInt();
+
+            // SMS specific
+            mAddress = in.readString();
+            mBody = in.readString();
+        }
+
+        public static final Parcelable.Creator<SmsMessage> CREATOR
+                = new Parcelable.Creator<SmsMessage>() {
+            @Override
+            public SmsMessage createFromParcel(final Parcel in) {
+                return new SmsMessage(in);
+            }
+
+            @Override
+            public SmsMessage[] newArray(final int size) {
+                return new SmsMessage[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            out.writeString(mUri);
+            out.writeLong(mRowId);
+            out.writeLong(mTimestampInMillis);
+            out.writeLong(mTimestampSentInMillis);
+            out.writeInt(mType);
+            out.writeLong(mThreadId);
+            out.writeInt(mStatus);
+            out.writeInt(mRead ? 1 : 0);
+            out.writeInt(mSeen ? 1 : 0);
+            out.writeInt(mSubId);
+
+            // SMS specific
+            out.writeString(mAddress);
+            out.writeString(mBody);
+        }
+    }
+
+    /**
+     * MMS message
+     */
+    public static class MmsMessage extends DatabaseMessage implements Parcelable {
+        private static int sIota = 0;
+        public static final int INDEX_ID = sIota++;
+        public static final int INDEX_MESSAGE_BOX = sIota++;
+        public static final int INDEX_SUBJECT = sIota++;
+        public static final int INDEX_SUBJECT_CHARSET = sIota++;
+        public static final int INDEX_MESSAGE_SIZE = sIota++;
+        public static final int INDEX_DATE = sIota++;
+        public static final int INDEX_DATE_SENT = sIota++;
+        public static final int INDEX_THREAD_ID = sIota++;
+        public static final int INDEX_PRIORITY = sIota++;
+        public static final int INDEX_STATUS = sIota++;
+        public static final int INDEX_READ = sIota++;
+        public static final int INDEX_SEEN = sIota++;
+        public static final int INDEX_CONTENT_LOCATION = sIota++;
+        public static final int INDEX_TRANSACTION_ID = sIota++;
+        public static final int INDEX_MESSAGE_TYPE = sIota++;
+        public static final int INDEX_EXPIRY = sIota++;
+        public static final int INDEX_RESPONSE_STATUS = sIota++;
+        public static final int INDEX_RETRIEVE_STATUS = sIota++;
+        public static final int INDEX_SUB_ID = sIota++;
+
+        private static String[] sProjection;
+
+        public static String[] getProjection() {
+            if (sProjection == null) {
+                String[] projection = new String[] {
+                    Mms._ID,
+                    Mms.MESSAGE_BOX,
+                    Mms.SUBJECT,
+                    Mms.SUBJECT_CHARSET,
+                    Mms.MESSAGE_SIZE,
+                    Mms.DATE,
+                    Mms.DATE_SENT,
+                    Mms.THREAD_ID,
+                    Mms.PRIORITY,
+                    Mms.STATUS,
+                    Mms.READ,
+                    Mms.SEEN,
+                    Mms.CONTENT_LOCATION,
+                    Mms.TRANSACTION_ID,
+                    Mms.MESSAGE_TYPE,
+                    Mms.EXPIRY,
+                    Mms.RESPONSE_STATUS,
+                    Mms.RETRIEVE_STATUS,
+                    Mms.SUBSCRIPTION_ID,
+                };
+
+                if (!OsUtil.isAtLeastL_MR1()) {
+                    Assert.equals(INDEX_SUB_ID, projection.length - 1);
+                    String[] withoutSubId = new String[projection.length - 1];
+                    System.arraycopy(projection, 0, withoutSubId, 0, withoutSubId.length);
+                    projection = withoutSubId;
+                }
+
+                sProjection = projection;
+            }
+
+            return sProjection;
+        }
+
+        public String mUri;
+        private long mRowId;
+        public int mType;
+        public String mSubject;
+        public int mSubjectCharset;
+        private long mSize;
+        public long mTimestampInMillis;
+        public long mSentTimestampInMillis;
+        public long mThreadId;
+        public int mPriority;
+        public int mStatus;
+        public boolean mRead;
+        public boolean mSeen;
+        public String mContentLocation;
+        public String mTransactionId;
+        public int mMmsMessageType;
+        public long mExpiryInMillis;
+        public int mSubId;
+        public String mSender;
+        public int mResponseStatus;
+        public int mRetrieveStatus;
+
+        public List<MmsPart> mParts = Lists.newArrayList();
+        private boolean mPartsProcessed = false;
+
+        private MmsMessage() {
+        }
+
+        /**
+         * Load from a cursor of a query that returns the MMS to import
+         *
+         * @param cursor
+         */
+        public void load(final Cursor cursor) {
+            mRowId = cursor.getLong(INDEX_ID);
+            mType = cursor.getInt(INDEX_MESSAGE_BOX);
+            mSubject = cursor.getString(INDEX_SUBJECT);
+            mSubjectCharset = cursor.getInt(INDEX_SUBJECT_CHARSET);
+            if (!TextUtils.isEmpty(mSubject)) {
+                // PduPersister stores the subject using ISO_8859_1
+                // Let's load it using that encoding and convert it back to its original
+                // See PduPersister.persist and PduPersister.toIsoString
+                // (Refer to bug b/11162476)
+                mSubject = getDecodedString(
+                        getStringBytes(mSubject, CharacterSets.ISO_8859_1), mSubjectCharset);
+            }
+            mSize = cursor.getLong(INDEX_MESSAGE_SIZE);
+            // MMS db times are in seconds
+            mTimestampInMillis = cursor.getLong(INDEX_DATE) * 1000;
+            mSentTimestampInMillis = cursor.getLong(INDEX_DATE_SENT) * 1000;
+            mThreadId = cursor.getLong(INDEX_THREAD_ID);
+            mPriority = cursor.getInt(INDEX_PRIORITY);
+            mStatus = cursor.getInt(INDEX_STATUS);
+            mRead = cursor.getInt(INDEX_READ) == 0 ? false : true;
+            mSeen = cursor.getInt(INDEX_SEEN) == 0 ? false : true;
+            mContentLocation = cursor.getString(INDEX_CONTENT_LOCATION);
+            mTransactionId = cursor.getString(INDEX_TRANSACTION_ID);
+            mMmsMessageType = cursor.getInt(INDEX_MESSAGE_TYPE);
+            mExpiryInMillis = cursor.getLong(INDEX_EXPIRY) * 1000;
+            mResponseStatus = cursor.getInt(INDEX_RESPONSE_STATUS);
+            mRetrieveStatus = cursor.getInt(INDEX_RETRIEVE_STATUS);
+            // Clear all parts in case we reuse this object
+            mParts.clear();
+            mPartsProcessed = false;
+            mUri = ContentUris.withAppendedId(Mms.CONTENT_URI, mRowId).toString();
+            mSubId = PhoneUtils.getDefault().getSubIdFromTelephony(cursor, INDEX_SUB_ID);
+        }
+
+        /**
+         * Get a new MmsMessage by loading from the cursor of a query
+         * that returns the MMS to import
+         *
+         * @param cursor
+         * @return
+         */
+        public static MmsMessage get(final Cursor cursor) {
+            final MmsMessage msg = new MmsMessage();
+            msg.load(cursor);
+            return msg;
+        }
+        /**
+         * Add a loaded MMS part
+         *
+         * @param part
+         */
+        public void addPart(final MmsPart part) {
+            mParts.add(part);
+        }
+
+        public List<MmsPart> getParts() {
+            return mParts;
+        }
+
+        public long getSize() {
+            if (!mPartsProcessed) {
+                processParts();
+            }
+            return mSize;
+        }
+
+        /**
+         * Process loaded MMS parts to obtain the combined text, the combined attachment url,
+         * the combined content type and the combined size.
+         */
+        private void processParts() {
+            if (mPartsProcessed) {
+                return;
+            }
+            mPartsProcessed = true;
+            // Remember the width and height of the first media part
+            // These are needed when building attachment list
+            long sizeOfParts = 0L;
+            for (final MmsPart part : mParts) {
+                sizeOfParts += part.mSize;
+            }
+            if (mSize <= 0) {
+                mSize = mSubject != null ? mSubject.getBytes().length : 0L;
+                mSize += sizeOfParts;
+            }
+        }
+
+        @Override
+        public String getUri() {
+            return mUri;
+        }
+
+        public long getId() {
+            return mRowId;
+        }
+
+        public int getSubId() {
+            return mSubId;
+        }
+
+        @Override
+        public int getProtocol() {
+            return MessageData.PROTOCOL_MMS;
+        }
+
+        @Override
+        public long getTimestampInMillis() {
+            return mTimestampInMillis;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public void setSender(final String sender) {
+            mSender = sender;
+        }
+
+        private MmsMessage(final Parcel in) {
+            mUri = in.readString();
+            mRowId = in.readLong();
+            mTimestampInMillis = in.readLong();
+            mSentTimestampInMillis = in.readLong();
+            mType = in.readInt();
+            mThreadId = in.readLong();
+            mStatus = in.readInt();
+            mRead = in.readInt() != 0;
+            mSeen = in.readInt() != 0;
+            mSubId = in.readInt();
+
+            // MMS specific
+            mSubject = in.readString();
+            mContentLocation = in.readString();
+            mTransactionId = in.readString();
+            mSender = in.readString();
+
+            mSize = in.readLong();
+            mExpiryInMillis = in.readLong();
+
+            mSubjectCharset = in.readInt();
+            mPriority = in.readInt();
+            mMmsMessageType = in.readInt();
+            mResponseStatus = in.readInt();
+            mRetrieveStatus = in.readInt();
+
+            final int nParts = in.readInt();
+            mParts = new ArrayList<MmsPart>();
+            mPartsProcessed = false;
+            for (int i = 0; i < nParts; i++) {
+                mParts.add((MmsPart) in.readParcelable(getClass().getClassLoader()));
+            }
+        }
+
+        public static final Parcelable.Creator<MmsMessage> CREATOR
+                = new Parcelable.Creator<MmsMessage>() {
+            @Override
+            public MmsMessage createFromParcel(final Parcel in) {
+                return new MmsMessage(in);
+            }
+
+            @Override
+            public MmsMessage[] newArray(final int size) {
+                return new MmsMessage[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            out.writeString(mUri);
+            out.writeLong(mRowId);
+            out.writeLong(mTimestampInMillis);
+            out.writeLong(mSentTimestampInMillis);
+            out.writeInt(mType);
+            out.writeLong(mThreadId);
+            out.writeInt(mStatus);
+            out.writeInt(mRead ? 1 : 0);
+            out.writeInt(mSeen ? 1 : 0);
+            out.writeInt(mSubId);
+
+            out.writeString(mSubject);
+            out.writeString(mContentLocation);
+            out.writeString(mTransactionId);
+            out.writeString(mSender);
+
+            out.writeLong(mSize);
+            out.writeLong(mExpiryInMillis);
+
+            out.writeInt(mSubjectCharset);
+            out.writeInt(mPriority);
+            out.writeInt(mMmsMessageType);
+            out.writeInt(mResponseStatus);
+            out.writeInt(mRetrieveStatus);
+
+            out.writeInt(mParts.size());
+            for (final MmsPart part : mParts) {
+                out.writeParcelable(part, 0);
+            }
+        }
+    }
+
+    /**
+     * Part of an MMS message
+     */
+    public static class MmsPart implements Parcelable {
+        public static final String[] PROJECTION = new String[] {
+            Mms.Part._ID,
+            Mms.Part.MSG_ID,
+            Mms.Part.CHARSET,
+            Mms.Part.CONTENT_TYPE,
+            Mms.Part.TEXT,
+        };
+        private static int sIota = 0;
+        public static final int INDEX_ID = sIota++;
+        public static final int INDEX_MSG_ID = sIota++;
+        public static final int INDEX_CHARSET = sIota++;
+        public static final int INDEX_CONTENT_TYPE = sIota++;
+        public static final int INDEX_TEXT = sIota++;
+
+        public String mUri;
+        public long mRowId;
+        public long mMessageId;
+        public String mContentType;
+        public String mText;
+        public int mCharset;
+        private int mWidth;
+        private int mHeight;
+        public long mSize;
+
+        private MmsPart() {
+        }
+
+        /**
+         * Load from a cursor of a query that returns the MMS part to import
+         *
+         * @param cursor
+         */
+        public void load(final Cursor cursor, final boolean loadMedia) {
+            mRowId = cursor.getLong(INDEX_ID);
+            mMessageId = cursor.getLong(INDEX_MSG_ID);
+            mContentType = cursor.getString(INDEX_CONTENT_TYPE);
+            mText = cursor.getString(INDEX_TEXT);
+            mCharset = cursor.getInt(INDEX_CHARSET);
+            mWidth = 0;
+            mHeight = 0;
+            mSize = 0;
+            if (isMedia()) {
+                // For importing we don't load media since performance is critical
+                // For loading when we receive mms, we do load media to get enough
+                // information of the media file
+                if (loadMedia) {
+                    if (ContentType.isImageType(mContentType)) {
+                        loadImage();
+                    } else if (ContentType.isVideoType(mContentType)) {
+                        loadVideo();
+                    } // No need to load audio for parsing
+                    mSize = MmsUtils.getMediaFileSize(getDataUri());
+                }
+            } else {
+                // Load text if not media type
+                loadText();
+            }
+            mUri = Uri.withAppendedPath(Mms.CONTENT_URI, cursor.getString(INDEX_ID)).toString();
+        }
+
+        /**
+         * Get content type from file extension
+         */
+        private static String extractContentType(final Context context, final Uri uri) {
+            final String path = uri.getPath();
+            final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+            String extension = MimeTypeMap.getFileExtensionFromUrl(path);
+            if (TextUtils.isEmpty(extension)) {
+                // getMimeTypeFromExtension() doesn't handle spaces in filenames nor can it handle
+                // urlEncoded strings. Let's try one last time at finding the extension.
+                final int dotPos = path.lastIndexOf('.');
+                if (0 <= dotPos) {
+                    extension = path.substring(dotPos + 1);
+                }
+            }
+            return mimeTypeMap.getMimeTypeFromExtension(extension);
+        }
+
+        /**
+         * Get text of a text part
+         */
+        private void loadText() {
+            byte[] data = null;
+            if (isEmbeddedTextType()) {
+                // Embedded text, get from the "text" column
+                if (!TextUtils.isEmpty(mText)) {
+                    data = getStringBytes(mText, mCharset);
+                }
+            } else {
+                // Not embedded, load from disk
+                final ContentResolver resolver =
+                        Factory.get().getApplicationContext().getContentResolver();
+                final Uri uri = getDataUri();
+                InputStream is = null;
+                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                try {
+                    is = resolver.openInputStream(uri);
+                    final byte[] buffer = new byte[256];
+                    int len = is.read(buffer);
+                    while (len >= 0) {
+                        baos.write(buffer, 0, len);
+                        len = is.read(buffer);
+                    }
+                } catch (final IOException e) {
+                    LogUtil.e(TAG,
+                            "DatabaseMessages.MmsPart: loading text from file failed: " + e, e);
+                } finally {
+                    if (is != null) {
+                        try {
+                            is.close();
+                        } catch (final IOException e) {
+                            LogUtil.e(TAG, "DatabaseMessages.MmsPart: close file failed: " + e, e);
+                        }
+                    }
+                }
+                data = baos.toByteArray();
+            }
+            if (data != null && data.length > 0) {
+                mSize = data.length;
+                mText = getDecodedString(data, mCharset);
+            }
+        }
+
+        /**
+         * Load image file of an image part and parse the dimensions and type
+         */
+        private void loadImage() {
+            final Context context = Factory.get().getApplicationContext();
+            final ContentResolver resolver = context.getContentResolver();
+            final Uri uri = getDataUri();
+            // We have to get the width and height of the image -- they're needed when adding
+            // an attachment in bugle.
+            InputStream is = null;
+            try {
+                is = resolver.openInputStream(uri);
+                final BitmapFactory.Options opt = new BitmapFactory.Options();
+                opt.inJustDecodeBounds = true;
+                BitmapFactory.decodeStream(is, null, opt);
+                mContentType = opt.outMimeType;
+                mWidth = opt.outWidth;
+                mHeight = opt.outHeight;
+                if (TextUtils.isEmpty(mContentType)) {
+                    // BitmapFactory couldn't figure out the image type. That's got to be a bad
+                    // sign, but see if we can figure it out from the file extension.
+                    mContentType = extractContentType(context, uri);
+                }
+            } catch (final FileNotFoundException e) {
+                LogUtil.e(TAG, "DatabaseMessages.MmsPart.loadImage: file not found", e);
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (final IOException e) {
+                        Log.e(TAG, "IOException caught while closing stream", e);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Load video file of a video part and parse the dimensions and type
+         */
+        private void loadVideo() {
+            // This is a coarse check, and should not be applied to outgoing messages. However,
+            // currently, this does not cause any problems.
+            if (!VideoThumbnailRequest.shouldShowIncomingVideoThumbnails()) {
+                return;
+            }
+            final Uri uri = getDataUri();
+            final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
+            try {
+                retriever.setDataSource(uri);
+                // FLAG: This inadvertently fixes a problem with phone receiving audio
+                // messages on some carrier. We should handle this in a less accidental way so that
+                // we don't break it again. (The carrier changes the content type in the wrapper
+                // in-transit from audio/mp4 to video/3gpp without changing the data)
+                // Also note: There is a bug in some OEM device where mmr returns
+                // video/ffmpeg for image files.  That shouldn't happen here but be aware.
+                mContentType =
+                        retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
+                final Bitmap bitmap = retriever.getFrameAtTime(-1);
+                if (bitmap != null) {
+                    mWidth = bitmap.getWidth();
+                    mHeight = bitmap.getHeight();
+                } else {
+                    // Get here if it's not actually video (see above)
+                    LogUtil.i(LogUtil.BUGLE_TAG, "loadVideo: Got null bitmap from " + uri);
+                }
+            } catch (IOException e) {
+                LogUtil.i(LogUtil.BUGLE_TAG, "Error extracting metadata from " + uri, e);
+            } finally {
+                retriever.release();
+            }
+        }
+
+        /**
+         * Get media file size
+         */
+        private long getMediaFileSize() {
+            final Context context = Factory.get().getApplicationContext();
+            final Uri uri = getDataUri();
+            AssetFileDescriptor fd = null;
+            try {
+                fd = context.getContentResolver().openAssetFileDescriptor(uri, "r");
+                if (fd != null) {
+                    return fd.getParcelFileDescriptor().getStatSize();
+                }
+            } catch (final FileNotFoundException e) {
+                LogUtil.e(TAG, "DatabaseMessages.MmsPart: cound not find media file: " + e, e);
+            } finally {
+                if (fd != null) {
+                    try {
+                        fd.close();
+                    } catch (final IOException e) {
+                        LogUtil.e(TAG, "DatabaseMessages.MmsPart: failed to close " + e, e);
+                    }
+                }
+            }
+            return 0L;
+        }
+
+        /**
+         * @return If the type is a text type that stores text embedded (i.e. in db table)
+         */
+        private boolean isEmbeddedTextType() {
+            return ContentType.TEXT_PLAIN.equals(mContentType)
+                    || ContentType.APP_SMIL.equals(mContentType)
+                    || ContentType.TEXT_HTML.equals(mContentType);
+        }
+
+        /**
+         * Get an instance of the MMS part from the part table cursor
+         *
+         * @param cursor
+         * @param loadMedia Whether to load the media file of the part
+         * @return
+         */
+        public static MmsPart get(final Cursor cursor, final boolean loadMedia) {
+            final MmsPart part = new MmsPart();
+            part.load(cursor, loadMedia);
+            return part;
+        }
+
+        public boolean isText() {
+            return ContentType.TEXT_PLAIN.equals(mContentType)
+                    || ContentType.TEXT_HTML.equals(mContentType)
+                    || ContentType.APP_WAP_XHTML.equals(mContentType);
+        }
+
+        public boolean isMedia() {
+            return ContentType.isImageType(mContentType)
+                    || ContentType.isVideoType(mContentType)
+                    || ContentType.isAudioType(mContentType)
+                    || ContentType.isVCardType(mContentType);
+        }
+
+        public boolean isImage() {
+            return ContentType.isImageType(mContentType);
+        }
+
+        public Uri getDataUri() {
+            return Uri.parse("content://mms/part/" + mRowId);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private MmsPart(final Parcel in) {
+            mUri = in.readString();
+            mRowId = in.readLong();
+            mMessageId = in.readLong();
+            mContentType = in.readString();
+            mText = in.readString();
+            mCharset = in.readInt();
+            mWidth = in.readInt();
+            mHeight = in.readInt();
+            mSize = in.readLong();
+        }
+
+        public static final Parcelable.Creator<MmsPart> CREATOR
+                = new Parcelable.Creator<MmsPart>() {
+            @Override
+            public MmsPart createFromParcel(final Parcel in) {
+                return new MmsPart(in);
+            }
+
+            @Override
+            public MmsPart[] newArray(final int size) {
+                return new MmsPart[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            out.writeString(mUri);
+            out.writeLong(mRowId);
+            out.writeLong(mMessageId);
+            out.writeString(mContentType);
+            out.writeString(mText);
+            out.writeInt(mCharset);
+            out.writeInt(mWidth);
+            out.writeInt(mHeight);
+            out.writeLong(mSize);
+        }
+    }
+
+    /**
+     * This class provides the same DatabaseMessage interface over a local SMS db message
+     */
+    public static class LocalDatabaseMessage extends DatabaseMessage implements Parcelable {
+        private final int mProtocol;
+        private final String mUri;
+        private final long mTimestamp;
+        private final long mLocalId;
+        private final String mConversationId;
+
+        public LocalDatabaseMessage(final long localId, final int protocol, final String uri,
+                final long timestamp, final String conversationId) {
+            mLocalId = localId;
+            mProtocol = protocol;
+            mUri = uri;
+            mTimestamp = timestamp;
+            mConversationId = conversationId;
+        }
+
+        @Override
+        public int getProtocol() {
+            return mProtocol;
+        }
+
+        @Override
+        public long getTimestampInMillis() {
+            return mTimestamp;
+        }
+
+        @Override
+        public String getUri() {
+            return mUri;
+        }
+
+        public long getLocalId() {
+            return mLocalId;
+        }
+
+        public String getConversationId() {
+            return mConversationId;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private LocalDatabaseMessage(final Parcel in) {
+            mUri = in.readString();
+            mConversationId = in.readString();
+            mLocalId = in.readLong();
+            mTimestamp = in.readLong();
+            mProtocol = in.readInt();
+        }
+
+        public static final Parcelable.Creator<LocalDatabaseMessage> CREATOR
+                = new Parcelable.Creator<LocalDatabaseMessage>() {
+            @Override
+            public LocalDatabaseMessage createFromParcel(final Parcel in) {
+                return new LocalDatabaseMessage(in);
+            }
+
+            @Override
+            public LocalDatabaseMessage[] newArray(final int size) {
+                return new LocalDatabaseMessage[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            out.writeString(mUri);
+            out.writeString(mConversationId);
+            out.writeLong(mLocalId);
+            out.writeLong(mTimestamp);
+            out.writeInt(mProtocol);
+        }
+    }
+
+    /**
+     * Address for MMS message
+     */
+    public static class MmsAddr {
+        public static final String[] PROJECTION = new String[] {
+            Mms.Addr.ADDRESS,
+            Mms.Addr.CHARSET,
+        };
+        private static int sIota = 0;
+        public static final int INDEX_ADDRESS = sIota++;
+        public static final int INDEX_CHARSET = sIota++;
+
+        public static String get(final Cursor cursor) {
+            final int charset = cursor.getInt(INDEX_CHARSET);
+            // PduPersister stores the addresses using ISO_8859_1
+            // Let's load it using that encoding and convert it back to its original
+            // See PduPersister.persistAddress
+            return getDecodedString(
+                    getStringBytes(cursor.getString(INDEX_ADDRESS), CharacterSets.ISO_8859_1),
+                    charset);
+        }
+    }
+
+    /**
+     * Decoded string by character set
+     */
+    public static String getDecodedString(final byte[] data, final int charset)  {
+        if (CharacterSets.ANY_CHARSET == charset) {
+            return new String(data); // system default encoding.
+        } else {
+            try {
+                final String name = CharacterSets.getMimeName(charset);
+                return new String(data, name);
+            } catch (final UnsupportedEncodingException e) {
+                try {
+                    return new String(data, CharacterSets.MIMENAME_ISO_8859_1);
+                } catch (final UnsupportedEncodingException exception) {
+                    return new String(data); // system default encoding.
+                }
+            }
+        }
+    }
+
+    /**
+     * Unpack a given String into a byte[].
+     */
+    public static byte[] getStringBytes(final String data, final int charset) {
+        if (CharacterSets.ANY_CHARSET == charset) {
+            return data.getBytes();
+        } else {
+            try {
+                final String name = CharacterSets.getMimeName(charset);
+                return data.getBytes(name);
+            } catch (final UnsupportedEncodingException e) {
+                return data.getBytes();
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/MmsConfig.java b/src/com/android/messaging/sms/MmsConfig.java
new file mode 100755
index 0000000..187e677
--- /dev/null
+++ b/src/com/android/messaging/sms/MmsConfig.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.os.Bundle;
+import androidx.appcompat.mms.CarrierConfigValuesLoader;
+import android.telephony.SubscriptionInfo;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+import com.google.common.collect.Maps;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * MMS configuration.
+ *
+ * This is now a wrapper around the BugleCarrierConfigValuesLoader, which does
+ * the actual loading and stores the values in a Bundle. This class provides getter
+ * methods for values used in the app, which is easier to use than the raw loader
+ * class.
+ */
+public class MmsConfig {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final int DEFAULT_MAX_TEXT_LENGTH = 2000;
+
+    /*
+     * Key types
+     */
+    public static final String KEY_TYPE_INT = "int";
+    public static final String KEY_TYPE_BOOL = "bool";
+    public static final String KEY_TYPE_STRING = "string";
+
+    private static final Map<String, String> sKeyTypeMap = Maps.newHashMap();
+    static {
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_MMS, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS,
+                KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
+                KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
+                KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_READ_REPORTS, KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_DELIVERY_REPORTS,
+                KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
+                KEY_TYPE_BOOL);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
+                KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH, KEY_TYPE_INT);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_UA_PROF_URL, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_USER_AGENT, KEY_TYPE_STRING);
+    }
+
+    // A map that stores all MmsConfigs, one per active subscription. For pre-LMSim, this will
+    // contain just one entry with the default self sub id; for LMSim and above, this will contain
+    // all active sub ids but the default subscription id - the default subscription id will be
+    // resolved to an active sub id during runtime.
+    private static final Map<Integer, MmsConfig> sSubIdToMmsConfigMap = Maps.newHashMap();
+    // The fallback values
+    private static final MmsConfig sFallback =
+            new MmsConfig(ParticipantData.DEFAULT_SELF_SUB_ID, new Bundle());
+
+    // Per-subscription configuration values.
+    private final Bundle mValues;
+    private final int mSubId;
+
+    /**
+     * Retrieves the MmsConfig instance associated with the given {@code subId}
+     */
+    public static MmsConfig get(final int subId) {
+        final int realSubId = PhoneUtils.getDefault().getEffectiveSubId(subId);
+        synchronized (sSubIdToMmsConfigMap) {
+            final MmsConfig mmsConfig = sSubIdToMmsConfigMap.get(realSubId);
+            if (mmsConfig == null) {
+                // The subId is no longer valid. Fall back to the default config.
+                LogUtil.e(LogUtil.BUGLE_TAG, "Get mms config failed: invalid subId. subId=" + subId
+                        + ", real subId=" + realSubId
+                        + ", map=" + sSubIdToMmsConfigMap.keySet());
+                return sFallback;
+            }
+            return mmsConfig;
+        }
+    }
+
+    private MmsConfig(final int subId, final Bundle values) {
+        mSubId = subId;
+        mValues = values;
+    }
+
+    /**
+     * Same as load() but doing it using an async thread from SafeAsyncTask thread pool.
+     */
+    public static void loadAsync() {
+        SafeAsyncTask.executeOnThreadPool(new Runnable() {
+            @Override
+            public void run() {
+                load();
+            }
+        });
+    }
+
+    /**
+     * Reload the device and per-subscription settings.
+     */
+    public static synchronized void load() {
+        final BugleCarrierConfigValuesLoader loader = Factory.get().getCarrierConfigValuesLoader();
+        // Rebuild the entire MmsConfig map.
+        sSubIdToMmsConfigMap.clear();
+        loader.reset();
+        if (OsUtil.isAtLeastL_MR1()) {
+            final List<SubscriptionInfo> subInfoRecords =
+                    PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList();
+            if (subInfoRecords == null) {
+                LogUtil.w(TAG, "Loading mms config failed: no active SIM");
+                return;
+            }
+            for (SubscriptionInfo subInfoRecord : subInfoRecords) {
+                final int subId = subInfoRecord.getSubscriptionId();
+                final Bundle values = loader.get(subId);
+                addMmsConfig(new MmsConfig(subId, values));
+            }
+        } else {
+            final Bundle values = loader.get(ParticipantData.DEFAULT_SELF_SUB_ID);
+            addMmsConfig(new MmsConfig(ParticipantData.DEFAULT_SELF_SUB_ID, values));
+        }
+    }
+
+    private static void addMmsConfig(MmsConfig mmsConfig) {
+        Assert.isTrue(OsUtil.isAtLeastL_MR1() !=
+                (mmsConfig.mSubId == ParticipantData.DEFAULT_SELF_SUB_ID));
+        sSubIdToMmsConfigMap.put(mmsConfig.mSubId, mmsConfig);
+    }
+
+    public int getSmsToMmsTextThreshold() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD,
+                CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD_DEFAULT);
+    }
+
+    public int getSmsToMmsTextLengthThreshold() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
+                CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_DEFAULT);
+    }
+
+    public int getMaxMessageSize() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE,
+                CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE_DEFAULT);
+    }
+
+    /**
+     * Return the largest MaxMessageSize for any subid
+     */
+    public static int getMaxMaxMessageSize() {
+        int maxMax = 0;
+        for (MmsConfig config : sSubIdToMmsConfigMap.values()) {
+            maxMax = Math.max(maxMax, config.getMaxMessageSize());
+        }
+        return maxMax > 0 ? maxMax : sFallback.getMaxMessageSize();
+    }
+
+    public boolean getTransIdEnabled() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID,
+                CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID_DEFAULT);
+    }
+
+    public String getEmailGateway() {
+        return mValues.getString(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER,
+                CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER_DEFAULT);
+    }
+
+    public int getMaxImageHeight() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT,
+                CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT_DEFAULT);
+    }
+
+    public int getMaxImageWidth() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH,
+                CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH_DEFAULT);
+    }
+
+    public int getRecipientLimit() {
+        final int limit = mValues.getInt(CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT,
+                CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT_DEFAULT);
+        return limit < 0 ? Integer.MAX_VALUE : limit;
+    }
+
+    public int getMaxTextLimit() {
+        final int max = mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE,
+                CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE_DEFAULT);
+        return max > -1 ? max : DEFAULT_MAX_TEXT_LENGTH;
+    }
+
+    public boolean getMultipartSmsEnabled() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS,
+                CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS_DEFAULT);
+    }
+
+    public boolean getSendMultipartSmsAsSeparateMessages() {
+        return mValues.getBoolean(
+                CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
+                CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_DEFAULT);
+    }
+
+    public boolean getSMSDeliveryReportsEnabled() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS,
+                CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS_DEFAULT);
+    }
+
+    public boolean getNotifyWapMMSC() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC,
+                CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC_DEFAULT);
+    }
+
+    public boolean isAliasEnabled() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED,
+                CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED_DEFAULT);
+    }
+
+    public int getAliasMinChars() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS,
+                CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS_DEFAULT);
+    }
+
+    public int getAliasMaxChars() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS,
+                CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS_DEFAULT);
+    }
+
+    public boolean getAllowAttachAudio() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO,
+                CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO_DEFAULT);
+    }
+
+    public int getMaxSubjectLength() {
+        return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH,
+                CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH_DEFAULT);
+    }
+
+    public boolean getGroupMmsEnabled() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS,
+                CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS_DEFAULT);
+    }
+
+    public boolean getSupportMmsContentDisposition() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
+                CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION_DEFAULT);
+    }
+
+    public boolean getShowCellBroadcast() {
+        return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS,
+                CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS_DEFAULT);
+    }
+
+    public Object getValue(final String key) {
+        return mValues.get(key);
+    }
+
+    public Set<String> keySet() {
+        return mValues.keySet();
+    }
+
+    public static String getKeyType(final String key) {
+        return sKeyTypeMap.get(key);
+    }
+
+    public void update(final String type, final String key, final String value) {
+        BugleCarrierConfigValuesLoader.update(mValues, type, key, value);
+    }
+}
diff --git a/src/com/android/messaging/sms/MmsFailureException.java b/src/com/android/messaging/sms/MmsFailureException.java
new file mode 100644
index 0000000..dd702ee
--- /dev/null
+++ b/src/com/android/messaging/sms/MmsFailureException.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.Assert;
+
+/**
+ * Exception for MMS failures
+ */
+public class MmsFailureException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Hint of how we should retry in case of failure. Take values defined in MmsUtils.
+     */
+    public final int retryHint;
+
+    /**
+     * If set, provides a more detailed reason for the failure.
+     */
+    public final int rawStatus;
+
+    private void checkRetryHint() {
+        Assert.isTrue(retryHint == MmsUtils.MMS_REQUEST_AUTO_RETRY
+                || retryHint == MmsUtils.MMS_REQUEST_MANUAL_RETRY
+                || retryHint == MmsUtils.MMS_REQUEST_NO_RETRY);
+    }
+    /**
+     * Creates a new MmsFailureException.
+     *
+     * @param retryHint Hint for how to retry
+     */
+    public MmsFailureException(final int retryHint) {
+        super();
+        this.retryHint = retryHint;
+        checkRetryHint();
+        this.rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+    }
+
+    public MmsFailureException(final int retryHint, final int rawStatus) {
+        super();
+        this.retryHint = retryHint;
+        checkRetryHint();
+        this.rawStatus = rawStatus;
+    }
+
+    /**
+     * Creates a new MmsFailureException with the specified detail message.
+     *
+     * @param retryHint Hint for how to retry
+     * @param message the detail message.
+     */
+    public MmsFailureException(final int retryHint, String message) {
+        super(message);
+        this.retryHint = retryHint;
+        checkRetryHint();
+        this.rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+    }
+
+    /**
+     * Creates a new MmsFailureException with the specified cause.
+     *
+     * @param retryHint Hint for how to retry
+     * @param cause the cause.
+     */
+    public MmsFailureException(final int retryHint, Throwable cause) {
+        super(cause);
+        this.retryHint = retryHint;
+        checkRetryHint();
+        this.rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+    }
+
+    /**
+     * Creates a new MmsFailureException
+     * with the specified detail message and cause.
+     *
+     * @param retryHint Hint for how to retry
+     * @param message the detail message.
+     * @param cause the cause.
+     */
+    public MmsFailureException(final int retryHint, String message, Throwable cause) {
+        super(message, cause);
+        this.retryHint = retryHint;
+        checkRetryHint();
+        this.rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+    }
+}
diff --git a/src/com/android/messaging/sms/MmsSender.java b/src/com/android/messaging/sms/MmsSender.java
new file mode 100644
index 0000000..b881a7f
--- /dev/null
+++ b/src/com/android/messaging/sms/MmsSender.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.appcompat.mms.MmsManager;
+import android.telephony.SmsManager;
+
+import com.android.messaging.datamodel.MmsFileProvider;
+import com.android.messaging.datamodel.action.SendMessageAction;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+import com.android.messaging.mmslib.pdu.AcknowledgeInd;
+import com.android.messaging.mmslib.pdu.EncodedStringValue;
+import com.android.messaging.mmslib.pdu.GenericPdu;
+import com.android.messaging.mmslib.pdu.NotifyRespInd;
+import com.android.messaging.mmslib.pdu.PduComposer;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.mmslib.pdu.PduParser;
+import com.android.messaging.mmslib.pdu.RetrieveConf;
+import com.android.messaging.mmslib.pdu.SendConf;
+import com.android.messaging.mmslib.pdu.SendReq;
+import com.android.messaging.receiver.SendStatusReceiver;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Class that sends chat message via MMS.
+ *
+ * The interface emulates a blocking send similar to making an HTTP request.
+ */
+public class MmsSender {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    /**
+     * Send an MMS message.
+     *
+     * @param context Context
+     * @param messageUri The unique URI of the message for identifying it during sending
+     * @param sendReq The SendReq PDU of the message
+     * @throws MmsFailureException
+     */
+    public static void sendMms(final Context context, final int subId, final Uri messageUri,
+            final SendReq sendReq, final Bundle sentIntentExras) throws MmsFailureException {
+        sendMms(context,
+                subId,
+                messageUri,
+                null /* locationUrl */,
+                sendReq,
+                true /* responseImportant */,
+                sentIntentExras);
+    }
+
+    /**
+     * Send NotifyRespInd (response to mms auto download).
+     *
+     * @param context Context
+     * @param subId subscription to use to send the response
+     * @param transactionId The transaction id of the MMS message
+     * @param contentLocation The url of the MMS message
+     * @param status The status to send with the NotifyRespInd
+     * @throws MmsFailureException
+     * @throws InvalidHeaderValueException
+     */
+    public static void sendNotifyResponseForMmsDownload(final Context context, final int subId,
+            final byte[] transactionId, final String contentLocation, final int status)
+            throws MmsFailureException, InvalidHeaderValueException {
+        // Create the M-NotifyResp.ind
+        final NotifyRespInd notifyRespInd = new NotifyRespInd(
+                PduHeaders.CURRENT_MMS_VERSION, transactionId, status);
+        final Uri messageUri = Uri.parse(contentLocation);
+        // Pack M-NotifyResp.ind and send it
+        sendMms(context,
+                subId,
+                messageUri,
+                MmsConfig.get(subId).getNotifyWapMMSC() ? contentLocation : null,
+                notifyRespInd,
+                false /* responseImportant */,
+                null /* sentIntentExtras */);
+    }
+
+    /**
+     * Send AcknowledgeInd (response to mms manual download). Ignore failures.
+     *
+     * @param context Context
+     * @param subId The SIM's subId we are currently using
+     * @param transactionId The transaction id of the MMS message
+     * @param contentLocation The url of the MMS message
+     * @throws MmsFailureException
+     * @throws InvalidHeaderValueException
+     */
+    public static void sendAcknowledgeForMmsDownload(final Context context, final int subId,
+            final byte[] transactionId, final String contentLocation)
+            throws MmsFailureException, InvalidHeaderValueException {
+        final String selfNumber = PhoneUtils.get(subId).getCanonicalForSelf(true/*allowOverride*/);
+        // Create the M-Acknowledge.ind
+        final AcknowledgeInd acknowledgeInd = new AcknowledgeInd(PduHeaders.CURRENT_MMS_VERSION,
+                transactionId);
+        acknowledgeInd.setFrom(new EncodedStringValue(selfNumber));
+        final Uri messageUri = Uri.parse(contentLocation);
+        // Sending
+        sendMms(context,
+                subId,
+                messageUri,
+                MmsConfig.get(subId).getNotifyWapMMSC() ? contentLocation : null,
+                acknowledgeInd,
+                false /*responseImportant*/,
+                null /* sentIntentExtras */);
+    }
+
+    /**
+     * Send a generic PDU.
+     *
+     * @param context Context
+     * @param messageUri The unique URI of the message for identifying it during sending
+     * @param locationUrl The optional URL to send to
+     * @param pdu The PDU to send
+     * @param responseImportant If the sending response is important. Responses to the
+     * Sending of AcknowledgeInd and NotifyRespInd are not important.
+     * @throws MmsFailureException
+     */
+    private static void sendMms(final Context context, final int subId, final Uri messageUri,
+            final String locationUrl, final GenericPdu pdu, final boolean responseImportant,
+            final Bundle sentIntentExtras) throws MmsFailureException {
+        // Write PDU to temporary file to send to platform
+        final Uri contentUri = writePduToTempFile(context, pdu, subId);
+
+        // Construct PendingIntent that will notify us when message sending is complete
+        final Intent sentIntent = new Intent(SendStatusReceiver.MMS_SENT_ACTION,
+                messageUri,
+                context,
+                SendStatusReceiver.class);
+        sentIntent.putExtra(SendMessageAction.EXTRA_CONTENT_URI, contentUri);
+        sentIntent.putExtra(SendMessageAction.EXTRA_RESPONSE_IMPORTANT, responseImportant);
+        if (sentIntentExtras != null) {
+            sentIntent.putExtras(sentIntentExtras);
+        }
+        final PendingIntent sentPendingIntent = PendingIntent.getBroadcast(
+                context,
+                0 /*request code*/,
+                sentIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        // Send the message
+        MmsManager.sendMultimediaMessage(subId, context, contentUri, locationUrl,
+                sentPendingIntent);
+    }
+
+    private static Uri writePduToTempFile(final Context context, final GenericPdu pdu, int subId)
+            throws MmsFailureException {
+        final Uri contentUri = MmsFileProvider.buildRawMmsUri();
+        final File tempFile = MmsFileProvider.getFile(contentUri);
+        FileOutputStream writer = null;
+        try {
+            // Ensure rawmms directory exists
+            tempFile.getParentFile().mkdirs();
+            writer = new FileOutputStream(tempFile);
+            final byte[] pduBytes = new PduComposer(context, pdu).make();
+            if (pduBytes == null) {
+                throw new MmsFailureException(
+                        MmsUtils.MMS_REQUEST_NO_RETRY, "Failed to compose PDU");
+            }
+            if (pduBytes.length > MmsConfig.get(subId).getMaxMessageSize()) {
+                throw new MmsFailureException(
+                        MmsUtils.MMS_REQUEST_NO_RETRY,
+                        MessageData.RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG);
+            }
+            writer.write(pduBytes);
+        } catch (final IOException e) {
+            if (tempFile != null) {
+                tempFile.delete();
+            }
+            LogUtil.e(TAG, "Cannot create temporary file " + tempFile.getAbsolutePath(), e);
+            throw new MmsFailureException(
+                    MmsUtils.MMS_REQUEST_AUTO_RETRY, "Cannot create raw mms file");
+        } catch (final OutOfMemoryError e) {
+            if (tempFile != null) {
+                tempFile.delete();
+            }
+            LogUtil.e(TAG, "Out of memory in composing PDU", e);
+            throw new MmsFailureException(
+                    MmsUtils.MMS_REQUEST_MANUAL_RETRY,
+                    MessageData.RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG);
+        } finally {
+            if (writer != null) {
+                try {
+                    writer.close();
+                } catch (final IOException e) {
+                    // no action we can take here
+                }
+            }
+        }
+        return contentUri;
+    }
+
+    public static SendConf parseSendConf(byte[] response, int subId) {
+        if (response != null) {
+            final GenericPdu respPdu = new PduParser(
+                    response, MmsConfig.get(subId).getSupportMmsContentDisposition()).parse();
+            if (respPdu != null) {
+                if (respPdu instanceof SendConf) {
+                    return (SendConf) respPdu;
+                } else {
+                    LogUtil.e(TAG, "MmsSender: send response not SendConf");
+                }
+            } else {
+                // Invalid PDU
+                LogUtil.e(TAG, "MmsSender: send invalid response");
+            }
+        }
+        // Empty or invalid response
+        return null;
+    }
+
+    /**
+     * Download an MMS message.
+     *
+     * @param context Context
+     * @param contentLocation The url of the MMS message
+     * @throws MmsFailureException
+     * @throws InvalidHeaderValueException
+     */
+    public static void downloadMms(final Context context, final int subId,
+            final String contentLocation, Bundle extras) throws MmsFailureException,
+            InvalidHeaderValueException {
+        final Uri requestUri = Uri.parse(contentLocation);
+        final Uri contentUri = MmsFileProvider.buildRawMmsUri();
+
+        final Intent downloadedIntent = new Intent(SendStatusReceiver.MMS_DOWNLOADED_ACTION,
+                requestUri,
+                context,
+                SendStatusReceiver.class);
+        downloadedIntent.putExtra(SendMessageAction.EXTRA_CONTENT_URI, contentUri);
+        if (extras != null) {
+            downloadedIntent.putExtras(extras);
+        }
+        final PendingIntent downloadedPendingIntent = PendingIntent.getBroadcast(
+                context,
+                0 /*request code*/,
+                downloadedIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        MmsManager.downloadMultimediaMessage(subId, context, contentLocation, contentUri,
+                downloadedPendingIntent);
+    }
+
+    public static RetrieveConf parseRetrieveConf(byte[] data, int subId) {
+        if (data != null) {
+            final GenericPdu pdu = new PduParser(
+                    data, MmsConfig.get(subId).getSupportMmsContentDisposition()).parse();
+            if (pdu != null) {
+                if (pdu instanceof RetrieveConf) {
+                    return (RetrieveConf) pdu;
+                } else {
+                    LogUtil.e(TAG, "MmsSender: downloaded pdu not RetrieveConf: "
+                            + pdu.getClass().getName());
+                }
+            } else {
+                LogUtil.e(TAG, "MmsSender: downloaded pdu could not be parsed (invalid)");
+            }
+        }
+        LogUtil.e(TAG, "MmsSender: downloaded pdu is empty");
+        return null;
+    }
+
+    // Process different result code from platform MMS service
+    public static int getErrorResultStatus(int resultCode, int httpStatusCode) {
+        Assert.isFalse(resultCode == Activity.RESULT_OK);
+        switch (resultCode) {
+            case SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS:
+            case SmsManager.MMS_ERROR_IO_ERROR:
+                return MmsUtils.MMS_REQUEST_AUTO_RETRY;
+            case SmsManager.MMS_ERROR_INVALID_APN:
+            case SmsManager.MMS_ERROR_CONFIGURATION_ERROR:
+            case SmsManager.MMS_ERROR_NO_DATA_NETWORK:
+            case SmsManager.MMS_ERROR_UNSPECIFIED:
+                return MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+            case SmsManager.MMS_ERROR_HTTP_FAILURE:
+                if (httpStatusCode == 404) {
+                    return MmsUtils.MMS_REQUEST_NO_RETRY;
+                } else {
+                    return MmsUtils.MMS_REQUEST_AUTO_RETRY;
+                }
+            default:
+                return MmsUtils.MMS_REQUEST_MANUAL_RETRY;
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/MmsSmsUtils.java b/src/com/android/messaging/sms/MmsSmsUtils.java
new file mode 100644
index 0000000..7719359
--- /dev/null
+++ b/src/com/android/messaging/sms/MmsSmsUtils.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.text.TextUtils;
+import android.util.Patterns;
+
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.util.LogUtil;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility functions for the Messaging Service
+ */
+public class MmsSmsUtils {
+    private MmsSmsUtils() {
+        // Forbidden being instantiated.
+    }
+
+    // An alias (or commonly called "nickname") is:
+    // Nickname must begin with a letter.
+    // Only letters a-z, numbers 0-9, or . are allowed in Nickname field.
+    public static boolean isAlias(final String string, final int subId) {
+        if (!MmsConfig.get(subId).isAliasEnabled()) {
+            return false;
+        }
+
+        final int len = string == null ? 0 : string.length();
+
+        if (len < MmsConfig.get(subId).getAliasMinChars() ||
+                len > MmsConfig.get(subId).getAliasMaxChars()) {
+            return false;
+        }
+
+        if (!Character.isLetter(string.charAt(0))) {    // Nickname begins with a letter
+            return false;
+        }
+        for (int i = 1; i < len; i++) {
+            final char c = string.charAt(i);
+            if (!(Character.isLetterOrDigit(c) || c == '.')) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * mailbox         =       name-addr
+     * name-addr       =       [display-name] angle-addr
+     * angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS]
+     */
+    public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+            Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
+    public static String extractAddrSpec(final String address) {
+        final Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
+
+        if (match.matches()) {
+            return match.group(2);
+        }
+        return address;
+    }
+
+    /**
+     * Returns true if the address is an email address
+     *
+     * @param address the input address to be tested
+     * @return true if address is an email address
+     */
+    public static boolean isEmailAddress(final String address) {
+        if (TextUtils.isEmpty(address)) {
+            return false;
+        }
+
+        final String s = extractAddrSpec(address);
+        final Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+        return match.matches();
+    }
+
+    /**
+     * This pattern is intended for searching for carrier specific phone numbers starting with star
+     * sign and digits such as the voice mail number.
+     * (e.g. *20 Chile Claro)
+     */
+    private static final Pattern PHONE_NUMBER_STARTING_WITH_STAR_PATTERN =
+            Pattern.compile("\\*[0-9]+");
+
+    /**
+     * Returns true if the number is a Phone number
+     *
+     * @param number the input number to be tested
+     * @return true if number is a Phone number
+     */
+    public static boolean isPhoneNumber(final String number) {
+        if (TextUtils.isEmpty(number)) {
+            return false;
+        }
+
+        Matcher match = Patterns.PHONE.matcher(number);
+        if (!match.matches()) {
+            match = PHONE_NUMBER_STARTING_WITH_STAR_PATTERN.matcher(number);
+            return match.matches();
+        }
+        return true;
+    }
+
+    /**
+     * Check if MMS is required when sending to email address
+     *
+     * @param destinationHasEmailAddress destination includes an email address
+     * @return true if MMS is required.
+     */
+    public static boolean getRequireMmsForEmailAddress(final boolean destinationHasEmailAddress,
+            final int subId) {
+        if (!TextUtils.isEmpty(MmsConfig.get(subId).getEmailGateway())) {
+            return false;
+        } else {
+            return destinationHasEmailAddress;
+        }
+    }
+
+    /**
+     * Helper functions for the "threads" table used by MMS and SMS.
+     */
+    public static final class Threads implements android.provider.Telephony.ThreadsColumns {
+        private static final String[] ID_PROJECTION = { BaseColumns._ID };
+        private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
+                "content://mms-sms/threadID");
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(
+                android.provider.Telephony.MmsSms.CONTENT_URI, "conversations");
+
+        // No one should construct an instance of this class.
+        private Threads() {
+        }
+
+        /**
+         * This is a single-recipient version of
+         * getOrCreateThreadId.  It's convenient for use with SMS
+         * messages.
+         */
+        public static long getOrCreateThreadId(final Context context, final String recipient) {
+            final Set<String> recipients = new HashSet<String>();
+
+            recipients.add(recipient);
+            return getOrCreateThreadId(context, recipients);
+        }
+
+        /**
+         * Given the recipients list and subject of an unsaved message,
+         * return its thread ID.  If the message starts a new thread,
+         * allocate a new thread ID.  Otherwise, use the appropriate
+         * existing thread ID.
+         *
+         * Find the thread ID of the same set of recipients (in
+         * any order, without any additions). If one
+         * is found, return it.  Otherwise, return a unique thread ID.
+         */
+        public static long getOrCreateThreadId(
+                final Context context, final Set<String> recipients) {
+            final Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+            for (String recipient : recipients) {
+                if (isEmailAddress(recipient)) {
+                    recipient = extractAddrSpec(recipient);
+                }
+
+                uriBuilder.appendQueryParameter("recipient", recipient);
+            }
+
+            final Uri uri = uriBuilder.build();
+            //if (DEBUG) Rlog.v(TAG, "getOrCreateThreadId uri: " + uri);
+
+            final Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+                    uri, ID_PROJECTION, null, null, null);
+            if (cursor != null) {
+                try {
+                    if (cursor.moveToFirst()) {
+                        return cursor.getLong(0);
+                    } else {
+                        LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG,
+                                "getOrCreateThreadId returned no rows!");
+                    }
+                } finally {
+                    cursor.close();
+                }
+            }
+
+            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "getOrCreateThreadId failed with "
+                    + LogUtil.sanitizePII(recipients.toString()));
+            throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/MmsUtils.java b/src/com/android/messaging/sms/MmsUtils.java
new file mode 100644
index 0000000..32f0616
--- /dev/null
+++ b/src/com/android/messaging/sms/MmsUtils.java
@@ -0,0 +1,2657 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.provider.Telephony.Mms;
+import android.provider.Telephony.Sms;
+import android.provider.Telephony.Threads;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.text.util.Rfc822Token;
+import android.text.util.Rfc822Tokenizer;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.action.DownloadMmsAction;
+import com.android.messaging.datamodel.action.SendMessageAction;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.InvalidHeaderValueException;
+import com.android.messaging.mmslib.MmsException;
+import com.android.messaging.mmslib.SqliteWrapper;
+import com.android.messaging.mmslib.pdu.CharacterSets;
+import com.android.messaging.mmslib.pdu.EncodedStringValue;
+import com.android.messaging.mmslib.pdu.GenericPdu;
+import com.android.messaging.mmslib.pdu.NotificationInd;
+import com.android.messaging.mmslib.pdu.PduBody;
+import com.android.messaging.mmslib.pdu.PduComposer;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.mmslib.pdu.PduParser;
+import com.android.messaging.mmslib.pdu.PduPart;
+import com.android.messaging.mmslib.pdu.PduPersister;
+import com.android.messaging.mmslib.pdu.RetrieveConf;
+import com.android.messaging.mmslib.pdu.SendConf;
+import com.android.messaging.mmslib.pdu.SendReq;
+import com.android.messaging.sms.SmsSender.SendResult;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.EmailAddress;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.ImageUtils.ImageResizer;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaMetadataRetrieverWrapper;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.google.common.base.Joiner;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Utils for sending sms/mms messages.
+ */
+public class MmsUtils {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    public static final boolean DEFAULT_DELIVERY_REPORT_MODE  = false;
+    public static final boolean DEFAULT_READ_REPORT_MODE = false;
+    public static final long DEFAULT_EXPIRY_TIME_IN_SECONDS = 7 * 24 * 60 * 60;
+    public static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL;
+
+    public static final int MAX_SMS_RETRY = 3;
+
+    /**
+     * MMS request succeeded
+     */
+    public static final int MMS_REQUEST_SUCCEEDED = 0;
+    /**
+     * MMS request failed with a transient error and can be retried automatically
+     */
+    public static final int MMS_REQUEST_AUTO_RETRY = 1;
+    /**
+     * MMS request failed with an error and can be retried manually
+     */
+    public static final int MMS_REQUEST_MANUAL_RETRY = 2;
+    /**
+     * MMS request failed with a specific error and should not be retried
+     */
+    public static final int MMS_REQUEST_NO_RETRY = 3;
+
+    public static final String getRequestStatusDescription(final int status) {
+        switch (status) {
+            case MMS_REQUEST_SUCCEEDED:
+                return "SUCCEEDED";
+            case MMS_REQUEST_AUTO_RETRY:
+                return "AUTO_RETRY";
+            case MMS_REQUEST_MANUAL_RETRY:
+                return "MANUAL_RETRY";
+            case MMS_REQUEST_NO_RETRY:
+                return "NO_RETRY";
+            default:
+                return String.valueOf(status) + " (check MmsUtils)";
+        }
+    }
+
+    public static final int PDU_HEADER_VALUE_UNDEFINED = 0;
+
+    private static final int DEFAULT_DURATION = 5000; //ms
+
+    // amount of space to leave in a MMS for text and overhead.
+    private static final int MMS_MAX_SIZE_SLOP = 1024;
+    public static final long INVALID_TIMESTAMP = 0L;
+    private static String[] sNoSubjectStrings;
+
+    public static class MmsInfo {
+        public Uri mUri;
+        public int mMessageSize;
+        public PduBody mPduBody;
+    }
+
+    // Sync all remote messages apart from drafts
+    private static final String REMOTE_SMS_SELECTION = String.format(
+            Locale.US,
+            "(%s IN (%d, %d, %d, %d, %d))",
+            Sms.TYPE,
+            Sms.MESSAGE_TYPE_INBOX,
+            Sms.MESSAGE_TYPE_OUTBOX,
+            Sms.MESSAGE_TYPE_QUEUED,
+            Sms.MESSAGE_TYPE_FAILED,
+            Sms.MESSAGE_TYPE_SENT);
+
+    private static final String REMOTE_MMS_SELECTION = String.format(
+            Locale.US,
+            "((%s IN (%d, %d, %d, %d)) AND (%s IN (%d, %d, %d)))",
+            Mms.MESSAGE_BOX,
+            Mms.MESSAGE_BOX_INBOX,
+            Mms.MESSAGE_BOX_OUTBOX,
+            Mms.MESSAGE_BOX_SENT,
+            Mms.MESSAGE_BOX_FAILED,
+            Mms.MESSAGE_TYPE,
+            PduHeaders.MESSAGE_TYPE_SEND_REQ,
+            PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND,
+            PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
+
+    /**
+     * Type selection for importing sms messages.
+     *
+     * @return The SQL selection for importing sms messages
+     */
+    public static String getSmsTypeSelectionSql() {
+        return REMOTE_SMS_SELECTION;
+    }
+
+    /**
+     * Type selection for importing mms messages.
+     *
+     * @return The SQL selection for importing mms messages. This selects the message type,
+     * not including the selection on timestamp.
+     */
+    public static String getMmsTypeSelectionSql() {
+        return REMOTE_MMS_SELECTION;
+    }
+
+    // SMIL spec: http://www.w3.org/TR/SMIL3
+
+    private static final String sSmilImagePart =
+            "<par dur=\"" + DEFAULT_DURATION + "ms\">" +
+                "<img src=\"%s\" region=\"Image\" />" +
+            "</par>";
+
+    private static final String sSmilVideoPart =
+            "<par dur=\"%2$dms\">" +
+                "<video src=\"%1$s\" dur=\"%2$dms\" region=\"Image\" />" +
+            "</par>";
+
+    private static final String sSmilAudioPart =
+            "<par dur=\"%2$dms\">" +
+                    "<audio src=\"%1$s\" dur=\"%2$dms\" />" +
+            "</par>";
+
+    private static final String sSmilTextPart =
+            "<par dur=\"" + DEFAULT_DURATION + "ms\">" +
+                "<text src=\"%s\" region=\"Text\" />" +
+            "</par>";
+
+    private static final String sSmilPart =
+            "<par dur=\"" + DEFAULT_DURATION + "ms\">" +
+                "<ref src=\"%s\" />" +
+            "</par>";
+
+    private static final String sSmilTextOnly =
+            "<smil>" +
+                "<head>" +
+                    "<layout>" +
+                        "<root-layout/>" +
+                        "<region id=\"Text\" top=\"0\" left=\"0\" "
+                          + "height=\"100%%\" width=\"100%%\"/>" +
+                    "</layout>" +
+                "</head>" +
+                "<body>" +
+                       "%s" +  // constructed body goes here
+                "</body>" +
+            "</smil>";
+
+    private static final String sSmilVisualAttachmentsOnly =
+            "<smil>" +
+                "<head>" +
+                    "<layout>" +
+                        "<root-layout/>" +
+                        "<region id=\"Image\" fit=\"meet\" top=\"0\" left=\"0\" "
+                          + "height=\"100%%\" width=\"100%%\"/>" +
+                    "</layout>" +
+                "</head>" +
+                "<body>" +
+                       "%s" +  // constructed body goes here
+                "</body>" +
+            "</smil>";
+
+    private static final String sSmilVisualAttachmentsWithText =
+            "<smil>" +
+                "<head>" +
+                    "<layout>" +
+                        "<root-layout/>" +
+                        "<region id=\"Image\" fit=\"meet\" top=\"0\" left=\"0\" "
+                          + "height=\"80%%\" width=\"100%%\"/>" +
+                        "<region id=\"Text\" top=\"80%%\" left=\"0\" height=\"20%%\" "
+                          + "width=\"100%%\"/>" +
+                    "</layout>" +
+                "</head>" +
+                "<body>" +
+                       "%s" +  // constructed body goes here
+                "</body>" +
+            "</smil>";
+
+    private static final String sSmilNonVisualAttachmentsOnly =
+            "<smil>" +
+                "<head>" +
+                    "<layout>" +
+                        "<root-layout/>" +
+                    "</layout>" +
+                "</head>" +
+                "<body>" +
+                       "%s" +  // constructed body goes here
+                "</body>" +
+            "</smil>";
+
+    private static final String sSmilNonVisualAttachmentsWithText = sSmilTextOnly;
+
+    public static final String MMS_DUMP_PREFIX = "mmsdump-";
+    public static final String SMS_DUMP_PREFIX = "smsdump-";
+
+    public static final int MIN_VIDEO_BYTES_PER_SECOND = 4 * 1024;
+    public static final int MIN_IMAGE_BYTE_SIZE = 16 * 1024;
+    public static final int MAX_VIDEO_ATTACHMENT_COUNT = 1;
+
+    public static MmsInfo makePduBody(final Context context, final MessageData message,
+            final int subId) {
+        final PduBody pb = new PduBody();
+
+        // Compute data size requirements for this message: count up images and total size of
+        // non-image attachments.
+        int totalLength = 0;
+        int countImage = 0;
+        for (final MessagePartData part : message.getParts()) {
+            if (part.isAttachment()) {
+                final String contentType = part.getContentType();
+                if (ContentType.isImageType(contentType)) {
+                    countImage++;
+                } else if (ContentType.isVCardType(contentType)) {
+                    totalLength += getDataLength(context, part.getContentUri());
+                } else {
+                    totalLength += getMediaFileSize(part.getContentUri());
+                }
+            }
+        }
+        final long minSize = countImage * MIN_IMAGE_BYTE_SIZE;
+        final int byteBudget = MmsConfig.get(subId).getMaxMessageSize() - totalLength
+                - MMS_MAX_SIZE_SLOP;
+        final double budgetFactor =
+                minSize > 0 ? Math.max(1.0, byteBudget / ((double) minSize)) : 1;
+        final int bytesPerImage = (int) (budgetFactor * MIN_IMAGE_BYTE_SIZE);
+        final int widthLimit = MmsConfig.get(subId).getMaxImageWidth();
+        final int heightLimit = MmsConfig.get(subId).getMaxImageHeight();
+
+        // Actually add the attachments, shrinking images appropriately.
+        int index = 0;
+        totalLength = 0;
+        boolean hasVisualAttachment = false;
+        boolean hasNonVisualAttachment = false;
+        boolean hasText = false;
+        final StringBuilder smilBody = new StringBuilder();
+        for (final MessagePartData part : message.getParts()) {
+            String srcName;
+            if (part.isAttachment()) {
+                String contentType = part.getContentType();
+                final String extension = ContentType.getExtensionFromMimeType(contentType);
+                if (ContentType.isImageType(contentType)) {
+                    if (extension != null) {
+                        srcName = String.format("image%06d.%s", index, extension);
+                    } else {
+                        // There's a good chance that if we selected the image from our media picker
+                        // the content type is image/*. Fix the content type here for gifs so that
+                        // we only need to open the input stream once. All other gif vs static image
+                        // checks will only have to do a string comparison which is much cheaper.
+                        final boolean isGif = ImageUtils.isGif(contentType, part.getContentUri());
+                        contentType = isGif ? ContentType.IMAGE_GIF : contentType;
+                        srcName = String.format(isGif ? "image%06d.gif" : "image%06d.jpg", index);
+                    }
+                    smilBody.append(String.format(sSmilImagePart, srcName));
+                    totalLength += addPicturePart(context, pb, index, part,
+                            widthLimit, heightLimit, bytesPerImage, srcName, contentType);
+                    hasVisualAttachment = true;
+                } else if (ContentType.isVideoType(contentType)) {
+                    srcName = String.format("video%06d.%s", index,
+                            extension != null ? extension : "mp4");
+                    final int length = addVideoPart(context, pb, part, srcName);
+                    totalLength += length;
+                    smilBody.append(String.format(sSmilVideoPart, srcName,
+                            getMediaDurationMs(context, part, DEFAULT_DURATION)));
+                    hasVisualAttachment = true;
+                } else if (ContentType.isVCardType(contentType)) {
+                    srcName = String.format("contact%06d.vcf", index);
+                    totalLength += addVCardPart(context, pb, part, srcName);
+                    smilBody.append(String.format(sSmilPart, srcName));
+                    hasNonVisualAttachment = true;
+                } else if (ContentType.isAudioType(contentType)) {
+                    srcName = String.format("recording%06d.%s",
+                            index, extension != null ? extension : "amr");
+                    totalLength += addOtherPart(context, pb, part, srcName);
+                    final int duration = getMediaDurationMs(context, part, -1);
+                    Assert.isTrue(duration != -1);
+                    smilBody.append(String.format(sSmilAudioPart, srcName, duration));
+                    hasNonVisualAttachment = true;
+                } else {
+                    srcName = String.format("other%06d.dat", index);
+                    totalLength += addOtherPart(context, pb, part, srcName);
+                    smilBody.append(String.format(sSmilPart, srcName));
+                }
+                index++;
+            }
+            if (!TextUtils.isEmpty(part.getText())) {
+                hasText = true;
+            }
+        }
+
+        if (hasText) {
+            final String srcName = String.format("text.%06d.txt", index);
+            final String text = message.getMessageText();
+            totalLength += addTextPart(context, pb, text, srcName);
+
+            // Append appropriate SMIL to the body.
+            smilBody.append(String.format(sSmilTextPart, srcName));
+        }
+
+        final String smilTemplate = getSmilTemplate(hasVisualAttachment,
+                hasNonVisualAttachment, hasText);
+        addSmilPart(pb, smilTemplate, smilBody.toString());
+
+        final MmsInfo mmsInfo = new MmsInfo();
+        mmsInfo.mPduBody = pb;
+        mmsInfo.mMessageSize = totalLength;
+
+        return mmsInfo;
+    }
+
+    private static int getMediaDurationMs(final Context context, final MessagePartData part,
+            final int defaultDurationMs) {
+        Assert.notNull(context);
+        Assert.notNull(part);
+        Assert.isTrue(ContentType.isAudioType(part.getContentType()) ||
+                ContentType.isVideoType(part.getContentType()));
+
+        final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
+        try {
+            retriever.setDataSource(part.getContentUri());
+            return retriever.extractInteger(
+                    MediaMetadataRetriever.METADATA_KEY_DURATION, defaultDurationMs);
+        } catch (final IOException e) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Error extracting duration from " + part.getContentUri(), e);
+            return defaultDurationMs;
+        } finally {
+            retriever.release();
+        }
+    }
+
+    private static void setPartContentLocationAndId(final PduPart part, final String srcName) {
+        // Set Content-Location.
+        part.setContentLocation(srcName.getBytes());
+
+        // Set Content-Id.
+        final int index = srcName.lastIndexOf(".");
+        final String contentId = (index == -1) ? srcName : srcName.substring(0, index);
+        part.setContentId(contentId.getBytes());
+    }
+
+    private static int addTextPart(final Context context, final PduBody pb,
+            final String text, final String srcName) {
+        final PduPart part = new PduPart();
+
+        // Set Charset if it's a text media.
+        part.setCharset(CharacterSets.UTF_8);
+
+        // Set Content-Type.
+        part.setContentType(ContentType.TEXT_PLAIN.getBytes());
+
+        // Set Content-Location.
+        setPartContentLocationAndId(part, srcName);
+
+        part.setData(text.getBytes());
+
+        pb.addPart(part);
+
+        return part.getData().length;
+    }
+
+    private static int addPicturePart(final Context context, final PduBody pb, final int index,
+            final MessagePartData messagePart, int widthLimit, int heightLimit,
+            final int maxPartSize, final String srcName, final String contentType) {
+        final Uri imageUri = messagePart.getContentUri();
+        final int width = messagePart.getWidth();
+        final int height = messagePart.getHeight();
+
+        // Swap the width and height limits to match the orientation of the image so we scale the
+        // picture as little as possible.
+        if ((height > width) != (heightLimit > widthLimit)) {
+            final int temp = widthLimit;
+            widthLimit = heightLimit;
+            heightLimit = temp;
+        }
+
+        final int orientation = ImageUtils.getOrientation(context, imageUri);
+        int imageSize = getDataLength(context, imageUri);
+        if (imageSize <= 0) {
+            LogUtil.e(TAG, "Can't get image", new Exception());
+            return 0;
+        }
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "addPicturePart size: " + imageSize + " width: "
+                    + width + " widthLimit: " + widthLimit
+                    + " height: " + height
+                    + " heightLimit: " + heightLimit);
+        }
+
+        PduPart part;
+        // Check if we're already within the limits - in which case we don't need to resize.
+        // The size can be zero here, even when the media has content. See the comment in
+        // MediaModel.initMediaSize. Sometimes it'll compute zero and it's costly to read the
+        // whole stream to compute the size. When we call getResizedImageAsPart(), we'll correctly
+        // set the size.
+        if (imageSize <= maxPartSize &&
+                width <= widthLimit &&
+                height <= heightLimit &&
+                (orientation == android.media.ExifInterface.ORIENTATION_UNDEFINED ||
+                orientation == android.media.ExifInterface.ORIENTATION_NORMAL)) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "addPicturePart - already sized");
+            }
+            part = new PduPart();
+            part.setDataUri(imageUri);
+            part.setContentType(contentType.getBytes());
+        } else {
+            part = getResizedImageAsPart(widthLimit, heightLimit, maxPartSize,
+                    width, height, orientation, imageUri, context, contentType);
+            if (part == null) {
+                final OutOfMemoryError e = new OutOfMemoryError();
+                LogUtil.e(TAG, "Can't resize image: not enough memory?", e);
+                throw e;
+            }
+            imageSize = part.getData().length;
+        }
+
+        setPartContentLocationAndId(part, srcName);
+
+        pb.addPart(index, part);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "addPicturePart size: " + imageSize);
+        }
+
+        return imageSize;
+    }
+
+    private static void addPartForUri(final Context context, final PduBody pb,
+            final String srcName, final Uri uri, final String contentType) {
+        final PduPart part = new PduPart();
+        part.setDataUri(uri);
+        part.setContentType(contentType.getBytes());
+
+        setPartContentLocationAndId(part, srcName);
+
+        pb.addPart(part);
+    }
+
+    private static int addVCardPart(final Context context, final PduBody pb,
+            final MessagePartData messagePart, final String srcName) {
+        final Uri vcardUri = messagePart.getContentUri();
+        final String contentType = messagePart.getContentType();
+        final int vcardSize = getDataLength(context, vcardUri);
+        if (vcardSize <= 0) {
+            LogUtil.e(TAG, "Can't get vcard", new Exception());
+            return 0;
+        }
+
+        addPartForUri(context, pb, srcName, vcardUri, contentType);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "addVCardPart size: " + vcardSize);
+        }
+
+        return vcardSize;
+    }
+
+    /**
+     * Add video part recompressing video if necessary.  If recompression fails, part is not
+     * added.
+     */
+    private static int addVideoPart(final Context context, final PduBody pb,
+            final MessagePartData messagePart, final String srcName) {
+        final Uri attachmentUri = messagePart.getContentUri();
+        String contentType = messagePart.getContentType();
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "addPart attachmentUrl: " + attachmentUri.toString());
+        }
+
+        if (TextUtils.isEmpty(contentType)) {
+            contentType = ContentType.VIDEO_3G2;
+        }
+
+        addPartForUri(context, pb, srcName, attachmentUri, contentType);
+        return (int) getMediaFileSize(attachmentUri);
+    }
+
+    private static int addOtherPart(final Context context, final PduBody pb,
+            final MessagePartData messagePart, final String srcName) {
+        final Uri attachmentUri = messagePart.getContentUri();
+        final String contentType = messagePart.getContentType();
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "addPart attachmentUrl: " + attachmentUri.toString());
+        }
+
+        final int dataSize = (int) getMediaFileSize(attachmentUri);
+
+        addPartForUri(context, pb, srcName, attachmentUri, contentType);
+
+        return dataSize;
+    }
+
+    private static void addSmilPart(final PduBody pb, final String smilTemplate,
+            final String smilBody) {
+        final PduPart smilPart = new PduPart();
+        smilPart.setContentId("smil".getBytes());
+        smilPart.setContentLocation("smil.xml".getBytes());
+        smilPart.setContentType(ContentType.APP_SMIL.getBytes());
+        final String smil = String.format(smilTemplate, smilBody);
+        smilPart.setData(smil.getBytes());
+        pb.addPart(0, smilPart);
+    }
+
+    private static String getSmilTemplate(final boolean hasVisualAttachments,
+            final boolean hasNonVisualAttachments, final boolean hasText) {
+        if (hasVisualAttachments) {
+            return hasText ? sSmilVisualAttachmentsWithText : sSmilVisualAttachmentsOnly;
+        }
+        if (hasNonVisualAttachments) {
+            return hasText ? sSmilNonVisualAttachmentsWithText : sSmilNonVisualAttachmentsOnly;
+        }
+        return sSmilTextOnly;
+    }
+
+    private static int getDataLength(final Context context, final Uri uri) {
+        InputStream is = null;
+        try {
+            is = context.getContentResolver().openInputStream(uri);
+            try {
+                return is == null ? 0 : is.available();
+            } catch (final IOException e) {
+                LogUtil.e(TAG, "getDataLength couldn't stream: " + uri, e);
+            }
+        } catch (final FileNotFoundException e) {
+            LogUtil.e(TAG, "getDataLength couldn't open: " + uri, e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (final IOException e) {
+                    LogUtil.e(TAG, "getDataLength couldn't close: " + uri, e);
+                }
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Returns {@code true} if group mms is turned on,
+     * {@code false} otherwise.
+     *
+     * For the group mms feature to be enabled, the following must be true:
+     *  1. the feature is enabled in mms_config.xml (currently on by default)
+     *  2. the feature is enabled in the SMS settings page
+     *
+     * @return true if group mms is supported
+     */
+    public static boolean groupMmsEnabled(final int subId) {
+        final Context context = Factory.get().getApplicationContext();
+        final Resources resources = context.getResources();
+        final BuglePrefs prefs = BuglePrefs.getSubscriptionPrefs(subId);
+        final String groupMmsKey = resources.getString(R.string.group_mms_pref_key);
+        final boolean groupMmsEnabledDefault = resources.getBoolean(R.bool.group_mms_pref_default);
+        final boolean groupMmsPrefOn = prefs.getBoolean(groupMmsKey, groupMmsEnabledDefault);
+        return MmsConfig.get(subId).getGroupMmsEnabled() && groupMmsPrefOn;
+    }
+
+    /**
+     * Get a version of this image resized to fit the given dimension and byte-size limits. Note
+     * that the content type of the resulting PduPart may not be the same as the content type of
+     * this UriImage; always call {@link PduPart#getContentType()} to get the new content type.
+     *
+     * @param widthLimit The width limit, in pixels
+     * @param heightLimit The height limit, in pixels
+     * @param byteLimit The binary size limit, in bytes
+     * @param width The image width, in pixels
+     * @param height The image height, in pixels
+     * @param orientation Orientation constant from ExifInterface for rotating or flipping the
+     *                    image
+     * @param imageUri Uri to the image data
+     * @param context Needed to open the image
+     * @return A new PduPart containing the resized image data
+     */
+    private static PduPart getResizedImageAsPart(final int widthLimit,
+            final int heightLimit, final int byteLimit, final int width, final int height,
+            final int orientation, final Uri imageUri, final Context context, final String contentType) {
+        final PduPart part = new PduPart();
+
+        final byte[] data = ImageResizer.getResizedImageData(width, height, orientation,
+                widthLimit, heightLimit, byteLimit, imageUri, context, contentType);
+        if (data == null) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "Resize image failed.");
+            }
+            return null;
+        }
+
+        part.setData(data);
+        // Any static images will be compressed into a jpeg
+        final String contentTypeOfResizedImage = ImageUtils.isGif(contentType, imageUri)
+                ? ContentType.IMAGE_GIF : ContentType.IMAGE_JPEG;
+        part.setContentType(contentTypeOfResizedImage.getBytes());
+
+        return part;
+    }
+
+    /**
+     * Get media file size
+     */
+    public static long getMediaFileSize(final Uri uri) {
+        final Context context = Factory.get().getApplicationContext();
+        AssetFileDescriptor fd = null;
+        try {
+            fd = context.getContentResolver().openAssetFileDescriptor(uri, "r");
+            if (fd != null) {
+                return fd.getParcelFileDescriptor().getStatSize();
+            }
+        } catch (final FileNotFoundException e) {
+            LogUtil.e(TAG, "MmsUtils.getMediaFileSize: cound not find media file: " + e, e);
+        } finally {
+            if (fd != null) {
+                try {
+                    fd.close();
+                } catch (final IOException e) {
+                    LogUtil.e(TAG, "MmsUtils.getMediaFileSize: failed to close " + e, e);
+                }
+            }
+        }
+        return 0L;
+    }
+
+    // Code for extracting the actual phone numbers for the participants in a conversation,
+    // given a thread id.
+
+    private static final Uri ALL_THREADS_URI =
+            Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
+
+    private static final String[] RECIPIENTS_PROJECTION = {
+        Threads._ID,
+        Threads.RECIPIENT_IDS
+    };
+
+    private static final int RECIPIENT_IDS  = 1;
+
+    public static List<String> getRecipientsByThread(final long threadId) {
+        final String spaceSepIds = getRawRecipientIdsForThread(threadId);
+        if (!TextUtils.isEmpty(spaceSepIds)) {
+            final Context context = Factory.get().getApplicationContext();
+            return getAddresses(context, spaceSepIds);
+        }
+        return null;
+    }
+
+    // NOTE: There are phones on which you can't get the recipients from the thread id for SMS
+    // until you have a message in the conversation!
+    public static String getRawRecipientIdsForThread(final long threadId) {
+        if (threadId <= 0) {
+            return null;
+        }
+        final Context context = Factory.get().getApplicationContext();
+        final ContentResolver cr = context.getContentResolver();
+        final Cursor thread = cr.query(
+                ALL_THREADS_URI,
+                RECIPIENTS_PROJECTION, "_id=?", new String[] { String.valueOf(threadId) }, null);
+        if (thread != null) {
+            try {
+                if (thread.moveToFirst()) {
+                    // recipientIds will be a space-separated list of ids into the
+                    // canonical addresses table.
+                    return thread.getString(RECIPIENT_IDS);
+                }
+            } finally {
+                thread.close();
+            }
+        }
+        return null;
+    }
+
+    private static final Uri SINGLE_CANONICAL_ADDRESS_URI =
+            Uri.parse("content://mms-sms/canonical-address");
+
+    private static List<String> getAddresses(final Context context, final String spaceSepIds) {
+        final List<String> numbers = new ArrayList<String>();
+        final String[] ids = spaceSepIds.split(" ");
+        for (final String id : ids) {
+            long longId;
+
+            try {
+                longId = Long.parseLong(id);
+                if (longId < 0) {
+                    LogUtil.e(TAG, "MmsUtils.getAddresses: invalid id " + longId);
+                    continue;
+                }
+            } catch (final NumberFormatException ex) {
+                LogUtil.e(TAG, "MmsUtils.getAddresses: invalid id. " + ex, ex);
+                // skip this id
+                continue;
+            }
+
+            // TODO: build a single query where we get all the addresses at once.
+            Cursor c = null;
+            try {
+                c = context.getContentResolver().query(
+                        ContentUris.withAppendedId(SINGLE_CANONICAL_ADDRESS_URI, longId),
+                        null, null, null, null);
+            } catch (final Exception e) {
+                LogUtil.e(TAG, "MmsUtils.getAddresses: query failed for id " + longId, e);
+            }
+            if (c != null) {
+                try {
+                    if (c.moveToFirst()) {
+                        final String number = c.getString(0);
+                        if (!TextUtils.isEmpty(number)) {
+                            numbers.add(number);
+                        } else {
+                            LogUtil.w(TAG, "Canonical MMS/SMS address is empty for id: " + longId);
+                        }
+                    }
+                } finally {
+                    c.close();
+                }
+            }
+        }
+        if (numbers.isEmpty()) {
+            LogUtil.w(TAG, "No MMS addresses found from ids string [" + spaceSepIds + "]");
+        }
+        return numbers;
+    }
+
+    // Get telephony SMS thread ID
+    public static long getOrCreateSmsThreadId(final Context context, final String dest) {
+        // use destinations to determine threadId
+        final Set<String> recipients = new HashSet<String>();
+        recipients.add(dest);
+        try {
+            return MmsSmsUtils.Threads.getOrCreateThreadId(context, recipients);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: getting thread id failed: " + e);
+            return -1;
+        }
+    }
+
+    // Get telephony SMS thread ID
+    public static long getOrCreateThreadId(final Context context, final List<String> dests) {
+        if (dests == null || dests.size() == 0) {
+            return -1;
+        }
+        // use destinations to determine threadId
+        final Set<String> recipients = new HashSet<String>(dests);
+        try {
+            return MmsSmsUtils.Threads.getOrCreateThreadId(context, recipients);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: getting thread id failed: " + e);
+            return -1;
+        }
+    }
+
+    /**
+     * Add an SMS to the given URI with thread_id specified.
+     *
+     * @param resolver the content resolver to use
+     * @param uri the URI to add the message to
+     * @param subId subId for the receiving sim
+     * @param address the address of the sender
+     * @param body the body of the message
+     * @param subject the psuedo-subject of the message
+     * @param date the timestamp for the message
+     * @param read true if the message has been read, false if not
+     * @param threadId the thread_id of the message
+     * @return the URI for the new message
+     */
+    private static Uri addMessageToUri(final ContentResolver resolver,
+            final Uri uri, final int subId, final String address, final String body,
+            final String subject, final Long date, final boolean read, final boolean seen,
+            final int status, final int type, final long threadId) {
+        final ContentValues values = new ContentValues(7);
+
+        values.put(Telephony.Sms.ADDRESS, address);
+        if (date != null) {
+            values.put(Telephony.Sms.DATE, date);
+        }
+        values.put(Telephony.Sms.READ, read ? 1 : 0);
+        values.put(Telephony.Sms.SEEN, seen ? 1 : 0);
+        values.put(Telephony.Sms.SUBJECT, subject);
+        values.put(Telephony.Sms.BODY, body);
+        if (OsUtil.isAtLeastL_MR1()) {
+            values.put(Telephony.Sms.SUBSCRIPTION_ID, subId);
+        }
+        if (status != Telephony.Sms.STATUS_NONE) {
+            values.put(Telephony.Sms.STATUS, status);
+        }
+        if (type != Telephony.Sms.MESSAGE_TYPE_ALL) {
+            values.put(Telephony.Sms.TYPE, type);
+        }
+        if (threadId != -1L) {
+            values.put(Telephony.Sms.THREAD_ID, threadId);
+        }
+        return resolver.insert(uri, values);
+    }
+
+    // Insert an SMS message to telephony
+    public static Uri insertSmsMessage(final Context context, final Uri uri, final int subId,
+            final String dest, final String text, final long timestamp, final int status,
+            final int type, final long threadId) {
+        Uri response = null;
+        try {
+            response = addMessageToUri(context.getContentResolver(), uri, subId, dest,
+                    text, null /* subject */, timestamp, true /* read */,
+                    true /* seen */, status, type, threadId);
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "Mmsutils: Inserted SMS message into telephony (type = " + type + ")"
+                        + ", uri: " + response);
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsUtils: persist sms message failure " + e, e);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: persist sms message failure " + e, e);
+        }
+        return response;
+    }
+
+    // Update SMS message type in telephony; returns true if it succeeded.
+    public static boolean updateSmsMessageSendingStatus(final Context context, final Uri uri,
+            final int type, final long date) {
+        try {
+            final ContentResolver resolver = context.getContentResolver();
+            final ContentValues values = new ContentValues(2);
+
+            values.put(Telephony.Sms.TYPE, type);
+            values.put(Telephony.Sms.DATE, date);
+            final int cnt = resolver.update(uri, values, null, null);
+            if (cnt == 1) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "Mmsutils: Updated sending SMS " + uri + "; type = " + type
+                            + ", date = " + date + " (millis since epoch)");
+                }
+                return true;
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsUtils: update sms message failure " + e, e);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: update sms message failure " + e, e);
+        }
+        return false;
+    }
+
+    // Persist a sent MMS message in telephony
+    private static Uri insertSendReq(final Context context, final GenericPdu pdu, final int subId,
+            final String subPhoneNumber) {
+        final PduPersister persister = PduPersister.getPduPersister(context);
+        Uri uri = null;
+        try {
+            // Persist the PDU
+            uri = persister.persist(
+                    pdu,
+                    Mms.Sent.CONTENT_URI,
+                    subId,
+                    subPhoneNumber,
+                    null/*preOpenedFiles*/);
+            // Update mms table to reflect sent messages are always seen and read
+            final ContentValues values = new ContentValues(1);
+            values.put(Mms.READ, 1);
+            values.put(Mms.SEEN, 1);
+            SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null);
+        } catch (final MmsException e) {
+            LogUtil.e(TAG, "MmsUtils: persist mms sent message failure " + e, e);
+        }
+        return uri;
+    }
+
+    // Persist a received MMS message in telephony
+    public static Uri insertReceivedMmsMessage(final Context context,
+            final RetrieveConf retrieveConf, final int subId, final String subPhoneNumber,
+            final long receivedTimestampInSeconds, final long expiry, final String transactionId) {
+        final PduPersister persister = PduPersister.getPduPersister(context);
+        Uri uri = null;
+        try {
+            uri = persister.persist(
+                    retrieveConf,
+                    Mms.Inbox.CONTENT_URI,
+                    subId,
+                    subPhoneNumber,
+                    null/*preOpenedFiles*/);
+
+            final ContentValues values = new ContentValues(3);
+            // Update mms table with local time instead of PDU time
+            values.put(Mms.DATE, receivedTimestampInSeconds);
+            // Also update the transaction id and the expiry from NotificationInd so that
+            // wap push dedup would work even after the wap push is deleted.
+            values.put(Mms.TRANSACTION_ID, transactionId);
+            values.put(Mms.EXPIRY, expiry);
+            SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null);
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "MmsUtils: Inserted MMS message into telephony, uri: " + uri);
+            }
+        } catch (final MmsException e) {
+            LogUtil.e(TAG, "MmsUtils: persist mms received message failure " + e, e);
+            // Just returns empty uri to RetrieveMmsRequest, which triggers a permanent failure
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsUtils: update mms received message failure " + e, e);
+            // Time update failure is ignored.
+        }
+        return uri;
+    }
+
+    // Update MMS message type in telephony; returns true if it succeeded.
+    public static boolean updateMmsMessageSendingStatus(final Context context, final Uri uri,
+            final int box, final long timestampInMillis) {
+        try {
+            final ContentResolver resolver = context.getContentResolver();
+            final ContentValues values = new ContentValues();
+
+            final long timestampInSeconds = timestampInMillis / 1000L;
+            values.put(Telephony.Mms.MESSAGE_BOX, box);
+            values.put(Telephony.Mms.DATE, timestampInSeconds);
+            final int cnt = resolver.update(uri, values, null, null);
+            if (cnt == 1) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "Mmsutils: Updated sending MMS " + uri + "; box = " + box
+                            + ", date = " + timestampInSeconds + " (secs since epoch)");
+                }
+                return true;
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsUtils: update mms message failure " + e, e);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: update mms message failure " + e, e);
+        }
+        return false;
+    }
+
+    /**
+     * Parse values from a received sms message
+     *
+     * @param context
+     * @param msgs The received sms message content
+     * @param error The received sms error
+     * @return Parsed values from the message
+     */
+    public static ContentValues parseReceivedSmsMessage(
+            final Context context, final SmsMessage[] msgs, final int error) {
+        final SmsMessage sms = msgs[0];
+        final ContentValues values = new ContentValues();
+
+        values.put(Sms.ADDRESS, sms.getDisplayOriginatingAddress());
+        values.put(Sms.BODY, buildMessageBodyFromPdus(msgs));
+        if (MmsUtils.hasSmsDateSentColumn()) {
+            // TODO:: The boxing here seems unnecessary.
+            values.put(Sms.DATE_SENT, Long.valueOf(sms.getTimestampMillis()));
+        }
+        values.put(Sms.PROTOCOL, sms.getProtocolIdentifier());
+        if (sms.getPseudoSubject().length() > 0) {
+            values.put(Sms.SUBJECT, sms.getPseudoSubject());
+        }
+        values.put(Sms.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0);
+        values.put(Sms.SERVICE_CENTER, sms.getServiceCenterAddress());
+        // Error code
+        values.put(Sms.ERROR_CODE, error);
+
+        return values;
+    }
+
+    // Some providers send formfeeds in their messages. Convert those formfeeds to newlines.
+    private static String replaceFormFeeds(final String s) {
+        return s == null ? "" : s.replace('\f', '\n');
+    }
+
+    // Parse the message body from message PDUs
+    private static String buildMessageBodyFromPdus(final SmsMessage[] msgs) {
+        if (msgs.length == 1) {
+            // There is only one part, so grab the body directly.
+            return replaceFormFeeds(msgs[0].getDisplayMessageBody());
+        } else {
+            // Build up the body from the parts.
+            final StringBuilder body = new StringBuilder();
+            for (final SmsMessage msg : msgs) {
+                try {
+                    // getDisplayMessageBody() can NPE if mWrappedMessage inside is null.
+                    body.append(msg.getDisplayMessageBody());
+                } catch (final NullPointerException e) {
+                    // Nothing to do
+                }
+            }
+            return replaceFormFeeds(body.toString());
+        }
+    }
+
+    // Parse the message date
+    public static Long getMessageDate(final SmsMessage sms, long now) {
+        // Use now for the timestamp to avoid confusion with clock
+        // drift between the handset and the SMSC.
+        // Check to make sure the system is giving us a non-bogus time.
+        final Calendar buildDate = new GregorianCalendar(2011, 8, 18);    // 18 Sep 2011
+        final Calendar nowDate = new GregorianCalendar();
+        nowDate.setTimeInMillis(now);
+        if (nowDate.before(buildDate)) {
+            // It looks like our system clock isn't set yet because the current time right now
+            // is before an arbitrary time we made this build. Instead of inserting a bogus
+            // receive time in this case, use the timestamp of when the message was sent.
+            now = sms.getTimestampMillis();
+        }
+        return now;
+    }
+
+    /**
+     * cleanseMmsSubject will take a subject that's says, "<Subject: no subject>", and return
+     * a null string. Otherwise it will return the original subject string.
+     * @param resources So the function can grab string resources
+     * @param subject the raw subject
+     * @return
+     */
+    public static String cleanseMmsSubject(final Resources resources, final String subject) {
+        if (TextUtils.isEmpty(subject)) {
+            return null;
+        }
+        if (sNoSubjectStrings == null) {
+            sNoSubjectStrings =
+                    resources.getStringArray(R.array.empty_subject_strings);
+        }
+        for (final String noSubjectString : sNoSubjectStrings) {
+            if (subject.equalsIgnoreCase(noSubjectString)) {
+                return null;
+            }
+        }
+        return subject;
+    }
+
+    /**
+     * @return Whether to auto retrieve MMS
+     */
+    public static boolean allowMmsAutoRetrieve(final int subId) {
+        final Context context = Factory.get().getApplicationContext();
+        final Resources resources = context.getResources();
+        final BuglePrefs prefs = BuglePrefs.getSubscriptionPrefs(subId);
+        final boolean autoRetrieve = prefs.getBoolean(
+                resources.getString(R.string.auto_retrieve_mms_pref_key),
+                resources.getBoolean(R.bool.auto_retrieve_mms_pref_default));
+        if (autoRetrieve) {
+            final boolean autoRetrieveInRoaming = prefs.getBoolean(
+                    resources.getString(R.string.auto_retrieve_mms_when_roaming_pref_key),
+                    resources.getBoolean(R.bool.auto_retrieve_mms_when_roaming_pref_default));
+            final PhoneUtils phoneUtils = PhoneUtils.get(subId);
+            if ((autoRetrieveInRoaming && phoneUtils.isDataRoamingEnabled())
+                    || !phoneUtils.isRoaming()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Parse the message row id from a message Uri.
+     *
+     * @param messageUri The input Uri
+     * @return The message row id if valid, otherwise -1
+     */
+    public static long parseRowIdFromMessageUri(final Uri messageUri) {
+        try {
+            if (messageUri != null) {
+                return ContentUris.parseId(messageUri);
+            }
+        } catch (final UnsupportedOperationException e) {
+            // Nothing to do
+        } catch (final NumberFormatException e) {
+            // Nothing to do
+        }
+        return -1;
+    }
+
+    public static SmsMessage getSmsMessageFromDeliveryReport(final Intent intent) {
+        final byte[] pdu = intent.getByteArrayExtra("pdu");
+        final String format = intent.getStringExtra("format");
+        return OsUtil.isAtLeastM()
+                ? SmsMessage.createFromPdu(pdu, format)
+                : SmsMessage.createFromPdu(pdu);
+    }
+
+    /**
+     * Update the status and date_sent column of sms message in telephony provider
+     *
+     * @param smsMessageUri
+     * @param status
+     * @param timeSentInMillis
+     */
+    public static void updateSmsStatusAndDateSent(final Uri smsMessageUri, final int status,
+            final long timeSentInMillis) {
+        if (smsMessageUri == null) {
+            return;
+        }
+        final ContentValues values = new ContentValues();
+        values.put(Sms.STATUS, status);
+        if (MmsUtils.hasSmsDateSentColumn()) {
+            values.put(Sms.DATE_SENT, timeSentInMillis);
+        }
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        resolver.update(smsMessageUri, values, null/*where*/, null/*selectionArgs*/);
+    }
+
+    /**
+     * Get the SQL selection statement for matching messages with media.
+     *
+     * Example for MMS part table:
+     * "((ct LIKE 'image/%')
+     *   OR (ct LIKE 'video/%')
+     *   OR (ct LIKE 'audio/%')
+     *   OR (ct='application/ogg'))
+     *
+     * @param contentTypeColumn The content-type column name
+     * @return The SQL selection statement for matching media types: image, video, audio
+     */
+    public static String getMediaTypeSelectionSql(final String contentTypeColumn) {
+        return String.format(
+                Locale.US,
+                "((%s LIKE '%s') OR (%s LIKE '%s') OR (%s LIKE '%s') OR (%s='%s'))",
+                contentTypeColumn,
+                "image/%",
+                contentTypeColumn,
+                "video/%",
+                contentTypeColumn,
+                "audio/%",
+                contentTypeColumn,
+                ContentType.AUDIO_OGG);
+    }
+
+    // Max number of operands per SQL query for deleting SMS messages
+    public static final int MAX_IDS_PER_QUERY = 128;
+
+    /**
+     * Delete MMS messages with media parts.
+     *
+     * Because the telephony provider constraints, we can't use JOIN and delete messages in one
+     * shot. We have to do a query first and then batch delete the messages based on IDs.
+     *
+     * @return The count of messages deleted.
+     */
+    public static int deleteMediaMessages() {
+        // Do a query first
+        //
+        // The WHERE clause has two parts:
+        // The first part is to select the exact same types of MMS messages as when we import them
+        // (so that we don't delete messages that are not in local database)
+        // The second part is to select MMS with media parts, including image, video and audio
+        final String selection = String.format(
+                Locale.US,
+                "%s AND (%s IN (SELECT %s FROM part WHERE %s))",
+                getMmsTypeSelectionSql(),
+                Mms._ID,
+                Mms.Part.MSG_ID,
+                getMediaTypeSelectionSql(Mms.Part.CONTENT_TYPE));
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        final Cursor cursor = resolver.query(Mms.CONTENT_URI,
+                new String[]{ Mms._ID },
+                selection,
+                null/*selectionArgs*/,
+                null/*sortOrder*/);
+        int deleted = 0;
+        if (cursor != null) {
+            final long[] messageIds = new long[cursor.getCount()];
+            try {
+                int i = 0;
+                while (cursor.moveToNext()) {
+                    messageIds[i++] = cursor.getLong(0);
+                }
+            } finally {
+                cursor.close();
+            }
+            final int totalIds = messageIds.length;
+            if (totalIds > 0) {
+                // Batch delete the messages using IDs
+                // We don't want to send all IDs at once since there is a limit on SQL statement
+                for (int start = 0; start < totalIds; start += MAX_IDS_PER_QUERY) {
+                    final int end = Math.min(start + MAX_IDS_PER_QUERY, totalIds); // excluding
+                    final int count = end - start;
+                    final String batchSelection = String.format(
+                            Locale.US,
+                            "%s IN %s",
+                            Mms._ID,
+                            getSqlInOperand(count));
+                    final String[] batchSelectionArgs =
+                            getSqlInOperandArgs(messageIds, start, count);
+                    final int deletedForBatch = resolver.delete(
+                            Mms.CONTENT_URI,
+                            batchSelection,
+                            batchSelectionArgs);
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        LogUtil.d(TAG, "deleteMediaMessages: deleting IDs = "
+                                + Joiner.on(',').skipNulls().join(batchSelectionArgs)
+                                + ", deleted = " + deletedForBatch);
+                    }
+                    deleted += deletedForBatch;
+                }
+            }
+        }
+        return deleted;
+    }
+
+    /**
+     * Get the (?,?,...) thing for the SQL IN operator by a count
+     *
+     * @param count
+     * @return
+     */
+    public static String getSqlInOperand(final int count) {
+        if (count <= 0) {
+            return null;
+        }
+        final StringBuilder sb = new StringBuilder();
+        sb.append("(?");
+        for (int i = 0; i < count - 1; i++) {
+            sb.append(",?");
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    /**
+     * Get the args for SQL IN operator from a long ID array
+     *
+     * @param ids The original long id array
+     * @param start Start of the ids to fill the args
+     * @param count Number of ids to pack
+     * @return The long array with the id args
+     */
+    private static String[] getSqlInOperandArgs(
+            final long[] ids, final int start, final int count) {
+        if (count <= 0) {
+            return null;
+        }
+        final String[] args = new String[count];
+        for (int i = 0; i < count; i++) {
+            args[i] = Long.toString(ids[start + i]);
+        }
+        return args;
+    }
+
+    /**
+     * Delete SMS and MMS messages that are earlier than a specific timestamp
+     *
+     * @param cutOffTimestampInMillis The cut-off timestamp
+     * @return Total number of messages deleted.
+     */
+    public static int deleteMessagesOlderThan(final long cutOffTimestampInMillis) {
+        int deleted = 0;
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        // Delete old SMS
+        final String smsSelection = String.format(
+                Locale.US,
+                "%s AND (%s<=%d)",
+                getSmsTypeSelectionSql(),
+                Sms.DATE,
+                cutOffTimestampInMillis);
+        deleted += resolver.delete(Sms.CONTENT_URI, smsSelection, null/*selectionArgs*/);
+        // Delete old MMS
+        final String mmsSelection = String.format(
+                Locale.US,
+                "%s AND (%s<=%d)",
+                getMmsTypeSelectionSql(),
+                Mms.DATE,
+                cutOffTimestampInMillis / 1000L);
+        deleted += resolver.delete(Mms.CONTENT_URI, mmsSelection, null/*selectionArgs*/);
+        return deleted;
+    }
+
+    /**
+     * Update the read status of SMS/MMS messages by thread and timestamp
+     *
+     * @param threadId The thread of sms/mms to change
+     * @param timestampInMillis Change the status before this timestamp
+     */
+    public static void updateSmsReadStatus(final long threadId, final long timestampInMillis) {
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        final ContentValues values = new ContentValues();
+        values.put("read", 1);
+        values.put("seen", 1); /* If you read it you saw it */
+        final String smsSelection = String.format(
+                Locale.US,
+                "%s=%d AND %s<=%d AND %s=0",
+                Sms.THREAD_ID,
+                threadId,
+                Sms.DATE,
+                timestampInMillis,
+                Sms.READ);
+        resolver.update(
+                Sms.CONTENT_URI,
+                values,
+                smsSelection,
+                null/*selectionArgs*/);
+        final String mmsSelection = String.format(
+                Locale.US,
+                "%s=%d AND %s<=%d AND %s=0",
+                Mms.THREAD_ID,
+                threadId,
+                Mms.DATE,
+                timestampInMillis / 1000L,
+                Mms.READ);
+        resolver.update(
+                Mms.CONTENT_URI,
+                values,
+                mmsSelection,
+                null/*selectionArgs*/);
+    }
+
+    /**
+     * Update the read status of a single MMS message by its URI
+     *
+     * @param mmsUri
+     * @param read
+     */
+    public static void updateReadStatusForMmsMessage(final Uri mmsUri, final boolean read) {
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        final ContentValues values = new ContentValues();
+        values.put(Mms.READ, read ? 1 : 0);
+        resolver.update(mmsUri, values, null/*where*/, null/*selectionArgs*/);
+    }
+
+    public static class AttachmentInfo {
+        public String mUrl;
+        public String mContentType;
+        public int mWidth;
+        public int mHeight;
+    }
+
+    /**
+     * Convert byte array to Java String using a charset name
+     *
+     * @param bytes
+     * @param charsetName
+     * @return
+     */
+    public static String bytesToString(final byte[] bytes, final String charsetName) {
+        if (bytes == null) {
+            return null;
+        }
+        try {
+            return new String(bytes, charsetName);
+        } catch (final UnsupportedEncodingException e) {
+            LogUtil.e(TAG, "MmsUtils.bytesToString: " + e, e);
+            return new String(bytes);
+        }
+    }
+
+    /**
+     * Convert a Java String to byte array using a charset name
+     *
+     * @param string
+     * @param charsetName
+     * @return
+     */
+    public static byte[] stringToBytes(final String string, final String charsetName) {
+        if (string == null) {
+            return null;
+        }
+        try {
+            return string.getBytes(charsetName);
+        } catch (final UnsupportedEncodingException e) {
+            LogUtil.e(TAG, "MmsUtils.stringToBytes: " + e, e);
+            return string.getBytes();
+        }
+    }
+
+    private static final String[] TEST_DATE_SENT_PROJECTION = new String[] { Sms.DATE_SENT };
+    private static Boolean sHasSmsDateSentColumn = null;
+    /**
+     * Check if date_sent column exists on ICS and above devices. We need to do a test
+     * query to figure that out since on some ICS+ devices, somehow the date_sent column does
+     * not exist. http://b/17629135 tracks the associated compliance test.
+     *
+     * @return Whether "date_sent" column exists in sms table
+     */
+    public static boolean hasSmsDateSentColumn() {
+        if (sHasSmsDateSentColumn == null) {
+            Cursor cursor = null;
+            try {
+                final Context context = Factory.get().getApplicationContext();
+                final ContentResolver resolver = context.getContentResolver();
+                cursor = SqliteWrapper.query(
+                        context,
+                        resolver,
+                        Sms.CONTENT_URI,
+                        TEST_DATE_SENT_PROJECTION,
+                        null/*selection*/,
+                        null/*selectionArgs*/,
+                        Sms.DATE_SENT + " ASC LIMIT 1");
+                sHasSmsDateSentColumn = true;
+            } catch (final SQLiteException e) {
+                LogUtil.w(TAG, "date_sent in sms table does not exist", e);
+                sHasSmsDateSentColumn = false;
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+        return sHasSmsDateSentColumn;
+    }
+
+    private static final String[] TEST_CARRIERS_PROJECTION =
+            new String[] { Telephony.Carriers.MMSC };
+    private static Boolean sUseSystemApn = null;
+    /**
+     * Check if we can access the APN data in the Telephony provider. Access was restricted in
+     * JB MR1 (and some JB MR2) devices. If we can't access the APN, we have to fall back and use
+     * a private table in our own app.
+     *
+     * @return Whether we can access the system APN table
+     */
+    public static boolean useSystemApnTable() {
+        if (sUseSystemApn == null) {
+            Cursor cursor = null;
+            try {
+                final Context context = Factory.get().getApplicationContext();
+                final ContentResolver resolver = context.getContentResolver();
+                cursor = SqliteWrapper.query(
+                        context,
+                        resolver,
+                        Telephony.Carriers.CONTENT_URI,
+                        TEST_CARRIERS_PROJECTION,
+                        null/*selection*/,
+                        null/*selectionArgs*/,
+                        null);
+                sUseSystemApn = true;
+            } catch (final SecurityException e) {
+                LogUtil.w(TAG, "Can't access system APN, using internal table", e);
+                sUseSystemApn = false;
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+        return sUseSystemApn;
+    }
+
+    // For the internal debugger only
+    public static void setUseSystemApnTable(final boolean turnOn) {
+        if (!turnOn) {
+            // We're not turning on to the system table. Instead, we're using our internal table.
+            final int osVersion = OsUtil.getApiVersion();
+            if (osVersion != android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                // We're turning on local APNs on a device where we wouldn't normally have the
+                // local APN table. Build it here.
+
+                final SQLiteDatabase database = ApnDatabase.getApnDatabase().getWritableDatabase();
+
+                // Do we already have the table?
+                Cursor cursor = null;
+                try {
+                    cursor = database.query(ApnDatabase.APN_TABLE,
+                            ApnDatabase.APN_PROJECTION,
+                            null, null, null, null, null, null);
+                } catch (final Exception e) {
+                    // Apparently there's no table, create it now.
+                    ApnDatabase.forceBuildAndLoadApnTables();
+                } finally {
+                    if (cursor != null) {
+                        cursor.close();
+                    }
+                }
+            }
+        }
+        sUseSystemApn = turnOn;
+    }
+
+    /**
+     * Checks if we should dump sms, based on both the setting and the global debug
+     * flag
+     *
+     * @return if dump sms is enabled
+     */
+    public static boolean isDumpSmsEnabled() {
+        if (!DebugUtils.isDebugEnabled()) {
+            return false;
+        }
+        return getDumpSmsOrMmsPref(R.string.dump_sms_pref_key, R.bool.dump_sms_pref_default);
+    }
+
+    /**
+     * Checks if we should dump mms, based on both the setting and the global debug
+     * flag
+     *
+     * @return if dump mms is enabled
+     */
+    public static boolean isDumpMmsEnabled() {
+        if (!DebugUtils.isDebugEnabled()) {
+            return false;
+        }
+        return getDumpSmsOrMmsPref(R.string.dump_mms_pref_key, R.bool.dump_mms_pref_default);
+    }
+
+    /**
+     * Load the value of dump sms or mms setting preference
+     */
+    private static boolean getDumpSmsOrMmsPref(final int prefKeyRes, final int defaultKeyRes) {
+        final Context context = Factory.get().getApplicationContext();
+        final Resources resources = context.getResources();
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        final String key = resources.getString(prefKeyRes);
+        final boolean defaultValue = resources.getBoolean(defaultKeyRes);
+        return prefs.getBoolean(key, defaultValue);
+    }
+
+    public static final Uri MMS_PART_CONTENT_URI = Uri.parse("content://mms/part");
+
+    /**
+     * Load MMS from telephony
+     *
+     * @param mmsUri The MMS pdu Uri
+     * @return A memory copy of the MMS pdu including parts (but not addresses)
+     */
+    public static DatabaseMessages.MmsMessage loadMms(final Uri mmsUri) {
+        final Context context = Factory.get().getApplicationContext();
+        final ContentResolver resolver = context.getContentResolver();
+        DatabaseMessages.MmsMessage mms = null;
+        Cursor cursor = null;
+        // Load pdu first
+        try {
+            cursor = SqliteWrapper.query(context, resolver,
+                    mmsUri,
+                    DatabaseMessages.MmsMessage.getProjection(),
+                    null/*selection*/, null/*selectionArgs*/, null/*sortOrder*/);
+            if (cursor != null && cursor.moveToFirst()) {
+                mms = DatabaseMessages.MmsMessage.get(cursor);
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsLoader: query pdu failure: " + e, e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        if (mms == null) {
+            return null;
+        }
+        // Load parts except SMIL
+        // TODO: we may need to load SMIL part in the future.
+        final long rowId = MmsUtils.parseRowIdFromMessageUri(mmsUri);
+        final String selection = String.format(
+                Locale.US,
+                "%s != '%s' AND %s = ?",
+                Mms.Part.CONTENT_TYPE,
+                ContentType.APP_SMIL,
+                Mms.Part.MSG_ID);
+        cursor = null;
+        try {
+            cursor = SqliteWrapper.query(context, resolver,
+                    MMS_PART_CONTENT_URI,
+                    DatabaseMessages.MmsPart.PROJECTION,
+                    selection,
+                    new String[] { Long.toString(rowId) },
+                    null/*sortOrder*/);
+            if (cursor != null) {
+                while (cursor.moveToNext()) {
+                    mms.addPart(DatabaseMessages.MmsPart.get(cursor, true/*loadMedia*/));
+                }
+            }
+        } catch (final SQLiteException e) {
+            LogUtil.e(TAG, "MmsLoader: query parts failure: " + e, e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return mms;
+    }
+
+    /**
+     * Get the sender of an MMS message
+     *
+     * @param recipients The recipient list of the message
+     * @param mmsUri The pdu uri of the MMS
+     * @return The sender phone number of the MMS
+     */
+    public static String getMmsSender(final List<String> recipients, final String mmsUri) {
+        final Context context = Factory.get().getApplicationContext();
+        // We try to avoid the database query.
+        // If this is a 1v1 conv., then the other party is the sender
+        if (recipients != null && recipients.size() == 1) {
+            return recipients.get(0);
+        }
+        // Otherwise, we have to query the MMS addr table for sender address
+        // This should only be done for a received group mms message
+        final Cursor cursor = SqliteWrapper.query(
+                context,
+                context.getContentResolver(),
+                Uri.withAppendedPath(Uri.parse(mmsUri), "addr"),
+                new String[] { Mms.Addr.ADDRESS, Mms.Addr.CHARSET },
+                Mms.Addr.TYPE + "=" + PduHeaders.FROM,
+                null/*selectionArgs*/,
+                null/*sortOrder*/);
+        if (cursor != null) {
+            try {
+                if (cursor.moveToFirst()) {
+                    return DatabaseMessages.MmsAddr.get(cursor);
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    public static int bugleStatusForMms(final boolean isOutgoing, final boolean isNotification,
+            final int messageBox) {
+        int bugleStatus = MessageData.BUGLE_STATUS_UNKNOWN;
+        // For a message we sync either
+        if (isOutgoing) {
+            if (messageBox == Mms.MESSAGE_BOX_OUTBOX || messageBox == Mms.MESSAGE_BOX_FAILED) {
+                // Not sent counts as failed and available for manual resend
+                bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_FAILED;
+            } else {
+                // Otherwise outgoing message is complete
+                bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_COMPLETE;
+            }
+        } else if (isNotification) {
+            // Incoming MMS notifications we sync count as failed and available for manual download
+            bugleStatus = MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD;
+        } else {
+            // Other incoming MMS messages are complete
+            bugleStatus = MessageData.BUGLE_STATUS_INCOMING_COMPLETE;
+        }
+        return bugleStatus;
+    }
+
+    public static MessageData createMmsMessage(final DatabaseMessages.MmsMessage mms,
+            final String conversationId, final String participantId, final String selfId,
+            final int bugleStatus) {
+        Assert.notNull(mms);
+        final boolean isNotification = (mms.mMmsMessageType ==
+                PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
+        final int rawMmsStatus = (bugleStatus < MessageData.BUGLE_STATUS_FIRST_INCOMING
+                ? mms.mRetrieveStatus : mms.mResponseStatus);
+
+        final MessageData message = MessageData.createMmsMessage(mms.getUri(),
+                participantId, selfId, conversationId, isNotification, bugleStatus,
+                mms.mContentLocation, mms.mTransactionId, mms.mPriority, mms.mSubject,
+                mms.mSeen, mms.mRead, mms.getSize(), rawMmsStatus,
+                mms.mExpiryInMillis, mms.mSentTimestampInMillis, mms.mTimestampInMillis);
+
+        for (final DatabaseMessages.MmsPart part : mms.mParts) {
+            final MessagePartData messagePart = MmsUtils.createMmsMessagePart(part);
+            // Import media and text parts (skip SMIL and others)
+            if (messagePart != null) {
+                message.addPart(messagePart);
+            }
+        }
+
+        if (!message.getParts().iterator().hasNext()) {
+            message.addPart(MessagePartData.createEmptyMessagePart());
+        }
+
+        return message;
+    }
+
+    public static MessagePartData createMmsMessagePart(final DatabaseMessages.MmsPart part) {
+        MessagePartData messagePart = null;
+        if (part.isText()) {
+            final int mmsTextLengthLimit =
+                    BugleGservices.get().getInt(BugleGservicesKeys.MMS_TEXT_LIMIT,
+                            BugleGservicesKeys.MMS_TEXT_LIMIT_DEFAULT);
+            String text = part.mText;
+            if (text != null && text.length() > mmsTextLengthLimit) {
+                // Limit the text to a reasonable value. We ran into a situation where a vcard
+                // with a photo was sent as plain text. The massive amount of text caused the
+                // app to hang, ANR, and eventually crash in native text code.
+                text = text.substring(0, mmsTextLengthLimit);
+            }
+            messagePart = MessagePartData.createTextMessagePart(text);
+        } else if (part.isMedia()) {
+            messagePart = MessagePartData.createMediaMessagePart(part.mContentType,
+                    part.getDataUri(), MessagePartData.UNSPECIFIED_SIZE,
+                    MessagePartData.UNSPECIFIED_SIZE);
+        }
+        return messagePart;
+    }
+
+    public static class StatusPlusUri {
+        // The request status to be as the result of the operation
+        // e.g. MMS_REQUEST_MANUAL_RETRY
+        public final int status;
+        // The raw telephony status
+        public final int rawStatus;
+        // The raw telephony URI
+        public final Uri uri;
+        // The operation result code from system api invocation (sent by system)
+        // or mapped from internal exception (sent by app)
+        public final int resultCode;
+
+        public StatusPlusUri(final int status, final int rawStatus, final Uri uri) {
+            this.status = status;
+            this.rawStatus = rawStatus;
+            this.uri = uri;
+            resultCode = MessageData.UNKNOWN_RESULT_CODE;
+        }
+
+        public StatusPlusUri(final int status, final int rawStatus, final Uri uri,
+                final int resultCode) {
+            this.status = status;
+            this.rawStatus = rawStatus;
+            this.uri = uri;
+            this.resultCode = resultCode;
+        }
+    }
+
+    public static class SendReqResp {
+        public SendReq mSendReq;
+        public SendConf mSendConf;
+
+        public SendReqResp(final SendReq sendReq, final SendConf sendConf) {
+            mSendReq = sendReq;
+            mSendConf = sendConf;
+        }
+    }
+
+    /**
+     * Returned when sending/downloading MMS via platform APIs. In that case, we have to wait to
+     * receive the pending intent to determine status.
+     */
+    public static final StatusPlusUri STATUS_PENDING = new StatusPlusUri(-1, -1, null);
+
+    public static StatusPlusUri downloadMmsMessage(final Context context, final Uri notificationUri,
+            final int subId, final String subPhoneNumber, final String transactionId,
+            final String contentLocation, final boolean autoDownload,
+            final long receivedTimestampInSeconds, final long expiry, Bundle extras) {
+        if (TextUtils.isEmpty(contentLocation)) {
+            LogUtil.e(TAG, "MmsUtils: Download from empty content location URL");
+            return new StatusPlusUri(
+                    MMS_REQUEST_NO_RETRY, MessageData.RAW_TELEPHONY_STATUS_UNDEFINED, null);
+        }
+        if (!isMmsDataAvailable(subId)) {
+            LogUtil.e(TAG,
+                    "MmsUtils: failed to download message, no data available");
+            return new StatusPlusUri(MMS_REQUEST_MANUAL_RETRY,
+                    MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
+                    null,
+                    SmsManager.MMS_ERROR_NO_DATA_NETWORK);
+        }
+        int status = MMS_REQUEST_MANUAL_RETRY;
+        try {
+            RetrieveConf retrieveConf = null;
+            if (DebugUtils.isDebugEnabled() &&
+                    MediaScratchFileProvider
+                            .isMediaScratchSpaceUri(Uri.parse(contentLocation))) {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "MmsUtils: Reading MMS from dump file: " + contentLocation);
+                }
+                final String fileName = Uri.parse(contentLocation).getPathSegments().get(1);
+                final byte[] data = DebugUtils.receiveFromDumpFile(fileName);
+                retrieveConf = receiveFromDumpFile(data);
+            } else {
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "MmsUtils: Downloading MMS via MMS lib API; notification "
+                            + "message: " + notificationUri);
+                }
+                if (OsUtil.isAtLeastL_MR1()) {
+                    if (subId < 0) {
+                        LogUtil.e(TAG, "MmsUtils: Incoming MMS came from unknown SIM");
+                        throw new MmsFailureException(MMS_REQUEST_NO_RETRY,
+                                "Message from unknown SIM");
+                    }
+                } else {
+                    Assert.isTrue(subId == ParticipantData.DEFAULT_SELF_SUB_ID);
+                }
+                if (extras == null) {
+                    extras = new Bundle();
+                }
+                extras.putParcelable(DownloadMmsAction.EXTRA_NOTIFICATION_URI, notificationUri);
+                extras.putInt(DownloadMmsAction.EXTRA_SUB_ID, subId);
+                extras.putString(DownloadMmsAction.EXTRA_SUB_PHONE_NUMBER, subPhoneNumber);
+                extras.putString(DownloadMmsAction.EXTRA_TRANSACTION_ID, transactionId);
+                extras.putString(DownloadMmsAction.EXTRA_CONTENT_LOCATION, contentLocation);
+                extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
+                extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
+                        receivedTimestampInSeconds);
+                extras.putLong(DownloadMmsAction.EXTRA_EXPIRY, expiry);
+
+                MmsSender.downloadMms(context, subId, contentLocation, extras);
+                return STATUS_PENDING; // Download happens asynchronously; no status to return
+            }
+            return insertDownloadedMessageAndSendResponse(context, notificationUri, subId,
+                    subPhoneNumber, transactionId, contentLocation, autoDownload,
+                    receivedTimestampInSeconds, expiry, retrieveConf);
+
+        } catch (final MmsFailureException e) {
+            LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
+            status = e.retryHint;
+        } catch (final InvalidHeaderValueException e) {
+            LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
+        }
+        return new StatusPlusUri(status, PDU_HEADER_VALUE_UNDEFINED, null);
+    }
+
+    public static StatusPlusUri insertDownloadedMessageAndSendResponse(final Context context,
+            final Uri notificationUri, final int subId, final String subPhoneNumber,
+            final String transactionId, final String contentLocation,
+            final boolean autoDownload, final long receivedTimestampInSeconds,
+            final long expiry, final RetrieveConf retrieveConf) {
+        final byte[] notificationTransactionId = stringToBytes(transactionId, "UTF-8");
+        Uri messageUri = null;
+        final int status;
+        final int retrieveStatus = retrieveConf.getRetrieveStatus();
+
+        if (retrieveStatus == PduHeaders.RETRIEVE_STATUS_OK) {
+            status = MMS_REQUEST_SUCCEEDED;
+        } else if (retrieveStatus >= PduHeaders.RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE &&
+                retrieveStatus < PduHeaders.RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE) {
+            status = MMS_REQUEST_AUTO_RETRY;
+        } else {
+            // else not meant to retry download
+            status = MMS_REQUEST_NO_RETRY;
+            LogUtil.e(TAG, "MmsUtils: failed to retrieve message; retrieveStatus: "
+                    + retrieveStatus);
+        }
+        final ContentValues values = new ContentValues(1);
+        values.put(Mms.RETRIEVE_STATUS, retrieveConf.getRetrieveStatus());
+        SqliteWrapper.update(context, context.getContentResolver(),
+                notificationUri, values, null, null);
+
+        if (status == MMS_REQUEST_SUCCEEDED) {
+            // Send response of the notification
+            if (autoDownload) {
+                sendNotifyResponseForMmsDownload(
+                        context,
+                        subId,
+                        notificationTransactionId,
+                        contentLocation,
+                        PduHeaders.STATUS_RETRIEVED);
+            } else {
+                sendAcknowledgeForMmsDownload(
+                        context, subId, retrieveConf.getTransactionId(), contentLocation);
+            }
+
+            // Insert downloaded message into telephony
+            final Uri inboxUri = MmsUtils.insertReceivedMmsMessage(context, retrieveConf, subId,
+                    subPhoneNumber, receivedTimestampInSeconds, expiry, transactionId);
+            messageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, ContentUris.parseId(inboxUri));
+        }
+        // Do nothing for MMS_REQUEST_AUTO_RETRY and MMS_REQUEST_NO_RETRY.
+
+        return new StatusPlusUri(status, retrieveStatus, messageUri);
+    }
+
+    /**
+     * Send response for MMS download - catches and ignores errors
+     */
+    public static void sendNotifyResponseForMmsDownload(final Context context, final int subId,
+            final byte[] transactionId, final String contentLocation, final int status) {
+        try {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "MmsUtils: Sending M-NotifyResp.ind for received MMS, status: "
+                        + String.format("0x%X", status));
+            }
+            if (contentLocation == null) {
+                LogUtil.w(TAG, "MmsUtils: Can't send NotifyResp; contentLocation is null");
+                return;
+            }
+            if (transactionId == null) {
+                LogUtil.w(TAG, "MmsUtils: Can't send NotifyResp; transaction id is null");
+                return;
+            }
+            if (!isMmsDataAvailable(subId)) {
+                LogUtil.w(TAG, "MmsUtils: Can't send NotifyResp; no data available");
+                return;
+            }
+            MmsSender.sendNotifyResponseForMmsDownload(
+                    context, subId, transactionId, contentLocation, status);
+        } catch (final MmsFailureException e) {
+            LogUtil.e(TAG, "sendNotifyResponseForMmsDownload: failed to retrieve message " + e, e);
+        } catch (final InvalidHeaderValueException e) {
+            LogUtil.e(TAG, "sendNotifyResponseForMmsDownload: failed to retrieve message " + e, e);
+        }
+    }
+
+    /**
+     * Send acknowledge for mms download - catched and ignores errors
+     */
+    public static void sendAcknowledgeForMmsDownload(final Context context, final int subId,
+            final byte[] transactionId, final String contentLocation) {
+        try {
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, "MmsUtils: Sending M-Acknowledge.ind for received MMS");
+            }
+            if (contentLocation == null) {
+                LogUtil.w(TAG, "MmsUtils: Can't send AckInd; contentLocation is null");
+                return;
+            }
+            if (transactionId == null) {
+                LogUtil.w(TAG, "MmsUtils: Can't send AckInd; transaction id is null");
+                return;
+            }
+            if (!isMmsDataAvailable(subId)) {
+                LogUtil.w(TAG, "MmsUtils: Can't send AckInd; no data available");
+                return;
+            }
+            MmsSender.sendAcknowledgeForMmsDownload(context, subId, transactionId, contentLocation);
+        } catch (final MmsFailureException e) {
+            LogUtil.e(TAG, "sendAcknowledgeForMmsDownload: failed to retrieve message " + e, e);
+        } catch (final InvalidHeaderValueException e) {
+            LogUtil.e(TAG, "sendAcknowledgeForMmsDownload: failed to retrieve message " + e, e);
+        }
+    }
+
+    /**
+     * Try parsing a PDU without knowing the carrier. This is useful for importing
+     * MMS or storing draft when carrier info is not available
+     *
+     * @param data The PDU data
+     * @return Parsed PDU, null if failed to parse
+     */
+    private static GenericPdu parsePduForAnyCarrier(final byte[] data) {
+        GenericPdu pdu = null;
+        try {
+            pdu = (new PduParser(data, true/*parseContentDisposition*/)).parse();
+        } catch (final RuntimeException e) {
+            LogUtil.d(TAG, "parsePduForAnyCarrier: Failed to parse PDU with content disposition",
+                    e);
+        }
+        if (pdu == null) {
+            try {
+                pdu = (new PduParser(data, false/*parseContentDisposition*/)).parse();
+            } catch (final RuntimeException e) {
+                LogUtil.d(TAG,
+                        "parsePduForAnyCarrier: Failed to parse PDU without content disposition",
+                        e);
+            }
+        }
+        return pdu;
+    }
+
+    private static RetrieveConf receiveFromDumpFile(final byte[] data) throws MmsFailureException {
+        final GenericPdu pdu = parsePduForAnyCarrier(data);
+        if (pdu == null || !(pdu instanceof RetrieveConf)) {
+            LogUtil.e(TAG, "receiveFromDumpFile: Parsing retrieved PDU failure");
+            throw new MmsFailureException(MMS_REQUEST_MANUAL_RETRY, "Failed reading dump file");
+        }
+        return (RetrieveConf) pdu;
+    }
+
+    private static boolean isMmsDataAvailable(final int subId) {
+        if (OsUtil.isAtLeastL_MR1()) {
+            // L_MR1 above may support sending mms via wifi
+            return true;
+        }
+        final PhoneUtils phoneUtils = PhoneUtils.get(subId);
+        return !phoneUtils.isAirplaneModeOn() && phoneUtils.isMobileDataEnabled();
+    }
+
+    private static boolean isSmsDataAvailable(final int subId) {
+        if (OsUtil.isAtLeastL_MR1()) {
+            // L_MR1 above may support sending sms via wifi
+            return true;
+        }
+        final PhoneUtils phoneUtils = PhoneUtils.get(subId);
+        return !phoneUtils.isAirplaneModeOn();
+    }
+
+    public static StatusPlusUri sendMmsMessage(final Context context, final int subId,
+            final Uri messageUri, final Bundle extras) {
+        int status = MMS_REQUEST_MANUAL_RETRY;
+        int rawStatus = MessageData.RAW_TELEPHONY_STATUS_UNDEFINED;
+        if (!isMmsDataAvailable(subId)) {
+            LogUtil.w(TAG, "MmsUtils: failed to send message, no data available");
+            return new StatusPlusUri(MMS_REQUEST_MANUAL_RETRY,
+                    MessageData.RAW_TELEPHONY_STATUS_UNDEFINED,
+                    messageUri,
+                    SmsManager.MMS_ERROR_NO_DATA_NETWORK);
+        }
+        final PduPersister persister = PduPersister.getPduPersister(context);
+        try {
+            final SendReq sendReq = (SendReq) persister.load(messageUri);
+            if (sendReq == null) {
+                LogUtil.w(TAG, "MmsUtils: Sending MMS was deleted; uri = " + messageUri);
+                return new StatusPlusUri(MMS_REQUEST_NO_RETRY,
+                        MessageData.RAW_TELEPHONY_STATUS_UNDEFINED, messageUri);
+            }
+            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                LogUtil.d(TAG, String.format("MmsUtils: Sending MMS, message uri: %s", messageUri));
+            }
+            extras.putInt(SendMessageAction.KEY_SUB_ID, subId);
+            MmsSender.sendMms(context, subId, messageUri, sendReq, extras);
+            return STATUS_PENDING;
+        } catch (final MmsFailureException e) {
+            status = e.retryHint;
+            rawStatus = e.rawStatus;
+            LogUtil.e(TAG, "MmsUtils: failed to send message " + e, e);
+        } catch (final InvalidHeaderValueException e) {
+            LogUtil.e(TAG, "MmsUtils: failed to send message " + e, e);
+        } catch (final IllegalArgumentException e) {
+            LogUtil.e(TAG, "MmsUtils: invalid message to send " + e, e);
+        } catch (final MmsException e) {
+            LogUtil.e(TAG, "MmsUtils: failed to send message " + e, e);
+        }
+        // If we get here, some exception occurred
+        return new StatusPlusUri(status, rawStatus, messageUri);
+    }
+
+    public static StatusPlusUri updateSentMmsMessageStatus(final Context context,
+            final Uri messageUri, final SendConf sendConf) {
+        final int status;
+        final int respStatus = sendConf.getResponseStatus();
+
+        final ContentValues values = new ContentValues(2);
+        values.put(Mms.RESPONSE_STATUS, respStatus);
+        final byte[] messageId = sendConf.getMessageId();
+        if (messageId != null && messageId.length > 0) {
+            values.put(Mms.MESSAGE_ID, PduPersister.toIsoString(messageId));
+        }
+        SqliteWrapper.update(context, context.getContentResolver(),
+                messageUri, values, null, null);
+        if (respStatus == PduHeaders.RESPONSE_STATUS_OK) {
+            status = MMS_REQUEST_SUCCEEDED;
+        } else if (respStatus >= PduHeaders.RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE
+                && respStatus < PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_FAILURE) {
+            // Only RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE and RESPONSE_STATUS_ERROR_TRANSIENT
+            // _NETWORK_PROBLEM are used in the M-Send.conf. But for others transient failures
+            // including reserved values for future purposes, it should work same as transient
+            // failure always. (OMA-MMS-ENC-V1_2, 7.2.37. X-Mms-Response-Status field)
+            status = MMS_REQUEST_AUTO_RETRY;
+        } else {
+            // else permanent failure
+            status = MMS_REQUEST_MANUAL_RETRY;
+            LogUtil.e(TAG, "MmsUtils: failed to send message; respStatus = "
+                    + String.format("0x%X", respStatus));
+        }
+        return new StatusPlusUri(status, respStatus, messageUri);
+    }
+
+    public static void clearMmsStatus(final Context context, final Uri uri) {
+        // Messaging application can leave invalid values in STATUS field of M-Notification.ind
+        // messages.  Take this opportunity to clear it.
+        // Downloading status just kept in local db and not reflected into telephony.
+        final ContentValues values = new ContentValues(1);
+        values.putNull(Mms.STATUS);
+        SqliteWrapper.update(context, context.getContentResolver(),
+                    uri, values, null, null);
+    }
+
+    // Selection for dedup algorithm:
+    // ((m_type=NOTIFICATION_IND) OR (m_type=RETRIEVE_CONF)) AND (exp>NOW)) AND (t_id=xxxxxx)
+    // i.e. If it is NotificationInd or RetrieveConf and not expired
+    //      AND transaction id is the input id
+    private static final String DUP_NOTIFICATION_QUERY_SELECTION =
+            "((" + Mms.MESSAGE_TYPE + "=?) OR (" + Mms.MESSAGE_TYPE + "=?)) AND ("
+                    + Mms.EXPIRY + ">?) AND (" + Mms.TRANSACTION_ID + "=?)";
+
+    private static final int MAX_RETURN = 32;
+    private static String[] getDupNotifications(final Context context, final NotificationInd nInd) {
+        final byte[] rawTransactionId = nInd.getTransactionId();
+        if (rawTransactionId != null) {
+            // dedup algorithm
+            String selection = DUP_NOTIFICATION_QUERY_SELECTION;
+            final long nowSecs = System.currentTimeMillis() / 1000;
+            String[] selectionArgs = new String[] {
+                    Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
+                    Integer.toString(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF),
+                    Long.toString(nowSecs),
+                    new String(rawTransactionId)
+            };
+
+            Cursor cursor = null;
+            try {
+                cursor = SqliteWrapper.query(
+                        context, context.getContentResolver(),
+                        Mms.CONTENT_URI, new String[] { Mms._ID },
+                        selection, selectionArgs, null);
+                final int dupCount = cursor.getCount();
+                if (dupCount > 0) {
+                    // We already received the same notification before.
+                    // Don't want to return too many dups. It is only for debugging.
+                    final int returnCount = dupCount < MAX_RETURN ? dupCount : MAX_RETURN;
+                    final String[] dups = new String[returnCount];
+                    for (int i = 0; cursor.moveToNext() && i < returnCount; i++) {
+                        dups[i] = cursor.getString(0);
+                    }
+                    return dups;
+                }
+            } catch (final SQLiteException e) {
+                LogUtil.e(TAG, "query failure: " + e, e);
+            } finally {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Try parse the address using RFC822 format. If it fails to parse, then return the
+     * original address
+     *
+     * @param address The MMS ind sender address to parse
+     * @return The real address. If in RFC822 format, returns the correct email.
+     */
+    private static String parsePotentialRfc822EmailAddress(final String address) {
+        if (address == null || !address.contains("@") || !address.contains("<")) {
+            return address;
+        }
+        final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address);
+        if (tokens != null && tokens.length > 0) {
+            for (final Rfc822Token token : tokens) {
+                if (token != null && !TextUtils.isEmpty(token.getAddress())) {
+                    return token.getAddress();
+                }
+            }
+        }
+        return address;
+    }
+
+    public static DatabaseMessages.MmsMessage processReceivedPdu(final Context context,
+            final byte[] pushData, final int subId, final String subPhoneNumber) {
+        // Parse data
+
+        // Insert placeholder row to telephony and local db
+        // Get raw PDU push-data from the message and parse it
+        final PduParser parser = new PduParser(pushData,
+                MmsConfig.get(subId).getSupportMmsContentDisposition());
+        final GenericPdu pdu = parser.parse();
+
+        if (null == pdu) {
+            LogUtil.e(TAG, "Invalid PUSH data");
+            return null;
+        }
+
+        final PduPersister p = PduPersister.getPduPersister(context);
+        final int type = pdu.getMessageType();
+
+        Uri messageUri = null;
+        switch (type) {
+            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
+            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND: {
+                // TODO: Should this be commented out?
+//                threadId = findThreadId(context, pdu, type);
+//                if (threadId == -1) {
+//                    // The associated SendReq isn't found, therefore skip
+//                    // processing this PDU.
+//                    break;
+//                }
+
+//                Uri uri = p.persist(pdu, Inbox.CONTENT_URI, true,
+//                        MessagingPreferenceActivity.getIsGroupMmsEnabled(mContext), null);
+//                // Update thread ID for ReadOrigInd & DeliveryInd.
+//                ContentValues values = new ContentValues(1);
+//                values.put(Mms.THREAD_ID, threadId);
+//                SqliteWrapper.update(mContext, cr, uri, values, null, null);
+                LogUtil.w(TAG, "Received unsupported WAP Push, type=" + type);
+                break;
+            }
+            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: {
+                final NotificationInd nInd = (NotificationInd) pdu;
+
+                if (MmsConfig.get(subId).getTransIdEnabled()) {
+                    final byte [] contentLocationTemp = nInd.getContentLocation();
+                    if ('=' == contentLocationTemp[contentLocationTemp.length - 1]) {
+                        final byte [] transactionIdTemp = nInd.getTransactionId();
+                        final byte [] contentLocationWithId =
+                                new byte [contentLocationTemp.length
+                                                                  + transactionIdTemp.length];
+                        System.arraycopy(contentLocationTemp, 0, contentLocationWithId,
+                                0, contentLocationTemp.length);
+                        System.arraycopy(transactionIdTemp, 0, contentLocationWithId,
+                                contentLocationTemp.length, transactionIdTemp.length);
+                        nInd.setContentLocation(contentLocationWithId);
+                    }
+                }
+                final String[] dups = getDupNotifications(context, nInd);
+                if (dups == null) {
+                    // TODO: Do we handle Rfc822 Email Addresses?
+                    //final String contentLocation =
+                    //        MmsUtils.bytesToString(nInd.getContentLocation(), "UTF-8");
+                    //final byte[] transactionId = nInd.getTransactionId();
+                    //final long messageSize = nInd.getMessageSize();
+                    //final long expiry = nInd.getExpiry();
+                    //final String transactionIdString =
+                    //        MmsUtils.bytesToString(transactionId, "UTF-8");
+
+                    //final EncodedStringValue fromEncoded = nInd.getFrom();
+                    // An mms ind received from email address will have from address shown as
+                    // "John Doe <johndoe@foobar.com>" but the actual received message will only
+                    // have the email address. So let's try to parse the RFC822 format to get the
+                    // real email. Otherwise we will create two conversations for the MMS
+                    // notification and the actual MMS message if auto retrieve is disabled.
+                    //final String from = parsePotentialRfc822EmailAddress(
+                    //        fromEncoded != null ? fromEncoded.getString() : null);
+
+                    Uri inboxUri = null;
+                    try {
+                        inboxUri = p.persist(pdu, Mms.Inbox.CONTENT_URI, subId, subPhoneNumber,
+                                null);
+                        messageUri = ContentUris.withAppendedId(Mms.CONTENT_URI,
+                                ContentUris.parseId(inboxUri));
+                    } catch (final MmsException e) {
+                        LogUtil.e(TAG, "Failed to save the data from PUSH: type=" + type, e);
+                    }
+                } else {
+                    LogUtil.w(TAG, "Received WAP Push is a dup: " + Joiner.on(',').join(dups));
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.w(TAG, "Dup Transaction Id=" + new String(nInd.getTransactionId()));
+                    }
+                }
+                break;
+            }
+            default:
+                LogUtil.e(TAG, "Received unrecognized WAP Push, type=" + type);
+        }
+
+        DatabaseMessages.MmsMessage mms = null;
+        if (messageUri != null) {
+            mms = MmsUtils.loadMms(messageUri);
+        }
+        return mms;
+    }
+
+    public static Uri insertSendingMmsMessage(final Context context, final List<String> recipients,
+            final MessageData content, final int subId, final String subPhoneNumber,
+            final long timestamp) {
+        final SendReq sendReq = createMmsSendReq(
+                context, subId, recipients.toArray(new String[recipients.size()]), content,
+                DEFAULT_DELIVERY_REPORT_MODE,
+                DEFAULT_READ_REPORT_MODE,
+                DEFAULT_EXPIRY_TIME_IN_SECONDS,
+                DEFAULT_PRIORITY,
+                timestamp);
+        Uri messageUri = null;
+        if (sendReq != null) {
+            final Uri outboxUri = MmsUtils.insertSendReq(context, sendReq, subId, subPhoneNumber);
+            if (outboxUri != null) {
+                messageUri = ContentUris.withAppendedId(Telephony.Mms.CONTENT_URI,
+                        ContentUris.parseId(outboxUri));
+                if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "Mmsutils: Inserted sending MMS message into telephony, uri: "
+                            + outboxUri);
+                }
+            } else {
+                LogUtil.e(TAG, "insertSendingMmsMessage: failed to persist message into telephony");
+            }
+        }
+        return messageUri;
+    }
+
+    public static MessageData readSendingMmsMessage(final Uri messageUri,
+            final String conversationId, final String participantId, final String selfId) {
+        MessageData message = null;
+        if (messageUri != null) {
+            final DatabaseMessages.MmsMessage mms = MmsUtils.loadMms(messageUri);
+
+            // Make sure that the message has not been deleted from the Telephony DB
+            if (mms != null) {
+                // Transform the message
+                message = MmsUtils.createMmsMessage(mms, conversationId, participantId, selfId,
+                        MessageData.BUGLE_STATUS_OUTGOING_RESENDING);
+            }
+        }
+        return message;
+    }
+
+    /**
+     * Create an MMS message with subject, text and image
+     *
+     * @return Both the M-Send.req and the M-Send.conf for processing in the caller
+     * @throws MmsException
+     */
+    private static SendReq createMmsSendReq(final Context context, final int subId,
+            final String[] recipients, final MessageData message,
+            final boolean requireDeliveryReport, final boolean requireReadReport,
+            final long expiryTime, final int priority, final long timestampMillis) {
+        Assert.notNull(context);
+        if (recipients == null || recipients.length < 1) {
+            throw new IllegalArgumentException("MMS sendReq no recipient");
+        }
+
+        // Make a copy so we don't propagate changes to recipients to outside of this method
+        final String[] recipientsCopy = new String[recipients.length];
+        // Don't send phone number as is since some received phone number is malformed
+        // for sending. We need to strip the separators.
+        for (int i = 0; i < recipients.length; i++) {
+            final String recipient = recipients[i];
+            if (EmailAddress.isValidEmail(recipients[i])) {
+                // Don't do stripping for emails
+                recipientsCopy[i] = recipient;
+            } else {
+                recipientsCopy[i] = stripPhoneNumberSeparators(recipient);
+            }
+        }
+
+        SendReq sendReq = null;
+        try {
+            sendReq = createSendReq(context, subId, recipientsCopy,
+                    message, requireDeliveryReport,
+                    requireReadReport, expiryTime, priority, timestampMillis);
+        } catch (final InvalidHeaderValueException e) {
+            LogUtil.e(TAG, "InvalidHeaderValue creating sendReq PDU");
+        } catch (final OutOfMemoryError e) {
+            LogUtil.e(TAG, "Out of memory error creating sendReq PDU");
+        }
+        return sendReq;
+    }
+
+    /**
+     * Stripping out the invalid characters in a phone number before sending
+     * MMS. We only keep alphanumeric and '*', '#', '+'.
+     */
+    private static String stripPhoneNumberSeparators(final String phoneNumber) {
+        if (phoneNumber == null) {
+            return null;
+        }
+        final int len = phoneNumber.length();
+        final StringBuilder ret = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            final char c = phoneNumber.charAt(i);
+            if (Character.isLetterOrDigit(c) || c == '+' || c == '*' || c == '#') {
+                ret.append(c);
+            }
+        }
+        return ret.toString();
+    }
+
+    /**
+     * Create M-Send.req for the MMS message to be sent.
+     *
+     * @return the M-Send.req
+     * @throws InvalidHeaderValueException if there is any error in parsing the input
+     */
+    static SendReq createSendReq(final Context context, final int subId,
+            final String[] recipients, final MessageData message,
+            final boolean requireDeliveryReport,
+            final boolean requireReadReport, final long expiryTime, final int priority,
+            final long timestampMillis)
+            throws InvalidHeaderValueException {
+        final SendReq req = new SendReq();
+        // From, per spec
+        final String lineNumber = PhoneUtils.get(subId).getCanonicalForSelf(true/*allowOverride*/);
+        if (!TextUtils.isEmpty(lineNumber)) {
+            req.setFrom(new EncodedStringValue(lineNumber));
+        }
+        // To
+        final EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(recipients);
+        if (encodedNumbers != null) {
+            req.setTo(encodedNumbers);
+        }
+        // Subject
+        if (!TextUtils.isEmpty(message.getMmsSubject())) {
+            req.setSubject(new EncodedStringValue(message.getMmsSubject()));
+        }
+        // Date
+        req.setDate(timestampMillis / 1000L);
+        // Body
+        final MmsInfo bodyInfo = MmsUtils.makePduBody(context, message, subId);
+        req.setBody(bodyInfo.mPduBody);
+        // Message size
+        req.setMessageSize(bodyInfo.mMessageSize);
+        // Message class
+        req.setMessageClass(PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes());
+        // Expiry
+        req.setExpiry(expiryTime);
+        // Priority
+        req.setPriority(priority);
+        // Delivery report
+        req.setDeliveryReport(requireDeliveryReport ? PduHeaders.VALUE_YES : PduHeaders.VALUE_NO);
+        // Read report
+        req.setReadReport(requireReadReport ? PduHeaders.VALUE_YES : PduHeaders.VALUE_NO);
+        return req;
+    }
+
+    public static boolean isDeliveryReportRequired(final int subId) {
+        if (!MmsConfig.get(subId).getSMSDeliveryReportsEnabled()) {
+            return false;
+        }
+        final Context context = Factory.get().getApplicationContext();
+        final Resources res = context.getResources();
+        final BuglePrefs prefs = BuglePrefs.getSubscriptionPrefs(subId);
+        final String deliveryReportKey = res.getString(R.string.delivery_reports_pref_key);
+        final boolean defaultValue = res.getBoolean(R.bool.delivery_reports_pref_default);
+        return prefs.getBoolean(deliveryReportKey, defaultValue);
+    }
+
+    public static int sendSmsMessage(final String recipient, final String messageText,
+            final Uri requestUri, final int subId,
+            final String smsServiceCenter, final boolean requireDeliveryReport) {
+        if (!isSmsDataAvailable(subId)) {
+            LogUtil.w(TAG, "MmsUtils: can't send SMS without radio");
+            return MMS_REQUEST_MANUAL_RETRY;
+        }
+        final Context context = Factory.get().getApplicationContext();
+        int status = MMS_REQUEST_MANUAL_RETRY;
+        try {
+            // Send a single message
+            final SendResult result = SmsSender.sendMessage(
+                    context,
+                    subId,
+                    recipient,
+                    messageText,
+                    smsServiceCenter,
+                    requireDeliveryReport,
+                    requestUri);
+            if (!result.hasPending()) {
+                // not timed out, check failures
+                final int failureLevel = result.getHighestFailureLevel();
+                switch (failureLevel) {
+                    case SendResult.FAILURE_LEVEL_NONE:
+                        status = MMS_REQUEST_SUCCEEDED;
+                        break;
+                    case SendResult.FAILURE_LEVEL_TEMPORARY:
+                        status = MMS_REQUEST_AUTO_RETRY;
+                        LogUtil.e(TAG, "MmsUtils: SMS temporary failure");
+                        break;
+                    case SendResult.FAILURE_LEVEL_PERMANENT:
+                        LogUtil.e(TAG, "MmsUtils: SMS permanent failure");
+                        break;
+                }
+            } else {
+                // Timed out
+                LogUtil.e(TAG, "MmsUtils: sending SMS timed out");
+            }
+        } catch (final Exception e) {
+            LogUtil.e(TAG, "MmsUtils: failed to send SMS " + e, e);
+        }
+        return status;
+    }
+
+    /**
+     * Delete SMS and MMS messages in a particular thread
+     *
+     * @return the number of messages deleted
+     */
+    public static int deleteThread(final long threadId, final long cutOffTimestampInMillis) {
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        final Uri threadUri = ContentUris.withAppendedId(Telephony.Threads.CONTENT_URI, threadId);
+        if (cutOffTimestampInMillis < Long.MAX_VALUE) {
+            return resolver.delete(threadUri, Sms.DATE + "<=?",
+                    new String[] { Long.toString(cutOffTimestampInMillis) });
+        } else {
+            return resolver.delete(threadUri, null /* smsSelection */, null /* selectionArgs */);
+        }
+    }
+
+    /**
+     * Delete single SMS and MMS message
+     *
+     * @return number of rows deleted (should be 1 or 0)
+     */
+    public static int deleteMessage(final Uri messageUri) {
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        return resolver.delete(messageUri, null /* selection */, null /* selectionArgs */);
+    }
+
+    public static byte[] createDebugNotificationInd(final String fileName) {
+        byte[] pduData = null;
+        try {
+            final Context context = Factory.get().getApplicationContext();
+            // Load the message file
+            final byte[] data = DebugUtils.receiveFromDumpFile(fileName);
+            final RetrieveConf retrieveConf = receiveFromDumpFile(data);
+            // Create the notification
+            final NotificationInd notification = new NotificationInd();
+            final long expiry = System.currentTimeMillis() / 1000 + 600;
+            notification.setTransactionId(fileName.getBytes());
+            notification.setMmsVersion(retrieveConf.getMmsVersion());
+            notification.setFrom(retrieveConf.getFrom());
+            notification.setSubject(retrieveConf.getSubject());
+            notification.setExpiry(expiry);
+            notification.setMessageSize(data.length);
+            notification.setMessageClass(retrieveConf.getMessageClass());
+
+            final Uri.Builder builder = MediaScratchFileProvider.getUriBuilder();
+            builder.appendPath(fileName);
+            final Uri contentLocation = builder.build();
+            notification.setContentLocation(contentLocation.toString().getBytes());
+
+            // Serialize
+            pduData = new PduComposer(context, notification).make();
+            if (pduData == null || pduData.length < 1) {
+                throw new IllegalArgumentException("Empty or zero length PDU data");
+            }
+        } catch (final MmsFailureException e) {
+            // Nothing to do
+        } catch (final InvalidHeaderValueException e) {
+            // Nothing to do
+        }
+        return pduData;
+    }
+
+    public static int mapRawStatusToErrorResourceId(final int bugleStatus, final int rawStatus) {
+        int stringResId = R.string.message_status_send_failed;
+        switch (rawStatus) {
+            case PduHeaders.RESPONSE_STATUS_ERROR_SERVICE_DENIED:
+            case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID:
+                stringResId = R.string.mms_failure_outgoing_service;
+                break;
+            case PduHeaders.RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED:
+            case PduHeaders.RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED:
+            case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED:
+                stringResId = R.string.mms_failure_outgoing_address;
+                break;
+            case PduHeaders.RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT:
+            case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT:
+                stringResId = R.string.mms_failure_outgoing_corrupt;
+                break;
+            case PduHeaders.RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED:
+            case PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED:
+                stringResId = R.string.mms_failure_outgoing_content;
+                break;
+            case PduHeaders.RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND:
+            //case PduHeaders.RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND:
+                stringResId = R.string.mms_failure_outgoing_unsupported;
+                break;
+            case MessageData.RAW_TELEPHONY_STATUS_MESSAGE_TOO_BIG:
+                stringResId = R.string.mms_failure_outgoing_too_large;
+                break;
+        }
+        return stringResId;
+    }
+
+    /**
+     * Dump the raw MMS data into a file
+     *
+     * @param rawPdu The raw pdu data
+     * @param pdu The parsed pdu, used to construct a dump file name
+     */
+    public static void dumpPdu(final byte[] rawPdu, final GenericPdu pdu) {
+        if (rawPdu == null || rawPdu.length < 1) {
+            return;
+        }
+        final String dumpFileName = MmsUtils.MMS_DUMP_PREFIX + getDumpFileId(pdu);
+        final File dumpFile = DebugUtils.getDebugFile(dumpFileName, true);
+        if (dumpFile != null) {
+            try {
+                final FileOutputStream fos = new FileOutputStream(dumpFile);
+                final BufferedOutputStream bos = new BufferedOutputStream(fos);
+                try {
+                    bos.write(rawPdu);
+                    bos.flush();
+                } finally {
+                    bos.close();
+                }
+                DebugUtils.ensureReadable(dumpFile);
+            } catch (final IOException e) {
+                LogUtil.e(TAG, "dumpPdu: " + e, e);
+            }
+        }
+    }
+
+    /**
+     * Get the dump file id based on the parsed PDU
+     * 1. Use message id if not empty
+     * 2. Use transaction id if message id is empty
+     * 3. If all above is empty, use random UUID
+     *
+     * @param pdu the parsed PDU
+     * @return the id of the dump file
+     */
+    private static String getDumpFileId(final GenericPdu pdu) {
+        String fileId = null;
+        if (pdu != null && pdu instanceof RetrieveConf) {
+            final RetrieveConf retrieveConf = (RetrieveConf) pdu;
+            if (retrieveConf.getMessageId() != null) {
+                fileId = new String(retrieveConf.getMessageId());
+            } else if (retrieveConf.getTransactionId() != null) {
+                fileId = new String(retrieveConf.getTransactionId());
+            }
+        }
+        if (TextUtils.isEmpty(fileId)) {
+            fileId = UUID.randomUUID().toString();
+        }
+        return fileId;
+    }
+}
diff --git a/src/com/android/messaging/sms/SmsException.java b/src/com/android/messaging/sms/SmsException.java
new file mode 100644
index 0000000..728db8c
--- /dev/null
+++ b/src/com/android/messaging/sms/SmsException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+/**
+ * A generic Exception for errors in sending SMS
+ */
+class SmsException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Creates a new SmsException.
+     */
+    public SmsException() {
+        super();
+    }
+
+    /**
+     * Creates a new SmsException with the specified detail message.
+     *
+     * @param message the detail message.
+     */
+    public SmsException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new SmsException with the specified cause.
+     *
+     * @param cause the cause.
+     */
+    public SmsException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Creates a new SmsException with the specified detail message and cause.
+     *
+     * @param message the detail message.
+     * @param cause the cause.
+     */
+    public SmsException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/com/android/messaging/sms/SmsReleaseStorage.java b/src/com/android/messaging/sms/SmsReleaseStorage.java
new file mode 100644
index 0000000..13a6284
--- /dev/null
+++ b/src/com/android/messaging/sms/SmsReleaseStorage.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.content.res.Resources;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Class handling message cleanup when storage is low
+ */
+public class SmsReleaseStorage {
+    /**
+     * Class representing a time duration specified by Gservices
+     */
+    public static class Duration {
+        // Time duration unit types
+        public static final int UNIT_WEEK = 'w';
+        public static final int UNIT_MONTH = 'm';
+        public static final int UNIT_YEAR = 'y';
+
+        // Number of units
+        public final int mCount;
+        // Unit type: week, month or year
+        public final int mUnit;
+
+        public Duration(final int count, final int unit) {
+            mCount = count;
+            mUnit = unit;
+        }
+    }
+
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final Duration DEFAULT_DURATION = new Duration(1, Duration.UNIT_MONTH);
+
+    private static final Pattern DURATION_PATTERN = Pattern.compile("([1-9]+\\d*)(w|m|y)");
+    /**
+     * Parse message retaining time duration specified by Gservices
+     *
+     * @return The parsed time duration from Gservices
+     */
+    public static Duration parseMessageRetainingDuration() {
+        final String smsAutoDeleteMessageRetainingDuration =
+                BugleGservices.get().getString(
+                        BugleGservicesKeys.SMS_STORAGE_PURGING_MESSAGE_RETAINING_DURATION,
+                        BugleGservicesKeys.SMS_STORAGE_PURGING_MESSAGE_RETAINING_DURATION_DEFAULT);
+        final Matcher matcher = DURATION_PATTERN.matcher(smsAutoDeleteMessageRetainingDuration);
+        try {
+            if (matcher.matches()) {
+                return new Duration(
+                        Integer.parseInt(matcher.group(1)),
+                        matcher.group(2).charAt(0));
+            }
+        } catch (final NumberFormatException e) {
+            // Nothing to do
+        }
+        LogUtil.e(TAG, "SmsAutoDelete: invalid duration " +
+                smsAutoDeleteMessageRetainingDuration);
+        return DEFAULT_DURATION;
+    }
+
+    /**
+     * Get string representation of the time duration
+     *
+     * @param duration
+     * @return
+     */
+    public static String getMessageRetainingDurationString(final Duration duration) {
+        final Resources resources = Factory.get().getApplicationContext().getResources();
+        switch (duration.mUnit) {
+            case Duration.UNIT_WEEK:
+                return resources.getQuantityString(
+                        R.plurals.week_count, duration.mCount, duration.mCount);
+            case Duration.UNIT_MONTH:
+                return resources.getQuantityString(
+                        R.plurals.month_count, duration.mCount, duration.mCount);
+            case Duration.UNIT_YEAR:
+                return resources.getQuantityString(
+                        R.plurals.year_count, duration.mCount, duration.mCount);
+        }
+        throw new IllegalArgumentException(
+                "SmsAutoDelete: invalid duration unit " + duration.mUnit);
+    }
+
+    // Time conversations
+    private static final long WEEK_IN_MILLIS = 7 * 24 * 3600 * 1000L;
+    private static final long MONTH_IN_MILLIS = 30 * 24 * 3600 * 1000L;
+    private static final long YEAR_IN_MILLIS = 365 * 24 * 3600 * 1000L;
+
+    /**
+     * Convert time duration to time in milliseconds
+     *
+     * @param duration
+     * @return
+     */
+    public static long durationToTimeInMillis(final Duration duration) {
+        switch (duration.mUnit) {
+            case Duration.UNIT_WEEK:
+                return duration.mCount * WEEK_IN_MILLIS;
+            case Duration.UNIT_MONTH:
+                return duration.mCount * MONTH_IN_MILLIS;
+            case Duration.UNIT_YEAR:
+                return duration.mCount * YEAR_IN_MILLIS;
+        }
+        return -1L;
+    }
+
+    /**
+     * Delete message actions:
+     * 0: delete media messages
+     * 1: delete old messages
+     *
+     * @param actionIndex The index of the delete action to perform
+     * @param durationInMillis The time duration for retaining messages
+     */
+    public static void deleteMessages(final int actionIndex, final long durationInMillis) {
+        int deleted = 0;
+        switch (actionIndex) {
+            case 0: {
+                // Delete media
+                deleted = MmsUtils.deleteMediaMessages();
+                break;
+            }
+            case 1: {
+                // Delete old messages
+                final long now = System.currentTimeMillis();
+                final long cutOffTimestampInMillis = now - durationInMillis;
+                // Delete messages from telephony provider
+                deleted = MmsUtils.deleteMessagesOlderThan(cutOffTimestampInMillis);
+                break;
+            }
+            default: {
+                LogUtil.e(TAG, "SmsStorageStatusManager: invalid action " + actionIndex);
+                break;
+            }
+        }
+
+        if (deleted > 0) {
+            // Kick off a sync to update local db.
+            SyncManager.sync();
+        }
+    }
+}
diff --git a/src/com/android/messaging/sms/SmsSender.java b/src/com/android/messaging/sms/SmsSender.java
new file mode 100644
index 0000000..e429995
--- /dev/null
+++ b/src/com/android/messaging/sms/SmsSender.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.sms;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.receiver.SendStatusReceiver;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Class that sends chat message via SMS.
+ *
+ * The interface emulates a blocking sending similar to making an HTTP request.
+ * It calls the SmsManager to send a (potentially multipart) message and waits
+ * on the sent status on each part. The waiting has a timeout so it won't wait
+ * forever. Once the sent status of all parts received, the call returns.
+ * A successful sending requires success status for all parts. Otherwise, we
+ * pick the highest level of failure as the error for the whole message, which
+ * is used to determine if we need to retry the sending.
+ */
+public class SmsSender {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    public static final String EXTRA_PART_ID = "part_id";
+
+    /*
+     * A map for pending sms messages. The key is the random request UUID.
+     */
+    private static ConcurrentHashMap<Uri, SendResult> sPendingMessageMap =
+            new ConcurrentHashMap<Uri, SendResult>();
+
+    private static final Random RANDOM = new Random();
+
+    /**
+     * Class that holds the sent status for all parts of a multipart message sending
+     */
+    public static class SendResult {
+        // Failure levels, used by the caller of the sender.
+        // For temporary failures, possibly we could retry the sending
+        // For permanent failures, we probably won't retry
+        public static final int FAILURE_LEVEL_NONE = 0;
+        public static final int FAILURE_LEVEL_TEMPORARY = 1;
+        public static final int FAILURE_LEVEL_PERMANENT = 2;
+
+        // Tracking the remaining pending parts in sending
+        private int mPendingParts;
+        // Tracking the highest level of failure among all parts
+        private int mHighestFailureLevel;
+
+        public SendResult(final int numOfParts) {
+            Assert.isTrue(numOfParts > 0);
+            mPendingParts = numOfParts;
+            mHighestFailureLevel = FAILURE_LEVEL_NONE;
+        }
+
+        // Update the sent status of one part
+        public void setPartResult(final int resultCode) {
+            mPendingParts--;
+            setHighestFailureLevel(resultCode);
+        }
+
+        public boolean hasPending() {
+            return mPendingParts > 0;
+        }
+
+        public int getHighestFailureLevel() {
+            return mHighestFailureLevel;
+        }
+
+        private int getFailureLevel(final int resultCode) {
+            switch (resultCode) {
+                case Activity.RESULT_OK:
+                    return FAILURE_LEVEL_NONE;
+                case SmsManager.RESULT_ERROR_NO_SERVICE:
+                    return FAILURE_LEVEL_TEMPORARY;
+                case SmsManager.RESULT_ERROR_RADIO_OFF:
+                    return FAILURE_LEVEL_PERMANENT;
+                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
+                    return FAILURE_LEVEL_PERMANENT;
+                default: {
+                    LogUtil.e(TAG, "SmsSender: Unexpected sent intent resultCode = " + resultCode);
+                    return FAILURE_LEVEL_PERMANENT;
+                }
+            }
+        }
+
+        private void setHighestFailureLevel(final int resultCode) {
+            final int level = getFailureLevel(resultCode);
+            if (level > mHighestFailureLevel) {
+                mHighestFailureLevel = level;
+            }
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("SendResult:");
+            sb.append("Pending=").append(mPendingParts).append(",");
+            sb.append("HighestFailureLevel=").append(mHighestFailureLevel);
+            return sb.toString();
+        }
+    }
+
+    public static void setResult(final Uri requestId, final int resultCode,
+            final int errorCode, final int partId, int subId) {
+        if (resultCode != Activity.RESULT_OK) {
+            LogUtil.e(TAG, "SmsSender: failure in sending message part. "
+                    + " requestId=" + requestId + " partId=" + partId
+                    + " resultCode=" + resultCode + " errorCode=" + errorCode);
+            if (errorCode != SendStatusReceiver.NO_ERROR_CODE) {
+                final Context context = Factory.get().getApplicationContext();
+                UiUtils.showToastAtBottom(getSendErrorToastMessage(context, subId, errorCode));
+            }
+        } else {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "SmsSender: received sent result. " + " requestId=" + requestId
+                        + " partId=" + partId + " resultCode=" + resultCode);
+            }
+        }
+        if (requestId != null) {
+            final SendResult result = sPendingMessageMap.get(requestId);
+            if (result != null) {
+                synchronized (result) {
+                    result.setPartResult(resultCode);
+                    if (!result.hasPending()) {
+                        result.notifyAll();
+                    }
+                }
+            } else {
+                LogUtil.e(TAG, "SmsSender: ignoring sent result. " + " requestId=" + requestId
+                        + " partId=" + partId + " resultCode=" + resultCode);
+            }
+        }
+    }
+
+    private static String getSendErrorToastMessage(final Context context, final int subId,
+            final int errorCode) {
+        final String carrierName = PhoneUtils.get(subId).getCarrierName();
+        if (TextUtils.isEmpty(carrierName)) {
+            return context.getString(R.string.carrier_send_error_unknown_carrier, errorCode);
+        } else {
+            return context.getString(R.string.carrier_send_error, carrierName, errorCode);
+        }
+    }
+
+    // This should be called from a RequestWriter queue thread
+    public static SendResult sendMessage(final Context context, final int subId, String dest,
+            String message, final String serviceCenter, final boolean requireDeliveryReport,
+            final Uri messageUri) throws SmsException {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "SmsSender: sending message. " +
+                    "dest=" + dest + " message=" + message +
+                    " serviceCenter=" + serviceCenter +
+                    " requireDeliveryReport=" + requireDeliveryReport +
+                    " requestId=" + messageUri);
+        }
+        if (TextUtils.isEmpty(message)) {
+            throw new SmsException("SmsSender: empty text message");
+        }
+        // Get the real dest and message for email or alias if dest is email or alias
+        // Or sanitize the dest if dest is a number
+        if (!TextUtils.isEmpty(MmsConfig.get(subId).getEmailGateway()) &&
+                (MmsSmsUtils.isEmailAddress(dest) || MmsSmsUtils.isAlias(dest, subId))) {
+            // The original destination (email address) goes with the message
+            message = dest + " " + message;
+            // the new address is the email gateway #
+            dest = MmsConfig.get(subId).getEmailGateway();
+        } else {
+            // remove spaces and dashes from destination number
+            // (e.g. "801 555 1212" -> "8015551212")
+            // (e.g. "+8211-123-4567" -> "+82111234567")
+            dest = PhoneNumberUtils.stripSeparators(dest);
+        }
+        if (TextUtils.isEmpty(dest)) {
+            throw new SmsException("SmsSender: empty destination address");
+        }
+        // Divide the input message by SMS length limit
+        final SmsManager smsManager = PhoneUtils.get(subId).getSmsManager();
+        final ArrayList<String> messages = smsManager.divideMessage(message);
+        if (messages == null || messages.size() < 1) {
+            throw new SmsException("SmsSender: fails to divide message");
+        }
+        // Prepare the send result, which collects the send status for each part
+        final SendResult pendingResult = new SendResult(messages.size());
+        sPendingMessageMap.put(messageUri, pendingResult);
+        // Actually send the sms
+        sendInternal(
+                context, subId, dest, messages, serviceCenter, requireDeliveryReport, messageUri);
+        // Wait for pending intent to come back
+        synchronized (pendingResult) {
+            final long smsSendTimeoutInMillis = BugleGservices.get().getLong(
+                    BugleGservicesKeys.SMS_SEND_TIMEOUT_IN_MILLIS,
+                    BugleGservicesKeys.SMS_SEND_TIMEOUT_IN_MILLIS_DEFAULT);
+            final long beginTime = SystemClock.elapsedRealtime();
+            long waitTime = smsSendTimeoutInMillis;
+            // We could possibly be woken up while still pending
+            // so make sure we wait the full timeout period unless
+            // we have the send results of all parts.
+            while (pendingResult.hasPending() && waitTime > 0) {
+                try {
+                    pendingResult.wait(waitTime);
+                } catch (final InterruptedException e) {
+                    LogUtil.e(TAG, "SmsSender: sending wait interrupted");
+                }
+                waitTime = smsSendTimeoutInMillis - (SystemClock.elapsedRealtime() - beginTime);
+            }
+        }
+        // Either we timed out or have all the results (success or failure)
+        sPendingMessageMap.remove(messageUri);
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "SmsSender: sending completed. " +
+                    "dest=" + dest + " message=" + message + " result=" + pendingResult);
+        }
+        return pendingResult;
+    }
+
+    // Actually sending the message using SmsManager
+    private static void sendInternal(final Context context, final int subId, String dest,
+            final ArrayList<String> messages, final String serviceCenter,
+            final boolean requireDeliveryReport, final Uri messageUri) throws SmsException {
+        Assert.notNull(context);
+        final SmsManager smsManager = PhoneUtils.get(subId).getSmsManager();
+        final int messageCount = messages.size();
+        final ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(messageCount);
+        final ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);
+        for (int i = 0; i < messageCount; i++) {
+            // Make pending intents different for each message part
+            final int partId = (messageCount <= 1 ? 0 : i + 1);
+            if (requireDeliveryReport && (i == (messageCount - 1))) {
+                // TODO we only care about the delivery status of the last part
+                // Shall we have better tracking of delivery status of all parts?
+                deliveryIntents.add(PendingIntent.getBroadcast(
+                        context,
+                        partId,
+                        getSendStatusIntent(context, SendStatusReceiver.MESSAGE_DELIVERED_ACTION,
+                                messageUri, partId, subId),
+                        0/*flag*/));
+            } else {
+                deliveryIntents.add(null);
+            }
+            sentIntents.add(PendingIntent.getBroadcast(
+                    context,
+                    partId,
+                    getSendStatusIntent(context, SendStatusReceiver.MESSAGE_SENT_ACTION,
+                            messageUri, partId, subId),
+                    0/*flag*/));
+        }
+        try {
+            if (MmsConfig.get(subId).getSendMultipartSmsAsSeparateMessages()) {
+                // If multipart sms is not supported, send them as separate messages
+                for (int i = 0; i < messageCount; i++) {
+                    smsManager.sendTextMessage(dest,
+                            serviceCenter,
+                            messages.get(i),
+                            sentIntents.get(i),
+                            deliveryIntents.get(i));
+                }
+            } else {
+                smsManager.sendMultipartTextMessage(
+                        dest, serviceCenter, messages, sentIntents, deliveryIntents);
+            }
+        } catch (final Exception e) {
+            throw new SmsException("SmsSender: caught exception in sending " + e);
+        }
+    }
+
+    private static Intent getSendStatusIntent(final Context context, final String action,
+            final Uri requestUri, final int partId, final int subId) {
+        // Encode requestId in intent data
+        final Intent intent = new Intent(action, requestUri, context, SendStatusReceiver.class);
+        intent.putExtra(SendStatusReceiver.EXTRA_PART_ID, partId);
+        intent.putExtra(SendStatusReceiver.EXTRA_SUB_ID, subId);
+        return intent;
+    }
+}
diff --git a/src/com/android/messaging/sms/SmsStorageStatusManager.java b/src/com/android/messaging/sms/SmsStorageStatusManager.java
new file mode 100644
index 0000000..4f03195
--- /dev/null
+++ b/src/com/android/messaging/sms/SmsStorageStatusManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.sms;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.PendingIntentConstants;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Class that handles SMS auto delete and notification when storage is low
+ */
+public class SmsStorageStatusManager {
+    /**
+     * Handles storage low signal for SMS
+     */
+    public static void handleStorageLow() {
+        if (!PhoneUtils.getDefault().isSmsEnabled()) {
+            return;
+        }
+
+        // TODO: Auto-delete messages, when that setting exists and is enabled
+
+        // Notify low storage for SMS
+        postStorageLowNotification();
+    }
+
+    /**
+     * Handles storage OK signal for SMS
+     */
+    public static void handleStorageOk() {
+        if (!PhoneUtils.getDefault().isSmsEnabled()) {
+            return;
+        }
+        cancelStorageLowNotification();
+    }
+
+    /**
+     * Post sms storage low notification
+     */
+    private static void postStorageLowNotification() {
+        final Context context = Factory.get().getApplicationContext();
+        final Resources resources = context.getResources();
+        final PendingIntent pendingIntent = UIIntents.get()
+                .getPendingIntentForLowStorageNotifications(context);
+
+        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+        builder.setContentTitle(resources.getString(R.string.sms_storage_low_title))
+                .setTicker(resources.getString(R.string.sms_storage_low_notification_ticker))
+                .setSmallIcon(R.drawable.ic_failed_light)
+                .setPriority(Notification.PRIORITY_DEFAULT)
+                .setOngoing(true)      // Can't be swiped off
+                .setAutoCancel(false)  // Don't auto cancel
+                .setContentIntent(pendingIntent);
+
+        final NotificationCompat.BigTextStyle bigTextStyle =
+                new NotificationCompat.BigTextStyle(builder);
+        bigTextStyle.bigText(resources.getString(R.string.sms_storage_low_text));
+        final Notification notification = bigTextStyle.build();
+
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+
+        notificationManager.notify(getNotificationTag(),
+                PendingIntentConstants.SMS_STORAGE_LOW_NOTIFICATION_ID, notification);
+    }
+
+    /**
+     * Cancel the notification
+     */
+    public static void cancelStorageLowNotification() {
+        final NotificationManagerCompat notificationManager =
+                NotificationManagerCompat.from(Factory.get().getApplicationContext());
+        notificationManager.cancel(getNotificationTag(),
+                PendingIntentConstants.SMS_STORAGE_LOW_NOTIFICATION_ID);
+    }
+
+    private static String getNotificationTag() {
+        return Factory.get().getApplicationContext().getPackageName() + ":smsstoragelow";
+    }
+}
diff --git a/src/com/android/messaging/sms/SystemProperties.java b/src/com/android/messaging/sms/SystemProperties.java
new file mode 100644
index 0000000..669e448
--- /dev/null
+++ b/src/com/android/messaging/sms/SystemProperties.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.sms;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Hacky way to call the hidden SystemProperties class API
+ */
+class SystemProperties {
+    private static Method sSystemPropertiesGetMethod = null;
+
+    public static String get(final String name) {
+        if (sSystemPropertiesGetMethod == null) {
+            try {
+                final Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
+                if (systemPropertiesClass != null) {
+                    sSystemPropertiesGetMethod =
+                            systemPropertiesClass.getMethod("get", String.class);
+                }
+            } catch (final ClassNotFoundException e) {
+                // Nothing to do
+            } catch (final NoSuchMethodException e) {
+                // Nothing to do
+            }
+        }
+        if (sSystemPropertiesGetMethod != null) {
+            try {
+                return (String) sSystemPropertiesGetMethod.invoke(null, name);
+            } catch (final IllegalArgumentException e) {
+                // Nothing to do
+            } catch (final IllegalAccessException e) {
+                // Nothing to do
+            } catch (final InvocationTargetException e) {
+                // Nothing to do
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/ui/AsyncImageView.java b/src/com/android/messaging/ui/AsyncImageView.java
new file mode 100644
index 0000000..7d057b3
--- /dev/null
+++ b/src/com/android/messaging/ui/AsyncImageView.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import androidx.annotation.Nullable;
+import android.support.rastermill.FrameSequenceDrawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.media.BindableMediaRequest;
+import com.android.messaging.datamodel.media.GifImageResource;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.ThreadUtil;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.HashSet;
+
+/**
+ * An ImageView used to asynchronously request an image from MediaResourceManager and render it.
+ */
+public class AsyncImageView extends ImageView implements MediaResourceLoadListener<ImageResource> {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    // 100ms delay before disposing the image in case the AsyncImageView is re-added to the UI
+    private static final int DISPOSE_IMAGE_DELAY = 100;
+
+    // AsyncImageView has a 1-1 binding relationship with an ImageRequest instance that requests
+    // the image from the MediaResourceManager. Since the request is done asynchronously, we
+    // want to make sure the image view is always bound to the latest image request that it
+    // issues, so that when the image is loaded, the ImageRequest (which extends BindableData)
+    // will be able to figure out whether the binding is still valid and whether the loaded image
+    // should be delivered to the AsyncImageView via onMediaResourceLoaded() callback.
+    @VisibleForTesting
+    public final Binding<BindableMediaRequest<ImageResource>> mImageRequestBinding;
+
+    /** True if we want the image to fade in when it loads */
+    private boolean mFadeIn;
+
+    /** True if we want the image to reveal (scale) when it loads. When set to true, this
+     * will take precedence over {@link #mFadeIn} */
+    private final boolean mReveal;
+
+    // The corner radius for drawing rounded corners around bitmap. The default value is zero
+    // (no rounded corners)
+    private final int mCornerRadius;
+    private final Path mRoundedCornerClipPath;
+    private int mClipPathWidth;
+    private int mClipPathHeight;
+
+    // A placeholder drawable that takes the spot of the image when it's loading. The default
+    // setting is null (no placeholder).
+    private final Drawable mPlaceholderDrawable;
+    protected ImageResource mImageResource;
+    private final Runnable mDisposeRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mImageRequestBinding.isBound()) {
+                mDetachedRequestDescriptor = (ImageRequestDescriptor)
+                        mImageRequestBinding.getData().getDescriptor();
+            }
+            unbindView();
+            releaseImageResource();
+        }
+    };
+
+    private AsyncImageViewDelayLoader mDelayLoader;
+    private ImageRequestDescriptor mDetachedRequestDescriptor;
+
+    public AsyncImageView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mImageRequestBinding = BindingBase.createBinding(this);
+        final TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.AsyncImageView,
+                0, 0);
+        mFadeIn = attr.getBoolean(R.styleable.AsyncImageView_fadeIn, true);
+        mReveal = attr.getBoolean(R.styleable.AsyncImageView_reveal, false);
+        mPlaceholderDrawable = attr.getDrawable(R.styleable.AsyncImageView_placeholderDrawable);
+        mCornerRadius = attr.getDimensionPixelSize(R.styleable.AsyncImageView_cornerRadius, 0);
+        mRoundedCornerClipPath = new Path();
+
+        attr.recycle();
+    }
+
+    /**
+     * The main entrypoint for AsyncImageView to load image resource given an ImageRequestDescriptor
+     * @param descriptor the request descriptor, or null if no image should be displayed
+     */
+    public void setImageResourceId(@Nullable final ImageRequestDescriptor descriptor) {
+        final String requestKey = (descriptor == null) ? null : descriptor.getKey();
+        if (mImageRequestBinding.isBound()) {
+            if (TextUtils.equals(mImageRequestBinding.getData().getKey(), requestKey)) {
+                // Don't re-request the bitmap if the new request is for the same resource.
+                return;
+            }
+            unbindView();
+        } else {
+            mDetachedRequestDescriptor = null;
+        }
+        setImage(null);
+        resetTransientViewStates();
+        if (!TextUtils.isEmpty(requestKey)) {
+            maybeSetupPlaceholderDrawable(descriptor);
+            final BindableMediaRequest<ImageResource> imageRequest =
+                    descriptor.buildAsyncMediaRequest(getContext(), this);
+            requestImage(imageRequest);
+        }
+    }
+
+    /**
+     * Sets a delay loader that centrally manages image request delay loading logic.
+     */
+    public void setDelayLoader(final AsyncImageViewDelayLoader delayLoader) {
+        Assert.isTrue(mDelayLoader == null);
+        mDelayLoader = delayLoader;
+    }
+
+    /**
+     * Called by the delay loader when we can resume image loading.
+     */
+    public void resumeLoading() {
+        Assert.notNull(mDelayLoader);
+        Assert.isTrue(mImageRequestBinding.isBound());
+        MediaResourceManager.get().requestMediaResourceAsync(mImageRequestBinding.getData());
+    }
+
+    /**
+     * Setup the placeholder drawable if:
+     * 1. There's an image to be loaded AND
+     * 2. We are given a placeholder drawable AND
+     * 3. The descriptor provided us with source width and height.
+     */
+    private void maybeSetupPlaceholderDrawable(final ImageRequestDescriptor descriptor) {
+        if (!TextUtils.isEmpty(descriptor.getKey()) && mPlaceholderDrawable != null) {
+            if (descriptor.sourceWidth != ImageRequest.UNSPECIFIED_SIZE &&
+                descriptor.sourceHeight != ImageRequest.UNSPECIFIED_SIZE) {
+                // Set a transparent inset drawable to the foreground so it will mimick the final
+                // size of the image, and use the background to show the actual placeholder
+                // drawable.
+                setImageDrawable(PlaceholderInsetDrawable.fromDrawable(
+                        new ColorDrawable(Color.TRANSPARENT),
+                        descriptor.sourceWidth, descriptor.sourceHeight));
+            }
+            setBackground(mPlaceholderDrawable);
+        }
+    }
+
+    protected void setImage(final ImageResource resource) {
+        setImage(resource, false /* isCached */);
+    }
+
+    protected void setImage(final ImageResource resource, final boolean isCached) {
+        // Switch reference to the new ImageResource. Make sure we release the current
+        // resource and addRef() on the new resource so that the underlying bitmaps don't
+        // get leaked or get recycled by the bitmap cache.
+        releaseImageResource();
+        // Ensure that any pending dispose runnables get removed.
+        ThreadUtil.getMainThreadHandler().removeCallbacks(mDisposeRunnable);
+        // The drawable may require work to get if its a static object so try to only make this call
+        // once.
+        final Drawable drawable = (resource != null) ? resource.getDrawable(getResources()) : null;
+        if (drawable != null) {
+            mImageResource = resource;
+            mImageResource.addRef();
+            setImageDrawable(drawable);
+            if (drawable instanceof FrameSequenceDrawable) {
+                ((FrameSequenceDrawable) drawable).start();
+            }
+
+            if (getVisibility() == VISIBLE) {
+                if (mReveal) {
+                    setVisibility(INVISIBLE);
+                    UiUtils.revealOrHideViewWithAnimation(this, VISIBLE, null);
+                } else if (mFadeIn && !isCached) {
+                    // Hide initially to avoid flash.
+                    setAlpha(0F);
+                    animate().alpha(1F).start();
+                }
+            }
+
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                if (mImageResource instanceof GifImageResource) {
+                    LogUtil.v(TAG, "setImage size unknown -- it's a GIF");
+                } else {
+                    LogUtil.v(TAG, "setImage size: " + mImageResource.getMediaSize() +
+                            " width: " + mImageResource.getBitmap().getWidth() +
+                            " heigh: " + mImageResource.getBitmap().getHeight());
+                }
+            }
+        }
+        invalidate();
+    }
+
+    private void requestImage(final BindableMediaRequest<ImageResource> request) {
+        mImageRequestBinding.bind(request);
+        if (mDelayLoader == null || !mDelayLoader.isDelayLoadingImage()) {
+            MediaResourceManager.get().requestMediaResourceAsync(request);
+        } else {
+            mDelayLoader.registerView(this);
+        }
+    }
+
+    @Override
+    public void onMediaResourceLoaded(final MediaRequest<ImageResource> request,
+            final ImageResource resource, final boolean isCached) {
+        if (mImageResource != resource) {
+            setImage(resource, isCached);
+        }
+    }
+
+    @Override
+    public void onMediaResourceLoadError(
+            final MediaRequest<ImageResource> request, final Exception exception) {
+        // Media load failed, unbind and reset bitmap to default.
+        unbindView();
+        setImage(null);
+    }
+
+    private void releaseImageResource() {
+        final Drawable drawable = getDrawable();
+        if (drawable instanceof FrameSequenceDrawable) {
+            ((FrameSequenceDrawable) drawable).stop();
+            ((FrameSequenceDrawable) drawable).destroy();
+        }
+        if (mImageResource != null) {
+            mImageResource.release();
+            mImageResource = null;
+        }
+        setImageDrawable(null);
+        setBackground(null);
+    }
+
+    /**
+     * Resets transient view states (eg. alpha, animations) before rebinding/reusing the view.
+     */
+    private void resetTransientViewStates() {
+        clearAnimation();
+        setAlpha(1F);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        // If it was recently removed, then cancel disposing, we're still using it.
+        ThreadUtil.getMainThreadHandler().removeCallbacks(mDisposeRunnable);
+
+        // When the image view gets detached and immediately re-attached, any fade-in animation
+        // will be terminated, leaving the view in a semi-transparent state. Make sure we restore
+        // alpha when the view is re-attached.
+        if (mFadeIn) {
+            setAlpha(1F);
+        }
+
+        // Check whether we are in a simple reuse scenario: detached from window, and reattached
+        // later without rebinding. This may be done by containers such as the RecyclerView to
+        // reuse the views. In this case, we would like to rebind the original image request.
+        if (!mImageRequestBinding.isBound() && mDetachedRequestDescriptor != null) {
+            setImageResourceId(mDetachedRequestDescriptor);
+        }
+        mDetachedRequestDescriptor = null;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        // Dispose the bitmap, but if an AysncImageView is removed from the window, then quickly
+        // re-added, we shouldn't dispose, so wait a short time before disposing
+        ThreadUtil.getMainThreadHandler().postDelayed(mDisposeRunnable, DISPOSE_IMAGE_DELAY);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        // The base implementation does not honor the minimum sizes. We try to to honor it here.
+
+        final int measuredWidth = getMeasuredWidth();
+        final int measuredHeight = getMeasuredHeight();
+        if (measuredWidth >= getMinimumWidth() || measuredHeight >= getMinimumHeight()) {
+            // We are ok if either of the minimum sizes is honored. Note that satisfying both the
+            // sizes may not be possible, depending on the aspect ratio of the image and whether
+            // a maximum size has been specified. This implementation only tries to handle the case
+            // where both the minimum sizes are not being satisfied.
+            return;
+        }
+
+        if (!getAdjustViewBounds()) {
+            // The base implementation is reasonable in this case. If the view bounds cannot be
+            // changed, it is not possible to satisfy the minimum sizes anyway.
+            return;
+        }
+
+        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+        if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
+            // The base implementation is reasonable in this case.
+            return;
+        }
+
+        int width = measuredWidth;
+        int height = measuredHeight;
+        // Get the minimum sizes that will honor other constraints as well.
+        final int minimumWidth = resolveSize(
+                getMinimumWidth(), getMaxWidth(), widthMeasureSpec);
+        final int minimumHeight = resolveSize(
+                getMinimumHeight(), getMaxHeight(), heightMeasureSpec);
+        final float aspectRatio = measuredWidth / (float) measuredHeight;
+        if (aspectRatio == 0) {
+            // If the image is (close to) infinitely high, there is not much we can do.
+            return;
+        }
+
+        if (width < minimumWidth) {
+            height = resolveSize((int) (minimumWidth / aspectRatio),
+                    getMaxHeight(), heightMeasureSpec);
+            width = (int) (height * aspectRatio);
+        }
+
+        if (height < minimumHeight) {
+            width = resolveSize((int) (minimumHeight * aspectRatio),
+                    getMaxWidth(), widthMeasureSpec);
+            height = (int) (width / aspectRatio);
+        }
+
+        setMeasuredDimension(width, height);
+    }
+
+    private static int resolveSize(int desiredSize, int maxSize, int measureSpec) {
+        final int specMode = MeasureSpec.getMode(measureSpec);
+        final int specSize =  MeasureSpec.getSize(measureSpec);
+        switch(specMode) {
+            case MeasureSpec.UNSPECIFIED:
+                return Math.min(desiredSize, maxSize);
+
+            case MeasureSpec.AT_MOST:
+                return Math.min(Math.min(desiredSize, specSize), maxSize);
+
+            default:
+                Assert.fail("Unreachable");
+                return specSize;
+        }
+    }
+
+    @Override
+    protected void onDraw(final Canvas canvas) {
+        if (mCornerRadius > 0) {
+            final int currentWidth = this.getWidth();
+            final int currentHeight = this.getHeight();
+            if (mClipPathWidth != currentWidth || mClipPathHeight != currentHeight) {
+                final RectF rect = new RectF(0, 0, currentWidth, currentHeight);
+                mRoundedCornerClipPath.reset();
+                mRoundedCornerClipPath.addRoundRect(rect, mCornerRadius, mCornerRadius,
+                        Path.Direction.CW);
+                mClipPathWidth = currentWidth;
+                mClipPathHeight = currentHeight;
+            }
+
+            final int saveCount = canvas.getSaveCount();
+            canvas.save();
+            canvas.clipPath(mRoundedCornerClipPath);
+            super.onDraw(canvas);
+            canvas.restoreToCount(saveCount);
+        } else {
+            super.onDraw(canvas);
+        }
+    }
+
+    private void unbindView() {
+        if (mImageRequestBinding.isBound()) {
+            mImageRequestBinding.unbind();
+            if (mDelayLoader != null) {
+                mDelayLoader.unregisterView(this);
+            }
+        }
+    }
+
+    /**
+     * As a performance optimization, the consumer of the AsyncImageView may opt to delay loading
+     * the image when it's busy doing other things (such as when a list view is scrolling). In
+     * order to do this, the consumer can create a new AsyncImageViewDelayLoader instance to be
+     * shared among all relevant AsyncImageViews (through setDelayLoader() method), and call
+     * onStartDelayLoading() and onStopDelayLoading() to start and stop delay loading, respectively.
+     */
+    public static class AsyncImageViewDelayLoader {
+        private boolean mShouldDelayLoad;
+        private final HashSet<AsyncImageView> mAttachedViews;
+
+        public AsyncImageViewDelayLoader() {
+            mAttachedViews = new HashSet<AsyncImageView>();
+        }
+
+        private void registerView(final AsyncImageView view) {
+            mAttachedViews.add(view);
+        }
+
+        private void unregisterView(final AsyncImageView view) {
+            mAttachedViews.remove(view);
+        }
+
+        public boolean isDelayLoadingImage() {
+            return mShouldDelayLoad;
+        }
+
+        /**
+         * Called by the consumer of this view to delay loading images
+         */
+        public void onDelayLoading() {
+            // Don't need to explicitly tell the AsyncImageView to stop loading since
+            // ImageRequests are not cancellable.
+            mShouldDelayLoad = true;
+        }
+
+        /**
+         * Called by the consumer of this view to resume loading images
+         */
+        public void onResumeLoading() {
+            if (mShouldDelayLoad) {
+                mShouldDelayLoad = false;
+
+                // Notify all attached views to resume loading.
+                for (final AsyncImageView view : mAttachedViews) {
+                    view.resumeLoading();
+                }
+                mAttachedViews.clear();
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/AttachmentPreview.java b/src/com/android/messaging/ui/AttachmentPreview.java
new file mode 100644
index 0000000..f4465c4
--- /dev/null
+++ b/src/com/android/messaging/ui/AttachmentPreview.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ScrollView;
+
+import com.android.messaging.R;
+import com.android.messaging.annotation.VisibleForAnimation;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.MediaPickerMessagePartData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.ui.MultiAttachmentLayout.OnAttachmentClickListener;
+import com.android.messaging.ui.animation.PopupTransitionAnimation;
+import com.android.messaging.ui.conversation.ComposeMessageView;
+import com.android.messaging.ui.conversation.ConversationFragment;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ThreadUtil;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AttachmentPreview extends ScrollView implements OnAttachmentClickListener {
+    private FrameLayout mAttachmentView;
+    private ComposeMessageView mComposeMessageView;
+    private ImageButton mCloseButton;
+    private int mAnimatedHeight = -1;
+    private Animator mCloseGapAnimator;
+    private boolean mPendingFirstUpdate;
+    private Handler mHandler;
+    private Runnable mHideRunnable;
+    private boolean mPendingHideCanceled;
+
+    private PopupTransitionAnimation mPopupTransitionAnimation;
+
+    private static final int CLOSE_BUTTON_REVEAL_STAGGER_MILLIS = 300;
+
+    public AttachmentPreview(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mHandler = new Handler(Looper.getMainLooper());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mCloseButton = (ImageButton) findViewById(R.id.close_button);
+        mCloseButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                mComposeMessageView.clearAttachments();
+            }
+        });
+
+        mAttachmentView = (FrameLayout) findViewById(R.id.attachment_view);
+
+        // The attachment preview is a scroll view so that it can show the bottom portion of the
+        // attachment whenever the space is tight (e.g. when in landscape mode). Per design
+        // request we'd like to make the attachment view always scrolled to the bottom.
+        addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(final View v, final int left, final int top, final int right,
+                    final int bottom, final int oldLeft, final int oldTop, final int oldRight,
+                    final int oldBottom) {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        final int childCount = getChildCount();
+                        if (childCount > 0) {
+                            final View lastChild = getChildAt(childCount - 1);
+                            scrollTo(getScrollX(), lastChild.getBottom() - getHeight());
+                        }
+                    }
+                });
+            }
+        });
+        mPendingFirstUpdate = true;
+    }
+
+    public void setComposeMessageView(final ComposeMessageView composeMessageView) {
+        mComposeMessageView = composeMessageView;
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mAnimatedHeight >= 0) {
+            setMeasuredDimension(getMeasuredWidth(), mAnimatedHeight);
+        }
+    }
+
+    private void cancelPendingHide() {
+        mPendingHideCanceled = true;
+    }
+
+    public void hideAttachmentPreview() {
+        if (getVisibility() != GONE) {
+            UiUtils.revealOrHideViewWithAnimation(mCloseButton, GONE,
+                    null /* onFinishRunnable */);
+            startCloseGapAnimationOnAttachmentClear();
+
+            if (mAttachmentView.getChildCount() > 0) {
+                mPendingHideCanceled = false;
+                final View viewToHide = mAttachmentView.getChildCount() > 1 ?
+                        mAttachmentView : mAttachmentView.getChildAt(0);
+                UiUtils.revealOrHideViewWithAnimation(viewToHide, INVISIBLE,
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                // Only hide if we are didn't get overruled by showing
+                                if (!mPendingHideCanceled) {
+                                    stopPopupAnimation();
+                                    mAttachmentView.removeAllViews();
+                                    setVisibility(GONE);
+                                }
+                            }
+                        });
+            } else {
+                mAttachmentView.removeAllViews();
+                setVisibility(GONE);
+            }
+        }
+    }
+
+    // returns true if we have attachments
+    public boolean onAttachmentsChanged(final DraftMessageData draftMessageData) {
+        final boolean isFirstUpdate = mPendingFirstUpdate;
+        final List<MessagePartData> attachments = draftMessageData.getReadOnlyAttachments();
+        final List<PendingAttachmentData> pendingAttachments =
+                draftMessageData.getReadOnlyPendingAttachments();
+
+        // Any change in attachments would invalidate the animated height animation.
+        cancelCloseGapAnimation();
+        mPendingFirstUpdate = false;
+
+        final int combinedAttachmentCount = attachments.size() + pendingAttachments.size();
+        mCloseButton.setContentDescription(getResources()
+                .getQuantityString(R.plurals.attachment_preview_close_content_description,
+                        combinedAttachmentCount));
+        if (combinedAttachmentCount == 0) {
+            mHideRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    mHideRunnable = null;
+                    // Only start the hiding if there are still no attachments
+                    if (attachments.size() + pendingAttachments.size() == 0) {
+                        hideAttachmentPreview();
+                    }
+                }
+            };
+            if (draftMessageData.isSending()) {
+                // Wait to hide until the message is ready to start animating
+                // We'll execute immediately when the animation triggers
+                mHandler.postDelayed(mHideRunnable,
+                        ConversationFragment.MESSAGE_ANIMATION_MAX_WAIT);
+            } else {
+                // Run immediately when clearing attachments
+                mHideRunnable.run();
+            }
+            return false;
+        }
+
+        cancelPendingHide();  // We're showing
+        if (getVisibility() != VISIBLE) {
+            setVisibility(VISIBLE);
+            mAttachmentView.setVisibility(VISIBLE);
+
+            // Don't animate in the close button if this is the first update after view creation.
+            // This is the initial draft load from database for pre-existing drafts.
+            if (!isFirstUpdate) {
+                // Reveal the close button after the view animates in.
+                mCloseButton.setVisibility(INVISIBLE);
+                ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        UiUtils.revealOrHideViewWithAnimation(mCloseButton, VISIBLE,
+                                null /* onFinishRunnable */);
+                    }
+                }, UiUtils.MEDIAPICKER_TRANSITION_DURATION + CLOSE_BUTTON_REVEAL_STAGGER_MILLIS);
+            }
+        }
+
+        // Merge the pending attachment list with real attachment.  Design would prefer these be
+        // in LIFO order user can see added images past the 5th one but we also want them to be in
+        // order and we want it to be WYSIWYG.
+        final List<MessagePartData> combinedAttachments = new ArrayList<>();
+        combinedAttachments.addAll(attachments);
+        combinedAttachments.addAll(pendingAttachments);
+
+        final LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+        if (combinedAttachmentCount > 1) {
+            MultiAttachmentLayout multiAttachmentLayout = null;
+            Rect transitionRect = null;
+            if (mAttachmentView.getChildCount() > 0) {
+                final View firstChild = mAttachmentView.getChildAt(0);
+                if (firstChild instanceof MultiAttachmentLayout) {
+                    Assert.equals(1, mAttachmentView.getChildCount());
+                    multiAttachmentLayout = (MultiAttachmentLayout) firstChild;
+                    multiAttachmentLayout.bindAttachments(combinedAttachments,
+                            null /* transitionRect */, combinedAttachmentCount);
+                } else {
+                    transitionRect = new Rect(firstChild.getLeft(), firstChild.getTop(),
+                            firstChild.getRight(), firstChild.getBottom());
+                }
+            }
+            if (multiAttachmentLayout == null) {
+                multiAttachmentLayout = AttachmentPreviewFactory.createMultiplePreview(
+                        getContext(), this);
+                multiAttachmentLayout.bindAttachments(combinedAttachments, transitionRect,
+                        combinedAttachmentCount);
+                mAttachmentView.removeAllViews();
+                mAttachmentView.addView(multiAttachmentLayout);
+            }
+        } else {
+            final MessagePartData attachment = combinedAttachments.get(0);
+            boolean shouldAnimate = true;
+            if (mAttachmentView.getChildCount() > 0) {
+                // If we are going from N->1 attachments, try to use the current bounds
+                // bounds as the starting rect.
+                shouldAnimate = false;
+                final View firstChild = mAttachmentView.getChildAt(0);
+                if (firstChild instanceof MultiAttachmentLayout &&
+                        attachment instanceof MediaPickerMessagePartData) {
+                    final View leftoverView = ((MultiAttachmentLayout) firstChild)
+                            .findViewForAttachment(attachment);
+                    if (leftoverView != null) {
+                        final Rect currentRect = UiUtils.getMeasuredBoundsOnScreen(leftoverView);
+                        if (!currentRect.isEmpty() &&
+                                attachment instanceof MediaPickerMessagePartData) {
+                            ((MediaPickerMessagePartData) attachment).setStartRect(currentRect);
+                            shouldAnimate = true;
+                        }
+                    }
+                }
+            }
+            mAttachmentView.removeAllViews();
+            final View attachmentView = AttachmentPreviewFactory.createAttachmentPreview(
+                    layoutInflater, attachment, mAttachmentView,
+                    AttachmentPreviewFactory.TYPE_SINGLE, true /* startImageRequest */, this);
+            if (attachmentView != null) {
+                mAttachmentView.addView(attachmentView);
+                if (shouldAnimate) {
+                    tryAnimateViewIn(attachment, attachmentView);
+                }
+            }
+        }
+        return true;
+    }
+
+    public void onMessageAnimationStart() {
+        if (mHideRunnable == null) {
+            return;
+        }
+
+        // Run the hide animation at the same time as the message animation
+        mHandler.removeCallbacks(mHideRunnable);
+        setVisibility(View.INVISIBLE);
+        mHideRunnable.run();
+    }
+
+    private void tryAnimateViewIn(final MessagePartData attachmentData, final View view) {
+        if (attachmentData instanceof MediaPickerMessagePartData) {
+            final Rect startRect = ((MediaPickerMessagePartData) attachmentData).getStartRect();
+            stopPopupAnimation();
+            mPopupTransitionAnimation = new PopupTransitionAnimation(startRect, view);
+            mPopupTransitionAnimation.startAfterLayoutComplete();
+        }
+    }
+
+    private void stopPopupAnimation() {
+        if (mPopupTransitionAnimation != null) {
+            mPopupTransitionAnimation.cancel();
+            mPopupTransitionAnimation = null;
+        }
+    }
+
+    @VisibleForAnimation
+    public void setAnimatedHeight(final int animatedHeight) {
+        if (mAnimatedHeight != animatedHeight) {
+            mAnimatedHeight = animatedHeight;
+            requestLayout();
+        }
+    }
+
+    /**
+     * Kicks off an animation to animate the layout change for closing the gap between the
+     * message list and the compose message box when the attachments are cleared.
+     */
+    private void startCloseGapAnimationOnAttachmentClear() {
+        // Cancel existing animation.
+        cancelCloseGapAnimation();
+        mCloseGapAnimator = ObjectAnimator.ofInt(this, "animatedHeight", getHeight(), 0);
+        mCloseGapAnimator.start();
+    }
+
+    private void cancelCloseGapAnimation() {
+        if (mCloseGapAnimator != null) {
+            mCloseGapAnimator.cancel();
+            mCloseGapAnimator = null;
+        }
+        mAnimatedHeight = -1;
+    }
+
+    @Override
+    public boolean onAttachmentClick(final MessagePartData attachment,
+            final Rect viewBoundsOnScreen, final boolean longPress) {
+        if (longPress) {
+            mComposeMessageView.onAttachmentPreviewLongClicked();
+            return true;
+        }
+
+        if (!(attachment instanceof PendingAttachmentData) && attachment.isImage()) {
+            mComposeMessageView.displayPhoto(attachment.getContentUri(), viewBoundsOnScreen);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/messaging/ui/AttachmentPreviewFactory.java b/src/com/android/messaging/ui/AttachmentPreviewFactory.java
new file mode 100644
index 0000000..e801fe0
--- /dev/null
+++ b/src/com/android/messaging/ui/AttachmentPreviewFactory.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.net.Uri;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.datamodel.data.VCardContactItemData;
+import com.android.messaging.datamodel.media.FileImageRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.ui.MultiAttachmentLayout.OnAttachmentClickListener;
+import com.android.messaging.ui.PersonItemView.PersonItemViewListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * A view factory that creates previews for single/multiple attachments.
+ */
+public class AttachmentPreviewFactory {
+    /** Standalone attachment preview */
+    public static final int TYPE_SINGLE = 1;
+
+    /** Attachment preview displayed in a multi-attachment layout */
+    public static final int TYPE_MULTIPLE = 2;
+
+    /** Attachment preview displayed in the attachment chooser grid view */
+    public static final int TYPE_CHOOSER_GRID = 3;
+
+    public static View createAttachmentPreview(final LayoutInflater layoutInflater,
+            final MessagePartData attachmentData, final ViewGroup parent,
+            final int viewType, final boolean startImageRequest,
+            @Nullable final OnAttachmentClickListener clickListener) {
+        final String contentType = attachmentData.getContentType();
+        View attachmentView = null;
+        if (attachmentData instanceof PendingAttachmentData) {
+            attachmentView = createPendingAttachmentPreview(layoutInflater, parent,
+                    (PendingAttachmentData) attachmentData);
+        } else if (ContentType.isImageType(contentType)) {
+            attachmentView = createImagePreview(layoutInflater, attachmentData, parent, viewType,
+                    startImageRequest);
+        } else if (ContentType.isAudioType(contentType)) {
+            attachmentView = createAudioPreview(layoutInflater, attachmentData, parent, viewType);
+        } else if (ContentType.isVideoType(contentType)) {
+            attachmentView = createVideoPreview(layoutInflater, attachmentData, parent, viewType);
+        } else if (ContentType.isVCardType(contentType)) {
+            attachmentView = createVCardPreview(layoutInflater, attachmentData, parent, viewType);
+        } else {
+            Assert.fail("unsupported attachment type: " + contentType);
+            return null;
+        }
+
+        // Some views have a caption, set the text/visibility if one exists
+        final TextView captionView = (TextView) attachmentView.findViewById(R.id.caption);
+        if (captionView != null) {
+            final String caption = attachmentData.getText();
+            captionView.setVisibility(TextUtils.isEmpty(caption) ? View.GONE : View.VISIBLE);
+            captionView.setText(caption);
+        }
+
+        if (attachmentView != null && clickListener != null) {
+            attachmentView.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(final View view) {
+                        final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
+                        clickListener.onAttachmentClick(attachmentData, bounds,
+                                false /* longPress */);
+                    }
+                });
+            attachmentView.setOnLongClickListener(new OnLongClickListener() {
+                    @Override
+                    public boolean onLongClick(final View view) {
+                        final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
+                        return clickListener.onAttachmentClick(attachmentData, bounds,
+                                true /* longPress */);
+                    }
+                });
+        }
+        return attachmentView;
+    }
+
+    public static MultiAttachmentLayout createMultiplePreview(final Context context,
+            final OnAttachmentClickListener listener) {
+        final MultiAttachmentLayout multiAttachmentLayout =
+                new MultiAttachmentLayout(context, null);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        multiAttachmentLayout.setLayoutParams(layoutParams);
+        multiAttachmentLayout.setOnAttachmentClickListener(listener);
+        return multiAttachmentLayout;
+    }
+
+    public static ImageRequestDescriptor getImageRequestDescriptorForAttachment(
+            final MessagePartData attachmentData, final int desiredWidth, final int desiredHeight) {
+        final Uri uri = attachmentData.getContentUri();
+        final String contentType = attachmentData.getContentType();
+        if (ContentType.isImageType(contentType)) {
+            final String filePath = UriUtil.getFilePathFromUri(uri);
+            if (filePath != null) {
+                return new FileImageRequestDescriptor(filePath, desiredWidth, desiredHeight,
+                        attachmentData.getWidth(), attachmentData.getHeight(),
+                        false /* canUseThumbnail */, true /* allowCompression */,
+                        false /* isStatic */);
+            } else {
+                return new UriImageRequestDescriptor(uri, desiredWidth, desiredHeight,
+                        attachmentData.getWidth(), attachmentData.getHeight(),
+                        true /* allowCompression */, false /* isStatic */, false /*cropToCircle*/,
+                        ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                        ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+            }
+        }
+        return null;
+    }
+
+    private static View createImagePreview(final LayoutInflater layoutInflater,
+            final MessagePartData attachmentData, final ViewGroup parent,
+            final int viewType, final boolean startImageRequest) {
+        int layoutId = R.layout.attachment_single_image;
+        switch (viewType) {
+            case AttachmentPreviewFactory.TYPE_SINGLE:
+                layoutId = R.layout.attachment_single_image;
+                break;
+            case AttachmentPreviewFactory.TYPE_MULTIPLE:
+                layoutId = R.layout.attachment_multiple_image;
+                break;
+            case AttachmentPreviewFactory.TYPE_CHOOSER_GRID:
+                layoutId = R.layout.attachment_chooser_image;
+                break;
+            default:
+                Assert.fail("unsupported attachment view type!");
+                break;
+        }
+        final View view = layoutInflater.inflate(layoutId, parent, false /* attachToRoot */);
+        final AsyncImageView imageView = (AsyncImageView) view.findViewById(
+                R.id.attachment_image_view);
+        int maxWidth = imageView.getMaxWidth();
+        int maxHeight = imageView.getMaxHeight();
+        if (viewType == TYPE_CHOOSER_GRID) {
+            final Resources resources = layoutInflater.getContext().getResources();
+            maxWidth = maxHeight = resources.getDimensionPixelSize(
+                    R.dimen.attachment_grid_image_cell_size);
+        }
+        if (maxWidth <= 0 || maxWidth == Integer.MAX_VALUE) {
+            maxWidth = ImageRequest.UNSPECIFIED_SIZE;
+        }
+        if (maxHeight <= 0 || maxHeight == Integer.MAX_VALUE) {
+            maxHeight = ImageRequest.UNSPECIFIED_SIZE;
+        }
+        if (startImageRequest) {
+            imageView.setImageResourceId(getImageRequestDescriptorForAttachment(attachmentData,
+                    maxWidth, maxHeight));
+        }
+        imageView.setContentDescription(
+                parent.getResources().getString(R.string.message_image_content_description));
+        return view;
+    }
+
+    private static View createPendingAttachmentPreview(final LayoutInflater layoutInflater,
+            final ViewGroup parent, final PendingAttachmentData attachmentData) {
+        final View pendingItemView = layoutInflater.inflate(R.layout.attachment_pending_item,
+                parent, false);
+        final ImageView imageView = (ImageView)
+                pendingItemView.findViewById(R.id.pending_item_view);
+        final ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
+        final int defaultSize = layoutInflater.getContext().getResources().getDimensionPixelSize(
+                R.dimen.pending_attachment_size);
+        layoutParams.width = attachmentData.getWidth() == MessagePartData.UNSPECIFIED_SIZE ?
+                defaultSize : attachmentData.getWidth();
+        layoutParams.height = attachmentData.getHeight() == MessagePartData.UNSPECIFIED_SIZE ?
+                defaultSize : attachmentData.getHeight();
+        return pendingItemView;
+    }
+
+    private static View createVCardPreview(final LayoutInflater layoutInflater,
+            final MessagePartData attachmentData, final ViewGroup parent,
+            final int viewType) {
+        int layoutId = R.layout.attachment_single_vcard;
+        switch (viewType) {
+            case AttachmentPreviewFactory.TYPE_SINGLE:
+                layoutId = R.layout.attachment_single_vcard;
+                break;
+            case AttachmentPreviewFactory.TYPE_MULTIPLE:
+                layoutId = R.layout.attachment_multiple_vcard;
+                break;
+            case AttachmentPreviewFactory.TYPE_CHOOSER_GRID:
+                layoutId = R.layout.attachment_chooser_vcard;
+                break;
+            default:
+                Assert.fail("unsupported attachment view type!");
+                break;
+        }
+        final View view = layoutInflater.inflate(layoutId, parent, false /* attachToRoot */);
+        final PersonItemView vcardPreview = (PersonItemView) view.findViewById(
+                R.id.vcard_attachment_view);
+        vcardPreview.setAvatarOnly(viewType != AttachmentPreviewFactory.TYPE_SINGLE);
+        vcardPreview.bind(DataModel.get().createVCardContactItemData(layoutInflater.getContext(),
+                attachmentData));
+        vcardPreview.setListener(new PersonItemViewListener() {
+            @Override
+            public void onPersonClicked(final PersonItemData data) {
+                Assert.isTrue(data instanceof VCardContactItemData);
+                final VCardContactItemData vCardData = (VCardContactItemData) data;
+                if (vCardData.hasValidVCard()) {
+                    final Uri vCardUri = vCardData.getVCardUri();
+                    UIIntents.get().launchVCardDetailActivity(vcardPreview.getContext(), vCardUri);
+                }
+            }
+
+            @Override
+            public boolean onPersonLongClicked(final PersonItemData data) {
+                return false;
+            }
+        });
+        return view;
+    }
+
+    private static View createAudioPreview(final LayoutInflater layoutInflater,
+                final MessagePartData attachmentData, final ViewGroup parent,
+                final int viewType) {
+        int layoutId = R.layout.attachment_single_audio;
+        switch (viewType) {
+            case AttachmentPreviewFactory.TYPE_SINGLE:
+                layoutId = R.layout.attachment_single_audio;
+                break;
+            case AttachmentPreviewFactory.TYPE_MULTIPLE:
+                layoutId = R.layout.attachment_multiple_audio;
+                break;
+            case AttachmentPreviewFactory.TYPE_CHOOSER_GRID:
+                layoutId = R.layout.attachment_chooser_audio;
+                break;
+            default:
+                Assert.fail("unsupported attachment view type!");
+                break;
+        }
+        final View view = layoutInflater.inflate(layoutId, parent, false /* attachToRoot */);
+        final AudioAttachmentView audioView = (AudioAttachmentView)
+                view.findViewById(R.id.audio_attachment_view);
+        audioView.bindMessagePartData(
+                attachmentData, false /* incoming */, false /* showAsSelected */);
+        return view;
+    }
+
+    private static View createVideoPreview(final LayoutInflater layoutInflater,
+            final MessagePartData attachmentData, final ViewGroup parent,
+            final int viewType) {
+        int layoutId = R.layout.attachment_single_video;
+        switch (viewType) {
+            case AttachmentPreviewFactory.TYPE_SINGLE:
+                layoutId = R.layout.attachment_single_video;
+                break;
+            case AttachmentPreviewFactory.TYPE_MULTIPLE:
+                layoutId = R.layout.attachment_multiple_video;
+                break;
+            case AttachmentPreviewFactory.TYPE_CHOOSER_GRID:
+                layoutId = R.layout.attachment_chooser_video;
+                break;
+            default:
+                Assert.fail("unsupported attachment view type!");
+                break;
+        }
+        final VideoThumbnailView videoThumbnail = (VideoThumbnailView) layoutInflater.inflate(
+                layoutId, parent, false /* attachToRoot */);
+        videoThumbnail.setSource(attachmentData, false /* incomingMessage */);
+        return videoThumbnail;
+    }
+}
diff --git a/src/com/android/messaging/ui/AudioAttachmentPlayPauseButton.java b/src/com/android/messaging/ui/AudioAttachmentPlayPauseButton.java
new file mode 100644
index 0000000..724c4fe
--- /dev/null
+++ b/src/com/android/messaging/ui/AudioAttachmentPlayPauseButton.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.ViewSwitcher;
+
+import com.android.messaging.R;
+
+/**
+ * Shows a tinted play pause button.
+ */
+public class AudioAttachmentPlayPauseButton extends ViewSwitcher {
+    private ImageView mPlayButton;
+    private ImageView mPauseButton;
+
+    private boolean mShowAsIncoming;
+
+    public AudioAttachmentPlayPauseButton(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mPlayButton = (ImageView) findViewById(R.id.play_button);
+        mPauseButton = (ImageView) findViewById(R.id.pause_button);
+        updateAppearance();
+    }
+
+    public void setVisualStyle(final boolean showAsIncoming) {
+        if (mShowAsIncoming != showAsIncoming) {
+            mShowAsIncoming = showAsIncoming;
+            updateAppearance();
+        }
+    }
+
+    private void updateAppearance() {
+        mPlayButton.setImageDrawable(ConversationDrawables.get()
+                .getPlayButtonDrawable(mShowAsIncoming));
+        mPauseButton.setImageDrawable(ConversationDrawables.get()
+                .getPauseButtonDrawable(mShowAsIncoming));
+    }
+}
diff --git a/src/com/android/messaging/ui/AudioAttachmentView.java b/src/com/android/messaging/ui/AudioAttachmentView.java
new file mode 100644
index 0000000..ad91ed2
--- /dev/null
+++ b/src/com/android/messaging/ui/AudioAttachmentView.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.mediapicker.PausableChronometer;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * A reusable widget that hosts an audio player for audio attachment playback. This widget is used
+ * by both the media picker and the conversation message view to show audio attachments.
+ */
+public class AudioAttachmentView extends LinearLayout {
+    /** The normal layout mode where we have the play button, timer and progress bar */
+    private static final int LAYOUT_MODE_NORMAL = 0;
+
+    /** The compact layout mode with only the play button and the timer beneath it. Suitable
+     *  for displaying in limited space such as multi-attachment layout */
+    private static final int LAYOUT_MODE_COMPACT = 1;
+
+    /** The sub-compact layout mode with only the play button. */
+    private static final int LAYOUT_MODE_SUB_COMPACT = 2;
+
+    private static final int PLAY_BUTTON = 0;
+    private static final int PAUSE_BUTTON = 1;
+
+    private AudioAttachmentPlayPauseButton mPlayPauseButton;
+    private PausableChronometer mChronometer;
+    private AudioPlaybackProgressBar mProgressBar;
+    private MediaPlayer mMediaPlayer;
+
+    private Uri mDataSourceUri;
+
+    // The corner radius for drawing rounded corners. The default value is zero (no rounded corners)
+    private final int mCornerRadius;
+    private final Path mRoundedCornerClipPath;
+    private int mClipPathWidth;
+    private int mClipPathHeight;
+
+    private boolean mUseIncomingStyle;
+    private int mThemeColor;
+
+    private boolean mStartPlayAfterPrepare;
+    // should the MediaPlayer be prepared lazily when the user chooses to play the audio (as
+    // opposed to preparing it early, on bind)
+    private boolean mPrepareOnPlayback;
+    private boolean mPrepared;
+    private boolean mPlaybackFinished; // Was the audio played all the way to the end
+    private final int mMode;
+
+    public AudioAttachmentView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        final TypedArray typedAttributes =
+                context.obtainStyledAttributes(attrs, R.styleable.AudioAttachmentView);
+        mMode = typedAttributes.getInt(R.styleable.AudioAttachmentView_layoutMode,
+                LAYOUT_MODE_NORMAL);
+        final LayoutInflater inflater = LayoutInflater.from(getContext());
+        inflater.inflate(R.layout.audio_attachment_view, this, true);
+        typedAttributes.recycle();
+
+        setWillNotDraw(mMode != LAYOUT_MODE_SUB_COMPACT);
+        mRoundedCornerClipPath = new Path();
+        mCornerRadius = context.getResources().getDimensionPixelSize(
+                R.dimen.conversation_list_image_preview_corner_radius);
+        setContentDescription(context.getString(R.string.audio_attachment_content_description));
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mPlayPauseButton = (AudioAttachmentPlayPauseButton) findViewById(R.id.play_pause_button);
+        mChronometer = (PausableChronometer) findViewById(R.id.timer);
+        mProgressBar = (AudioPlaybackProgressBar) findViewById(R.id.progress);
+        mPlayPauseButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                // Has the MediaPlayer already been prepared?
+                if (mMediaPlayer != null && mPrepared) {
+                    if (mMediaPlayer.isPlaying()) {
+                        mMediaPlayer.pause();
+                        mChronometer.pause();
+                        mProgressBar.pause();
+                    } else {
+                        playAudio();
+                    }
+                } else {
+                    // Either eager preparation is still going on (the user must have clicked
+                    // the Play button immediately after the view is bound) or this is lazy
+                    // preparation.
+                    if (mStartPlayAfterPrepare) {
+                        // The user is (starting and) pausing before the MediaPlayer is prepared
+                        mStartPlayAfterPrepare = false;
+                    } else {
+                        mStartPlayAfterPrepare = true;
+                        setupMediaPlayer();
+                    }
+                }
+                updatePlayPauseButtonState();
+            }
+        });
+        updatePlayPauseButtonState();
+        initializeViewsForMode();
+    }
+
+    private void updateChronometerVisibility(final boolean playing) {
+        if (mChronometer.getVisibility() == View.GONE) {
+            // The chronometer is always GONE for LAYOUT_MODE_SUB_COMPACT
+            Assert.equals(LAYOUT_MODE_SUB_COMPACT, mMode);
+            return;
+        }
+
+        if (mPrepareOnPlayback) {
+            // For lazy preparation, the chronometer will only be shown during playback
+            mChronometer.setVisibility(playing ? View.VISIBLE : View.INVISIBLE);
+        } else {
+            mChronometer.setVisibility(View.VISIBLE);
+        }
+    }
+
+    /**
+     * Bind the audio attachment view with a MessagePartData.
+     * @param incoming indicates whether the attachment view is to be styled as a part of an
+     *        incoming message.
+     */
+    public void bindMessagePartData(final MessagePartData messagePartData,
+            final boolean incoming, final boolean showAsSelected) {
+        Assert.isTrue(messagePartData == null ||
+                ContentType.isAudioType(messagePartData.getContentType()));
+        final Uri contentUri = (messagePartData == null) ? null : messagePartData.getContentUri();
+        bind(contentUri, incoming, showAsSelected);
+    }
+
+    public void bind(
+            final Uri dataSourceUri, final boolean incoming, final boolean showAsSelected) {
+        final String currentUriString = (mDataSourceUri == null) ? "" : mDataSourceUri.toString();
+        final String newUriString = (dataSourceUri == null) ? "" : dataSourceUri.toString();
+        final int themeColor = ConversationDrawables.get().getConversationThemeColor();
+        final boolean useIncomingStyle = incoming || showAsSelected;
+        final boolean visualStyleChanged = mThemeColor != themeColor ||
+                mUseIncomingStyle != useIncomingStyle;
+
+        mUseIncomingStyle = useIncomingStyle;
+        mThemeColor = themeColor;
+        mPrepareOnPlayback = incoming && !MediaUtil.canAutoAccessIncomingMedia();
+
+        if (!TextUtils.equals(currentUriString, newUriString)) {
+            mDataSourceUri = dataSourceUri;
+            resetToZeroState();
+        } else if (visualStyleChanged) {
+            updateVisualStyle();
+        }
+    }
+
+    private void playAudio() {
+        Assert.notNull(mMediaPlayer);
+        if (mPlaybackFinished) {
+            mMediaPlayer.seekTo(0);
+            mChronometer.restart();
+            mProgressBar.restart();
+            mPlaybackFinished = false;
+        } else {
+            mChronometer.resume();
+            mProgressBar.resume();
+        }
+        mMediaPlayer.start();
+    }
+
+    private void onAudioReplayError(final int what, final int extra, final Exception exception) {
+        if (exception == null) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "audio replay failed, what=" + what +
+                    ", extra=" + extra);
+        } else {
+            LogUtil.e(LogUtil.BUGLE_TAG, "audio replay failed, exception=" + exception);
+        }
+        UiUtils.showToastAtBottom(R.string.audio_recording_replay_failed);
+        releaseMediaPlayer();
+    }
+
+    /**
+     * Prepare the MediaPlayer, and if mPrepareOnPlayback, start playing the audio
+     */
+    private void setupMediaPlayer() {
+        Assert.notNull(mDataSourceUri);
+        if (mMediaPlayer == null) {
+            Assert.isTrue(!mPrepared);
+            mMediaPlayer = new MediaPlayer();
+
+            try {
+                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+                mMediaPlayer.setDataSource(Factory.get().getApplicationContext(), mDataSourceUri);
+                mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
+                    @Override
+                    public void onCompletion(final MediaPlayer mp) {
+                        updatePlayPauseButtonState();
+                        mChronometer.reset();
+                        mChronometer.setBase(SystemClock.elapsedRealtime() -
+                                mMediaPlayer.getDuration());
+                        updateChronometerVisibility(false /* playing */);
+                        mProgressBar.reset();
+
+                        mPlaybackFinished = true;
+                    }
+                });
+
+                mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
+                    @Override
+                    public void onPrepared(final MediaPlayer mp) {
+                        // Set base on the chronometer so we can show the full length of the audio.
+                        mChronometer.setBase(SystemClock.elapsedRealtime() -
+                                mMediaPlayer.getDuration());
+                        mProgressBar.setDuration(mMediaPlayer.getDuration());
+                        mMediaPlayer.seekTo(0);
+                        mPrepared = true;
+
+                        if (mStartPlayAfterPrepare) {
+                            mStartPlayAfterPrepare = false;
+                            playAudio();
+                            updatePlayPauseButtonState();
+                        }
+                    }
+                });
+
+                mMediaPlayer.setOnErrorListener(new OnErrorListener() {
+                    @Override
+                    public boolean onError(final MediaPlayer mp, final int what, final int extra) {
+                        mStartPlayAfterPrepare = false;
+                        onAudioReplayError(what, extra, null);
+                        return true;
+                    }
+                });
+
+                mMediaPlayer.prepareAsync();
+            } catch (final Exception exception) {
+                onAudioReplayError(0, 0, exception);
+                releaseMediaPlayer();
+            }
+        }
+    }
+
+    private void releaseMediaPlayer() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            mPrepared = false;
+            mStartPlayAfterPrepare = false;
+            mPlaybackFinished = false;
+            mChronometer.reset();
+            mProgressBar.reset();
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        // The view must have scrolled off. Stop playback.
+        releaseMediaPlayer();
+    }
+
+    @Override
+    protected void onDraw(final Canvas canvas) {
+        if (mMode != LAYOUT_MODE_SUB_COMPACT) {
+            return;
+        }
+
+        final int currentWidth = this.getWidth();
+        final int currentHeight = this.getHeight();
+        if (mClipPathWidth != currentWidth || mClipPathHeight != currentHeight) {
+            final RectF rect = new RectF(0, 0, currentWidth, currentHeight);
+            mRoundedCornerClipPath.reset();
+            mRoundedCornerClipPath.addRoundRect(rect, mCornerRadius, mCornerRadius,
+                    Path.Direction.CW);
+            mClipPathWidth = currentWidth;
+            mClipPathHeight = currentHeight;
+        }
+
+        canvas.clipPath(mRoundedCornerClipPath);
+        super.onDraw(canvas);
+    }
+
+    private void updatePlayPauseButtonState() {
+        final boolean playing = mMediaPlayer != null && mMediaPlayer.isPlaying();
+        updateChronometerVisibility(playing);
+        if (mStartPlayAfterPrepare || playing) {
+            mPlayPauseButton.setDisplayedChild(PAUSE_BUTTON);
+        } else {
+            mPlayPauseButton.setDisplayedChild(PLAY_BUTTON);
+        }
+    }
+
+    private void resetToZeroState() {
+        // Release the media player so it may be set up with the new audio source.
+        releaseMediaPlayer();
+        updateVisualStyle();
+        updateChronometerVisibility(false /* playing */);
+
+        if (mDataSourceUri != null && !mPrepareOnPlayback) {
+            // Prepare the media player, so we can read the duration of the audio.
+            setupMediaPlayer();
+        }
+    }
+
+    private void updateVisualStyle() {
+        if (mMode == LAYOUT_MODE_SUB_COMPACT) {
+            // Sub-compact mode has static visual appearance already set up during initialization.
+            return;
+        }
+
+        if (mUseIncomingStyle) {
+            mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_incoming));
+        } else {
+            mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_outgoing));
+        }
+        mProgressBar.setVisualStyle(mUseIncomingStyle);
+        mPlayPauseButton.setVisualStyle(mUseIncomingStyle);
+        updatePlayPauseButtonState();
+    }
+
+    private void initializeViewsForMode() {
+        switch (mMode) {
+            case LAYOUT_MODE_NORMAL:
+                setOrientation(HORIZONTAL);
+                mProgressBar.setVisibility(VISIBLE);
+                break;
+
+            case LAYOUT_MODE_COMPACT:
+                setOrientation(VERTICAL);
+                mProgressBar.setVisibility(GONE);
+                ((MarginLayoutParams) mPlayPauseButton.getLayoutParams()).setMargins(0, 0, 0, 0);
+                ((MarginLayoutParams) mChronometer.getLayoutParams()).setMargins(0, 0, 0, 0);
+                break;
+
+            case LAYOUT_MODE_SUB_COMPACT:
+                setOrientation(VERTICAL);
+                mProgressBar.setVisibility(GONE);
+                mChronometer.setVisibility(GONE);
+                ((MarginLayoutParams) mPlayPauseButton.getLayoutParams()).setMargins(0, 0, 0, 0);
+                final ImageView playButton = (ImageView) findViewById(R.id.play_button);
+                playButton.setImageDrawable(
+                        getResources().getDrawable(R.drawable.ic_preview_play));
+                final ImageView pauseButton = (ImageView) findViewById(R.id.pause_button);
+                pauseButton.setImageDrawable(
+                        getResources().getDrawable(R.drawable.ic_preview_pause));
+                break;
+
+            default:
+                Assert.fail("Unsupported mode for AudioAttachmentView!");
+                break;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/AudioPlaybackProgressBar.java b/src/com/android/messaging/ui/AudioPlaybackProgressBar.java
new file mode 100644
index 0000000..a5b3a57
--- /dev/null
+++ b/src/com/android/messaging/ui/AudioPlaybackProgressBar.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.animation.TimeAnimator.TimeListener;
+import android.content.Context;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.ProgressBar;
+
+/**
+ * Shows a styled progress bar that is synchronized with the playback state of an audio attachment.
+ */
+public class AudioPlaybackProgressBar extends ProgressBar implements PlaybackStateView {
+    private long mDurationInMillis;
+    private final TimeAnimator mUpdateAnimator;
+    private long mCumulativeTime = 0;
+    private long mCurrentPlayStartTime = 0;
+    private boolean mIncoming = false;
+
+    public AudioPlaybackProgressBar(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+
+        mUpdateAnimator = new TimeAnimator();
+        mUpdateAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+        mUpdateAnimator.setTimeListener(new TimeListener() {
+            @Override
+            public void onTimeUpdate(final TimeAnimator animation, final long totalTime,
+                    final long deltaTime) {
+                int progress = 0;
+                if (mDurationInMillis > 0) {
+                    progress = (int) (((mCumulativeTime + SystemClock.elapsedRealtime() -
+                            mCurrentPlayStartTime) * 1.0f / mDurationInMillis) * 100);
+                    progress = Math.max(Math.min(progress, 100), 0);
+                }
+                setProgress(progress);
+            }
+        });
+        updateAppearance();
+    }
+
+    /**
+     * Sets the duration of the audio that's being played, in milliseconds.
+     */
+    public void setDuration(final long durationInMillis) {
+        mDurationInMillis = durationInMillis;
+    }
+
+    @Override
+    public void restart() {
+        reset();
+        resume();
+    }
+
+    @Override
+    public void reset() {
+        stopUpdateTicks();
+        setProgress(0);
+        mCumulativeTime = 0;
+        mCurrentPlayStartTime = 0;
+    }
+
+    @Override
+    public void resume() {
+        mCurrentPlayStartTime = SystemClock.elapsedRealtime();
+        startUpdateTicks();
+    }
+
+    @Override
+    public void pause() {
+        mCumulativeTime += SystemClock.elapsedRealtime() - mCurrentPlayStartTime;
+        stopUpdateTicks();
+    }
+
+    private void startUpdateTicks() {
+        if (!mUpdateAnimator.isStarted()) {
+            mUpdateAnimator.start();
+        }
+    }
+
+    private void stopUpdateTicks() {
+        if (mUpdateAnimator.isStarted()) {
+            mUpdateAnimator.end();
+        }
+    }
+
+    private void updateAppearance() {
+        final Drawable drawable =
+                ConversationDrawables.get().getAudioProgressDrawable(mIncoming);
+        final ClipDrawable clipDrawable = new ClipDrawable(drawable, Gravity.START,
+                ClipDrawable.HORIZONTAL);
+        setProgressDrawable(clipDrawable);
+        setBackground(ConversationDrawables.get()
+                .getAudioProgressBackgroundDrawable(mIncoming));
+    }
+
+    public void setVisualStyle(final boolean incoming) {
+        if (mIncoming != incoming) {
+            mIncoming = incoming;
+            updateAppearance();
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/BaseBugleActivity.java b/src/com/android/messaging/ui/BaseBugleActivity.java
new file mode 100644
index 0000000..1236282
--- /dev/null
+++ b/src/com/android/messaging/ui/BaseBugleActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.messaging.util.BugleActivityUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Base class for app activities that would normally derive from Activity. Responsible for
+ * ensuring app requirements are met during onResume()
+ */
+public class BaseBugleActivity extends Activity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (UiUtils.redirectToPermissionCheckIfNeeded(this)) {
+            return;
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onResume");
+        BugleActivityUtil.onActivityResume(this, BaseBugleActivity.this);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onPause");
+    }
+}
diff --git a/src/com/android/messaging/ui/BaseBugleFragmentActivity.java b/src/com/android/messaging/ui/BaseBugleFragmentActivity.java
new file mode 100644
index 0000000..947970f
--- /dev/null
+++ b/src/com/android/messaging/ui/BaseBugleFragmentActivity.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+
+import com.android.messaging.util.BugleActivityUtil;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Base class for app activities that would normally derive from FragmentActivity. Responsible for
+ * ensuring app requirements are met during onResume()
+ */
+public class BaseBugleFragmentActivity extends Activity {
+    @Override
+    protected void onResume() {
+        super.onResume();
+        LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onResume");
+        // Ensure we have a sufficient version of Google Play Services, prompting for upgrade and
+        // disabling the data updates if we don't have the correct version.
+        BugleActivityUtil.onActivityResume(this, BaseBugleFragmentActivity.this);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onPause");
+    }
+}
diff --git a/src/com/android/messaging/ui/BasePagerViewHolder.java b/src/com/android/messaging/ui/BasePagerViewHolder.java
new file mode 100644
index 0000000..a82ecce
--- /dev/null
+++ b/src/com/android/messaging/ui/BasePagerViewHolder.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.os.Parcelable;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * The base pager view holder implementation that handles basic view creation/destruction logic,
+ * as well as logic to save/restore instance state that's persisted not only for activity
+ * reconstruction (e.g. during a configuration change), but also cases where the individual
+ * page view gets destroyed and recreated.
+ *
+ * To opt into saving/restoring instance state behavior for a particular page view, let the
+ * PageView implement PersistentInstanceState to save and restore instance states to/from a
+ * Parcelable.
+ */
+public abstract class BasePagerViewHolder implements PagerViewHolder {
+    protected View mView;
+    protected Parcelable mSavedState;
+
+    /**
+     * This is called when the entire view pager is being torn down (due to configuration change
+     * for example) that will be restored later.
+     */
+    @Override
+    public Parcelable saveState() {
+        savePendingState();
+        return mSavedState;
+    }
+
+    /**
+     * This is called when the view pager is being restored.
+     */
+    @Override
+    public void restoreState(final Parcelable restoredState) {
+        if (restoredState != null) {
+            mSavedState = restoredState;
+            // If the view is already there, let it restore the state. Otherwise, it will be
+            // restored the next time the view gets created.
+            restorePendingState();
+        }
+    }
+
+    @Override
+    public void resetState() {
+        mSavedState = null;
+        if (mView != null && (mView instanceof PersistentInstanceState)) {
+            ((PersistentInstanceState) mView).resetState();
+        }
+    }
+
+    /**
+     * This is called when the view itself is being torn down. This may happen when the user
+     * has flipped to another page in the view pager, so we want to save the current state if
+     * possible.
+     */
+    @Override
+    public View destroyView() {
+        savePendingState();
+        final View retView = mView;
+        mView = null;
+        return retView;
+    }
+
+    @Override
+    public View getView(ViewGroup container) {
+        if (mView == null) {
+            mView = createView(container);
+            // When initially created, check if the view has any saved state. If so restore it.
+            restorePendingState();
+        }
+        return mView;
+    }
+
+    private void savePendingState() {
+        if (mView != null && (mView instanceof PersistentInstanceState)) {
+            mSavedState = ((PersistentInstanceState) mView).saveState();
+        }
+    }
+
+    private void restorePendingState() {
+        if (mView != null && (mView instanceof PersistentInstanceState) && (mSavedState != null)) {
+            ((PersistentInstanceState) mView).restoreState(mSavedState);
+        }
+    }
+
+    /**
+     * Create and initialize a new page view.
+     */
+    protected abstract View createView(ViewGroup container);
+}
diff --git a/src/com/android/messaging/ui/BlockedParticipantListItemView.java b/src/com/android/messaging/ui/BlockedParticipantListItemView.java
new file mode 100644
index 0000000..9654e70
--- /dev/null
+++ b/src/com/android/messaging/ui/BlockedParticipantListItemView.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantListItemData;
+
+/**
+ * View for individual participant in blocked participants list.
+ *
+ * Unblocks participant when clicked.
+ */
+public class BlockedParticipantListItemView extends LinearLayout {
+    private TextView mNameTextView;
+    private ContactIconView mContactIconView;
+    private ParticipantListItemData mData;
+
+    public BlockedParticipantListItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mNameTextView = (TextView) findViewById(R.id.name);
+        mContactIconView = (ContactIconView) findViewById(R.id.contact_icon);
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                mData.unblock(getContext());
+            }
+        });
+    }
+
+    public void bind(final ParticipantListItemData data) {
+        mData = data;
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+        mNameTextView.setText(bidiFormatter.unicodeWrap(
+                data.getDisplayName(), TextDirectionHeuristicsCompat.LTR));
+        mContactIconView.setImageResourceUri(data.getAvatarUri(), data.getContactId(),
+                    data.getLookupKey(), data.getNormalizedDestination());
+        mNameTextView.setText(data.getDisplayName());
+    }
+}
diff --git a/src/com/android/messaging/ui/BlockedParticipantsActivity.java b/src/com/android/messaging/ui/BlockedParticipantsActivity.java
new file mode 100644
index 0000000..8d79155
--- /dev/null
+++ b/src/com/android/messaging/ui/BlockedParticipantsActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+
+/**
+ * Show a list of currently blocked participants.
+ */
+public class BlockedParticipantsActivity extends BugleActionBarActivity {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.blocked_participants_activity);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                // Treat the home press as back press so that when we go back to
+                // ConversationActivity, it doesn't lose its original intent (conversation id etc.)
+                onBackPressed();
+                return true;
+
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/BlockedParticipantsFragment.java b/src/com/android/messaging/ui/BlockedParticipantsFragment.java
new file mode 100644
index 0000000..14ec9d8
--- /dev/null
+++ b/src/com/android/messaging/ui/BlockedParticipantsFragment.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import androidx.cursoradapter.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.BlockedParticipantsData;
+import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.util.Assert;
+
+/**
+ * Show a list of currently blocked participants.
+ */
+public class BlockedParticipantsFragment extends Fragment
+        implements BlockedParticipantsDataListener {
+    private ListView mListView;
+    private BlockedParticipantListAdapter mAdapter;
+    private final Binding<BlockedParticipantsData> mBinding =
+            BindingBase.createBinding(this);
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view =
+                inflater.inflate(R.layout.blocked_participants_fragment, container, false);
+        mListView = (ListView) view.findViewById(android.R.id.list);
+        mAdapter = new BlockedParticipantListAdapter(getActivity(), null);
+        mListView.setAdapter(mAdapter);
+        mBinding.bind(DataModel.get().createBlockedParticipantsData(getActivity(), this));
+        mBinding.getData().init(getLoaderManager(), mBinding);
+        return view;
+    }
+
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mBinding.unbind();
+    }
+
+    /**
+     * An adapter to display ParticipantListItemView based on ParticipantData.
+     */
+    private class BlockedParticipantListAdapter extends CursorAdapter {
+        public BlockedParticipantListAdapter(final Context context, final Cursor cursor) {
+            super(context, cursor, 0);
+        }
+
+        @Override
+        public View newView(Context context, Cursor cursor, ViewGroup parent) {
+            return LayoutInflater.from(context)
+                    .inflate(R.layout.blocked_participant_list_item_view, parent, false);
+        }
+
+        @Override
+        public void bindView(View view, Context context, Cursor cursor) {
+            Assert.isTrue(view instanceof BlockedParticipantListItemView);
+            ((BlockedParticipantListItemView) view).bind(
+                    mBinding.getData().createParticipantListItemData(cursor));
+        }
+    }
+
+    @Override
+    public void onBlockedParticipantsCursorUpdated(Cursor cursor) {
+        mAdapter.swapCursor(cursor);
+    }
+}
diff --git a/src/com/android/messaging/ui/BugleActionBarActivity.java b/src/com/android/messaging/ui/BugleActionBarActivity.java
new file mode 100644
index 0000000..42d40fe
--- /dev/null
+++ b/src/com/android/messaging/ui/BugleActionBarActivity.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.util.BugleActivityUtil;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Base class for app activities that use an action bar. Responsible for logging/telemetry/other
+ * needs that will be common for all activities.  We can break out the common code if/when we need
+ * a version that doesn't use an actionbar.
+ */
+public class BugleActionBarActivity extends AppCompatActivity implements ImeUtil.ImeStateHost {
+    // Tracks the list of observers opting in for IME state change.
+    private final Set<ImeUtil.ImeStateObserver> mImeStateObservers = new HashSet<>();
+
+    // Tracks the soft keyboard display state
+    private boolean mImeOpen;
+
+    // The ActionMode that represents the modal contextual action bar, using our own implementation
+    // rather than the built in contextual action bar to reduce jank
+    private CustomActionMode mActionMode;
+
+    // The menu for the action bar
+    private Menu mActionBarMenu;
+
+    // Used to determine if a onDisplayHeightChanged was due to the IME opening or rotation of the
+    // device
+    private int mLastScreenHeight;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (UiUtils.redirectToPermissionCheckIfNeeded(this)) {
+            return;
+        }
+
+        mLastScreenHeight = getResources().getDisplayMetrics().heightPixels;
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onCreate");
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onStart");
+        }
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onStop();
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onRestart");
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onResume");
+        }
+        BugleActivityUtil.onActivityResume(this, BugleActionBarActivity.this);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onPause");
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onStop");
+        }
+    }
+
+    private boolean mDestroyed;
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mDestroyed = true;
+    }
+
+    public boolean getIsDestroyed() {
+        return mDestroyed;
+    }
+
+    @Override
+    public void onDisplayHeightChanged(final int heightSpecification) {
+        int screenHeight = getResources().getDisplayMetrics().heightPixels;
+
+        if (screenHeight != mLastScreenHeight) {
+            // Appears to be an orientation change, don't fire ime updates
+            mLastScreenHeight = screenHeight;
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onDisplayHeightChanged " +
+                    " screenHeight: " + screenHeight + " lastScreenHeight: " + mLastScreenHeight +
+                    " Skipped, appears to be orientation change.");
+            return;
+        }
+        final ActionBar actionBar = getSupportActionBar();
+        if (actionBar != null && actionBar.isShowing()) {
+            screenHeight -= actionBar.getHeight();
+        }
+        final int height = View.MeasureSpec.getSize(heightSpecification);
+
+        final boolean imeWasOpen = mImeOpen;
+        mImeOpen = screenHeight - height > 100;
+
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, this.getLocalClassName() + ".onDisplayHeightChanged " +
+                    "imeWasOpen: " + imeWasOpen + " mImeOpen: " + mImeOpen + " screenHeight: " +
+                    screenHeight + " height: " + height);
+        }
+
+        if (imeWasOpen != mImeOpen) {
+            for (final ImeUtil.ImeStateObserver observer : mImeStateObservers) {
+                observer.onImeStateChanged(mImeOpen);
+            }
+        }
+    }
+
+    @Override
+    public void registerImeStateObserver(final ImeUtil.ImeStateObserver observer) {
+        mImeStateObservers.add(observer);
+    }
+
+    @Override
+    public void unregisterImeStateObserver(final ImeUtil.ImeStateObserver observer) {
+        mImeStateObservers.remove(observer);
+    }
+
+    @Override
+    public boolean isImeOpen() {
+        return mImeOpen;
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        mActionBarMenu = menu;
+        if (mActionMode != null &&
+                mActionMode.getCallback().onCreateActionMode(mActionMode, menu)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        mActionBarMenu = menu;
+        if (mActionMode != null &&
+                mActionMode.getCallback().onPrepareActionMode(mActionMode, menu)) {
+            return true;
+        }
+        return super.onPrepareOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem menuItem) {
+        if (mActionMode != null &&
+                mActionMode.getCallback().onActionItemClicked(mActionMode, menuItem)) {
+            return true;
+        }
+
+        switch (menuItem.getItemId()) {
+            case android.R.id.home:
+                if (mActionMode != null) {
+                    dismissActionMode();
+                    return true;
+                }
+        }
+        return super.onOptionsItemSelected(menuItem);
+    }
+
+    @Override
+    public ActionMode startActionMode(final ActionMode.Callback callback) {
+        mActionMode = new CustomActionMode(callback);
+        supportInvalidateOptionsMenu();
+        invalidateActionBar();
+        return mActionMode;
+    }
+
+    public void dismissActionMode() {
+        if (mActionMode != null) {
+            mActionMode.finish();
+            mActionMode = null;
+            invalidateActionBar();
+        }
+    }
+
+    public ActionMode getActionMode() {
+        return mActionMode;
+    }
+
+    protected ActionMode.Callback getActionModeCallback() {
+        if (mActionMode == null) {
+            return null;
+        }
+
+        return mActionMode.getCallback();
+    }
+
+    /**
+     * Receives and handles action bar invalidation request from sub-components of this activity.
+     *
+     * <p>Normally actions have sole control over the action bar, but in order to support seamless
+     * transitions for components such as the full screen media picker, we have to let it take over
+     * the action bar and then restore its state afterwards</p>
+     *
+     * <p>If a fragment does anything that may change the action bar, it should call this method
+     * and then it is this method's responsibility to figure out which component "controls" the
+     * action bar and delegate the updating of the action bar to that component</p>
+     */
+    public final void invalidateActionBar() {
+        if (mActionMode != null) {
+            mActionMode.updateActionBar(getSupportActionBar());
+        } else {
+            updateActionBar(getSupportActionBar());
+        }
+    }
+
+    protected void updateActionBar(final ActionBar actionBar) {
+        actionBar.setHomeAsUpIndicator(null);
+    }
+
+    /**
+     * Custom ActionMode implementation which allows us to just replace the contents of the main
+     * action bar rather than overlay over it
+     */
+    private class CustomActionMode extends ActionMode {
+        private CharSequence mTitle;
+        private CharSequence mSubtitle;
+        private View mCustomView;
+        private final Callback mCallback;
+
+        public CustomActionMode(final Callback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void setTitle(final CharSequence title) {
+            mTitle = title;
+        }
+
+        @Override
+        public void setTitle(final int resId) {
+            mTitle = getResources().getString(resId);
+        }
+
+        @Override
+        public void setSubtitle(final CharSequence subtitle) {
+            mSubtitle = subtitle;
+        }
+
+        @Override
+        public void setSubtitle(final int resId) {
+            mSubtitle = getResources().getString(resId);
+        }
+
+        @Override
+        public void setCustomView(final View view) {
+            mCustomView = view;
+        }
+
+        @Override
+        public void invalidate() {
+            invalidateActionBar();
+        }
+
+        @Override
+        public void finish() {
+            mActionMode = null;
+            mCallback.onDestroyActionMode(this);
+            supportInvalidateOptionsMenu();
+            invalidateActionBar();
+        }
+
+        @Override
+        public Menu getMenu() {
+            return mActionBarMenu;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return mTitle;
+        }
+
+        @Override
+        public CharSequence getSubtitle() {
+            return mSubtitle;
+        }
+
+        @Override
+        public View getCustomView() {
+            return mCustomView;
+        }
+
+        @Override
+        public MenuInflater getMenuInflater() {
+            return BugleActionBarActivity.this.getMenuInflater();
+        }
+
+        public Callback getCallback() {
+            return mCallback;
+        }
+
+        public void updateActionBar(final ActionBar actionBar) {
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP);
+            actionBar.setDisplayShowTitleEnabled(false);
+            actionBar.setDisplayShowCustomEnabled(false);
+            mActionMode.getCallback().onPrepareActionMode(mActionMode, mActionBarMenu);
+            actionBar.setBackgroundDrawable(new ColorDrawable(
+                    getResources().getColor(R.color.contextual_action_bar_background_color)));
+            actionBar.setHomeAsUpIndicator(R.drawable.ic_cancel_small_dark);
+            actionBar.show();
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/BugleAnimationTags.java b/src/com/android/messaging/ui/BugleAnimationTags.java
new file mode 100644
index 0000000..b141f5b
--- /dev/null
+++ b/src/com/android/messaging/ui/BugleAnimationTags.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+
+/**
+ * Defines a list of animation tags used as android:transitionName properties used for L's
+ * hero transitions.
+ */
+public class BugleAnimationTags {
+    /**
+     * The tag for the FAB in the conversation list activity.
+     */
+    public static final String TAG_FABICON = "bugle:fabicon";
+
+    /**
+     * The tag for the content view of a conversation list item view.
+     */
+    public static final String TAG_CLIVCONTENT = "bugle:clivcontent";
+
+    /**
+     * The tag for the action bar.
+     */
+    public static final String TAG_ACTIONBAR = "bugle:actionbar";
+}
diff --git a/src/com/android/messaging/ui/ClassZeroActivity.java b/src/com/android/messaging/ui/ClassZeroActivity.java
new file mode 100644
index 0000000..129ec19
--- /dev/null
+++ b/src/com/android/messaging/ui/ClassZeroActivity.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ContentValues;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Telephony.Sms;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Window;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.action.ReceiveSmsMessageAction;
+import com.android.messaging.util.Assert;
+
+import java.util.ArrayList;
+
+/**
+ * Display a class-zero SMS message to the user. Wait for the user to dismiss
+ * it.
+ */
+public class ClassZeroActivity extends Activity {
+    private static final boolean VERBOSE = false;
+    private static final String TAG = "display_00";
+    private static final int ON_AUTO_SAVE = 1;
+
+    /** Default timer to dismiss the dialog. */
+    private static final long DEFAULT_TIMER = 5 * 60 * 1000;
+
+    /** To remember the exact time when the timer should fire. */
+    private static final String TIMER_FIRE = "timer_fire";
+
+    private ContentValues mMessageValues = null;
+
+    /** Is the message read. */
+    private boolean mRead = false;
+
+    /** The timer to dismiss the dialog automatically. */
+    private long mTimerSet = 0;
+    private AlertDialog mDialog = null;
+
+    private ArrayList<ContentValues> mMessageQueue = null;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(final Message msg) {
+            // Do not handle an invalid message.
+            if (msg.what == ON_AUTO_SAVE) {
+                mRead = false;
+                mDialog.dismiss();
+                saveMessage();
+                processNextMessage();
+            }
+        }
+    };
+
+    private boolean queueMsgFromIntent(final Intent msgIntent) {
+        final ContentValues messageValues =
+                msgIntent.getParcelableExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_VALUES);
+        // that takes the format argument is a hidden API right now.
+        final String message = messageValues.getAsString(Sms.BODY);
+        if (TextUtils.isEmpty(message)) {
+            if (mMessageQueue.size() == 0) {
+                finish();
+            }
+            return false;
+        }
+        mMessageQueue.add(messageValues);
+        return true;
+    }
+
+    private void processNextMessage() {
+        if (mMessageQueue.size() > 0) {
+            mMessageQueue.remove(0);
+        }
+        if (mMessageQueue.size() == 0) {
+            finish();
+        } else {
+            displayZeroMessage(mMessageQueue.get(0));
+        }
+    }
+
+    private void saveMessage() {
+        mMessageValues.put(Sms.Inbox.READ, mRead ? Integer.valueOf(1) : Integer.valueOf(0));
+        final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(mMessageValues);
+        action.start();
+    }
+
+    @Override
+    protected void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+        if (mMessageQueue == null) {
+            mMessageQueue = new ArrayList<ContentValues>();
+        }
+        if (!queueMsgFromIntent(getIntent())) {
+            return;
+        }
+        Assert.isTrue(mMessageQueue.size() == 1);
+        if (mMessageQueue.size() == 1) {
+            displayZeroMessage(mMessageQueue.get(0));
+        }
+
+        if (icicle != null) {
+            mTimerSet = icicle.getLong(TIMER_FIRE, mTimerSet);
+        }
+    }
+
+    private void displayZeroMessage(final ContentValues messageValues) {
+        /* This'll be used by the save action */
+        mMessageValues = messageValues;
+        final String message = messageValues.getAsString(Sms.BODY);;
+
+        mDialog = new AlertDialog.Builder(this).setMessage(message)
+            .setPositiveButton(R.string.save, mSaveListener)
+            .setNegativeButton(android.R.string.cancel, mCancelListener)
+            .setTitle(R.string.class_0_message_activity)
+            .setCancelable(false).show();
+        final long now = SystemClock.uptimeMillis();
+        mTimerSet = now + DEFAULT_TIMER;
+    }
+
+    @Override
+    protected void onNewIntent(final Intent msgIntent) {
+        // Running with another visible message, queue this one
+        queueMsgFromIntent(msgIntent);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        final long now = SystemClock.uptimeMillis();
+        if (mTimerSet <= now) {
+            // Save the message if the timer already expired.
+            mHandler.sendEmptyMessage(ON_AUTO_SAVE);
+        } else {
+            mHandler.sendEmptyMessageAtTime(ON_AUTO_SAVE, mTimerSet);
+            if (VERBOSE) {
+                Log.d(TAG, "onRestart time = " + Long.toString(mTimerSet) + " "
+                        + this.toString());
+            }
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(final Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putLong(TIMER_FIRE, mTimerSet);
+        if (VERBOSE) {
+            Log.d(TAG, "onSaveInstanceState time = " + Long.toString(mTimerSet)
+                    + " " + this.toString());
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mHandler.removeMessages(ON_AUTO_SAVE);
+        if (VERBOSE) {
+            Log.d(TAG, "onStop time = " + Long.toString(mTimerSet)
+                    + " " + this.toString());
+        }
+    }
+
+    private final OnClickListener mCancelListener = new OnClickListener() {
+        @Override
+        public void onClick(final DialogInterface dialog, final int whichButton) {
+            dialog.dismiss();
+            processNextMessage();
+        }
+    };
+
+    private final OnClickListener mSaveListener = new OnClickListener() {
+        @Override
+        public void onClick(final DialogInterface dialog, final int whichButton) {
+            mRead = true;
+            saveMessage();
+            dialog.dismiss();
+            processNextMessage();
+        }
+    };
+}
diff --git a/src/com/android/messaging/ui/CompositeAdapter.java b/src/com/android/messaging/ui/CompositeAdapter.java
new file mode 100644
index 0000000..620e511
--- /dev/null
+++ b/src/com/android/messaging/ui/CompositeAdapter.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+/**
+ * A general purpose adapter that composes one or more other adapters.  It
+ * appends them in the order they are added.
+ */
+public class CompositeAdapter extends BaseAdapter {
+
+    private static final int INITIAL_CAPACITY = 2;
+
+    public static class Partition {
+        boolean mShowIfEmpty;
+        boolean mHasHeader;
+        BaseAdapter mAdapter;
+
+        public Partition(final boolean showIfEmpty, final boolean hasHeader,
+                final BaseAdapter adapter) {
+            this.mShowIfEmpty = showIfEmpty;
+            this.mHasHeader = hasHeader;
+            this.mAdapter = adapter;
+        }
+
+        /**
+         * True if the directory should be shown even if no contacts are found.
+         */
+        public boolean showIfEmpty() {
+            return mShowIfEmpty;
+        }
+
+        public boolean hasHeader() {
+            return mHasHeader;
+        }
+
+        public int getCount() {
+            int count = mAdapter.getCount();
+            if (mHasHeader && (count != 0 || mShowIfEmpty)) {
+                count++;
+            }
+            return count;
+        }
+
+        public BaseAdapter getAdapter() {
+            return mAdapter;
+        }
+
+        public View getHeaderView(final View convertView, final ViewGroup parentView) {
+            return null;
+        }
+
+        public void close() {
+            // do nothing in base class.
+        }
+    }
+
+    private class Observer extends DataSetObserver {
+        @Override
+        public void onChanged() {
+            CompositeAdapter.this.notifyDataSetChanged();
+        }
+
+        @Override
+        public void onInvalidated() {
+            CompositeAdapter.this.notifyDataSetInvalidated();
+        }
+    };
+
+    protected final Context mContext;
+    private Partition[] mPartitions;
+    private int mSize = 0;
+    private int mCount = 0;
+    private boolean mCacheValid = true;
+    private final Observer mObserver;
+
+    public CompositeAdapter(final Context context) {
+        mContext = context;
+        mObserver = new Observer();
+        mPartitions = new Partition[INITIAL_CAPACITY];
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    public void addPartition(final Partition partition) {
+        if (mSize >= mPartitions.length) {
+            final int newCapacity = mSize + 2;
+            final Partition[] newAdapters = new Partition[newCapacity];
+            System.arraycopy(mPartitions, 0, newAdapters, 0, mSize);
+            mPartitions = newAdapters;
+        }
+        mPartitions[mSize++] = partition;
+        partition.getAdapter().registerDataSetObserver(mObserver);
+        invalidate();
+        notifyDataSetChanged();
+    }
+
+    public void removePartition(final int index) {
+        final Partition partition = mPartitions[index];
+        partition.close();
+        System.arraycopy(mPartitions, index + 1, mPartitions, index,
+                mSize - index - 1);
+        mSize--;
+        partition.getAdapter().unregisterDataSetObserver(mObserver);
+        invalidate();
+        notifyDataSetChanged();
+    }
+
+    public void clearPartitions() {
+        for (int i = 0; i < mSize; i++) {
+            final Partition partition = mPartitions[i];
+            partition.close();
+            partition.getAdapter().unregisterDataSetObserver(mObserver);
+        }
+        invalidate();
+        notifyDataSetChanged();
+    }
+
+    public Partition getPartition(final int index) {
+        return mPartitions[index];
+    }
+
+    public int getPartitionAtPosition(final int position) {
+        ensureCacheValid();
+        int start = 0;
+        for (int i = 0; i < mSize; i++) {
+            final int end = start + mPartitions[i].getCount();
+            if (position >= start && position < end) {
+                int offset = position - start;
+                if (mPartitions[i].hasHeader() &&
+                        (mPartitions[i].getCount() > 0 || mPartitions[i].showIfEmpty())) {
+                    offset--;
+                }
+                if (offset == -1) {
+                    return -1;
+                }
+                return i;
+            }
+            start = end;
+        }
+        return mSize - 1;
+    }
+
+    public int getPartitionCount() {
+        return mSize;
+    }
+
+    public void invalidate() {
+        mCacheValid = false;
+    }
+
+    private void ensureCacheValid() {
+        if (mCacheValid) {
+            return;
+        }
+        mCount = 0;
+        for (int i = 0; i < mSize; i++) {
+            mCount += mPartitions[i].getCount();
+        }
+    }
+
+    @Override
+    public int getCount() {
+        ensureCacheValid();
+        return mCount;
+    }
+
+    public int getCount(final int index) {
+        ensureCacheValid();
+        return mPartitions[index].getCount();
+    }
+
+    @Override
+    public Object getItem(final int position) {
+        ensureCacheValid();
+        int start = 0;
+        for (int i = 0; i < mSize; i++) {
+            final int end = start + mPartitions[i].getCount();
+            if (position >= start && position < end) {
+                final int offset = position - start;
+                final Partition partition = mPartitions[i];
+                if (partition.hasHeader() && offset == 0 &&
+                        (partition.getCount() > 0 || partition.showIfEmpty())) {
+                    // This is the header
+                    return null;
+                }
+                return mPartitions[i].getAdapter().getItem(offset);
+            }
+            start = end;
+        }
+
+        return null;
+    }
+
+    @Override
+    public long getItemId(final int position) {
+        ensureCacheValid();
+        int start = 0;
+        for (int i = 0; i < mSize; i++) {
+            final int end = start + mPartitions[i].getCount();
+            if (position >= start && position < end) {
+                final int offset = position - start;
+                final Partition partition = mPartitions[i];
+                if (partition.hasHeader() && offset == 0 &&
+                        (partition.getCount() > 0 || partition.showIfEmpty())) {
+                    // Header
+                    return 0;
+                }
+                return mPartitions[i].getAdapter().getItemId(offset);
+            }
+            start = end;
+        }
+
+        return 0;
+    }
+
+    @Override
+    public boolean isEnabled(int position) {
+        ensureCacheValid();
+        int start = 0;
+        for (int i = 0; i < mSize; i++) {
+            final int end = start + mPartitions[i].getCount();
+            if (position >= start && position < end) {
+                final int offset = position - start;
+                final Partition partition = mPartitions[i];
+                if (partition.hasHeader() && offset == 0 &&
+                        (partition.getCount() > 0 || partition.showIfEmpty())) {
+                    // This is the header
+                    return false;
+                }
+                return true;
+            }
+            start = end;
+        }
+        return true;
+    }
+
+    @Override
+    public View getView(final int position, final View convertView, final ViewGroup parentView) {
+        ensureCacheValid();
+        int start = 0;
+        for (int i = 0; i < mSize; i++) {
+            final Partition partition = mPartitions[i];
+            final int end = start + partition.getCount();
+            if (position >= start && position < end) {
+                int offset = position - start;
+                View view;
+                if (partition.hasHeader() &&
+                        (partition.getCount() > 0 || partition.showIfEmpty())) {
+                    offset = offset - 1;
+                }
+                if (offset == -1) {
+                    view = partition.getHeaderView(convertView, parentView);
+                } else {
+                    view = partition.getAdapter().getView(offset, convertView, parentView);
+                }
+                if (view == null) {
+                    throw new NullPointerException("View should not be null, partition: " + i
+                            + " position: " + offset);
+                }
+                return view;
+            }
+            start = end;
+        }
+
+        throw new ArrayIndexOutOfBoundsException(position);
+    }
+}
diff --git a/src/com/android/messaging/ui/ContactIconView.java b/src/com/android/messaging/ui/ContactIconView.java
new file mode 100644
index 0000000..44983ab
--- /dev/null
+++ b/src/com/android/messaging/ui/ContactIconView.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.media.AvatarGroupRequestDescriptor;
+import com.android.messaging.datamodel.media.AvatarRequestDescriptor;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ContactUtil;
+
+/**
+ * A view used to render contact icons. This class derives from AsyncImageView, so it loads contact
+ * icons from MediaResourceManager, and it handles more rendering logic than an AsyncImageView
+ * (draws a circular bitmap).
+ */
+public class ContactIconView extends AsyncImageView {
+    private static final int NORMAL_ICON_SIZE_ID = 0;
+    private static final int LARGE_ICON_SIZE_ID = 1;
+    private static final int SMALL_ICON_SIZE_ID = 2;
+
+    protected final int mIconSize;
+    private final int mColorPressedId;
+
+    private long mContactId;
+    private String mContactLookupKey;
+    private String mNormalizedDestination;
+    private Uri mAvatarUri;
+    private boolean mDisableClickHandler;
+
+    public ContactIconView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+
+        final Resources resources = context.getResources();
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ContactIconView);
+
+        final int iconSizeId = a.getInt(R.styleable.ContactIconView_iconSize, 0);
+        switch (iconSizeId) {
+            case NORMAL_ICON_SIZE_ID:
+                mIconSize = (int) resources.getDimension(
+                        R.dimen.contact_icon_view_normal_size);
+                break;
+            case LARGE_ICON_SIZE_ID:
+                mIconSize = (int) resources.getDimension(
+                        R.dimen.contact_icon_view_large_size);
+                break;
+            case SMALL_ICON_SIZE_ID:
+                mIconSize = (int) resources.getDimension(
+                        R.dimen.contact_icon_view_small_size);
+                break;
+            default:
+                // For the compiler, something has to be set even with the assert.
+                mIconSize = 0;
+                Assert.fail("Unsupported ContactIconView icon size attribute");
+        }
+        mColorPressedId = resources.getColor(R.color.contact_avatar_pressed_color);
+
+        setImage(null);
+        a.recycle();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            setColorFilter(mColorPressedId);
+        } else {
+            clearColorFilter();
+        }
+        return super.onTouchEvent(event);
+    }
+
+    /**
+     * Method which allows the automatic hookup of a click handler when the Uri is changed
+     */
+    public void setImageClickHandlerDisabled(final boolean isHandlerDisabled) {
+        mDisableClickHandler = isHandlerDisabled;
+        setOnClickListener(null);
+        setClickable(false);
+    }
+
+    /**
+     * A convenience method that sets the URI of the contact icon by creating a new image request.
+     */
+    public void setImageResourceUri(final Uri uri) {
+        setImageResourceUri(uri, 0, null, null);
+    }
+
+    public void setImageResourceUri(final Uri uri, final long contactId,
+            final String contactLookupKey, final String normalizedDestination) {
+        if (uri == null) {
+            setImageResourceId(null);
+        } else {
+            final String avatarType = AvatarUriUtil.getAvatarType(uri);
+            if (AvatarUriUtil.TYPE_GROUP_URI.equals(avatarType)) {
+                setImageResourceId(new AvatarGroupRequestDescriptor(uri, mIconSize, mIconSize));
+            } else {
+                setImageResourceId(new AvatarRequestDescriptor(uri, mIconSize, mIconSize));
+            }
+        }
+
+        mContactId = contactId;
+        mContactLookupKey = contactLookupKey;
+        mNormalizedDestination = normalizedDestination;
+        mAvatarUri = uri;
+
+        maybeInitializeOnClickListener();
+    }
+
+    protected void maybeInitializeOnClickListener() {
+        if ((mContactId > ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED
+                && !TextUtils.isEmpty(mContactLookupKey)) ||
+                !TextUtils.isEmpty(mNormalizedDestination)) {
+            if (!mDisableClickHandler) {
+                setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(final View view) {
+                        ContactUtil.showOrAddContact(view, mContactId, mContactLookupKey,
+                                mAvatarUri, mNormalizedDestination);
+                    }
+                });
+            }
+        } else {
+            // This should happen when the phone number is not in the user's contacts or it is a
+            // group conversation, group conversations don't have contact phone numbers. If this
+            // is the case then absorb the click to prevent propagation.
+            setOnClickListener(null);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/ConversationDrawables.java b/src/com/android/messaging/ui/ConversationDrawables.java
new file mode 100644
index 0000000..cf858e2
--- /dev/null
+++ b/src/com/android/messaging/ui/ConversationDrawables.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.util.ImageUtils;
+
+/**
+ * A singleton cache that holds tinted drawable resources for displaying messages, such as
+ * message bubbles, audio attachments etc.
+ */
+public class ConversationDrawables {
+    private static ConversationDrawables sInstance;
+
+    // Cache the color filtered bubble drawables so that we don't need to create a
+    // new one for each ConversationMessageView.
+    private Drawable mIncomingBubbleDrawable;
+    private Drawable mOutgoingBubbleDrawable;
+    private Drawable mIncomingErrorBubbleDrawable;
+    private Drawable mIncomingBubbleNoArrowDrawable;
+    private Drawable mOutgoingBubbleNoArrowDrawable;
+    private Drawable mAudioPlayButtonDrawable;
+    private Drawable mAudioPauseButtonDrawable;
+    private Drawable mIncomingAudioProgressBackgroundDrawable;
+    private Drawable mOutgoingAudioProgressBackgroundDrawable;
+    private Drawable mAudioProgressForegroundDrawable;
+    private Drawable mFastScrollThumbDrawable;
+    private Drawable mFastScrollThumbPressedDrawable;
+    private Drawable mFastScrollPreviewDrawableLeft;
+    private Drawable mFastScrollPreviewDrawableRight;
+    private final Context mContext;
+    private int mOutgoingBubbleColor;
+    private int mIncomingErrorBubbleColor;
+    private int mIncomingAudioButtonColor;
+    private int mSelectedBubbleColor;
+    private int mThemeColor;
+
+    public static ConversationDrawables get() {
+        if (sInstance == null) {
+            sInstance = new ConversationDrawables(Factory.get().getApplicationContext());
+        }
+        return sInstance;
+    }
+
+    private ConversationDrawables(final Context context) {
+        mContext = context;
+        // Pre-create all the drawables.
+        updateDrawables();
+    }
+
+    public int getConversationThemeColor() {
+        return mThemeColor;
+    }
+
+    public void updateDrawables() {
+        final Resources resources = mContext.getResources();
+
+        mIncomingBubbleDrawable = resources.getDrawable(R.drawable.msg_bubble_incoming);
+        mIncomingBubbleNoArrowDrawable =
+                resources.getDrawable(R.drawable.message_bubble_incoming_no_arrow);
+        mIncomingErrorBubbleDrawable = resources.getDrawable(R.drawable.msg_bubble_error);
+        mOutgoingBubbleDrawable =  resources.getDrawable(R.drawable.msg_bubble_outgoing);
+        mOutgoingBubbleNoArrowDrawable =
+                resources.getDrawable(R.drawable.message_bubble_outgoing_no_arrow);
+        mAudioPlayButtonDrawable = resources.getDrawable(R.drawable.ic_audio_play);
+        mAudioPauseButtonDrawable = resources.getDrawable(R.drawable.ic_audio_pause);
+        mIncomingAudioProgressBackgroundDrawable =
+                resources.getDrawable(R.drawable.audio_progress_bar_background_incoming);
+        mOutgoingAudioProgressBackgroundDrawable =
+                resources.getDrawable(R.drawable.audio_progress_bar_background_outgoing);
+        mAudioProgressForegroundDrawable =
+                resources.getDrawable(R.drawable.audio_progress_bar_progress);
+        mFastScrollThumbDrawable = resources.getDrawable(R.drawable.fastscroll_thumb);
+        mFastScrollThumbPressedDrawable =
+                resources.getDrawable(R.drawable.fastscroll_thumb_pressed);
+        mFastScrollPreviewDrawableLeft =
+                resources.getDrawable(R.drawable.fastscroll_preview_left);
+        mFastScrollPreviewDrawableRight =
+                resources.getDrawable(R.drawable.fastscroll_preview_right);
+        mOutgoingBubbleColor = resources.getColor(R.color.message_bubble_color_outgoing);
+        mIncomingErrorBubbleColor =
+                resources.getColor(R.color.message_error_bubble_color_incoming);
+        mIncomingAudioButtonColor =
+                resources.getColor(R.color.message_audio_button_color_incoming);
+        mSelectedBubbleColor = resources.getColor(R.color.message_bubble_color_selected);
+        mThemeColor = resources.getColor(R.color.primary_color);
+    }
+
+    public Drawable getBubbleDrawable(final boolean selected, final boolean incoming,
+            final boolean needArrow, final boolean isError) {
+        final Drawable protoDrawable;
+        if (needArrow) {
+            if (incoming) {
+                protoDrawable = isError && !selected ?
+                        mIncomingErrorBubbleDrawable : mIncomingBubbleDrawable;
+            } else {
+                protoDrawable = mOutgoingBubbleDrawable;
+            }
+        } else if (incoming) {
+            protoDrawable = mIncomingBubbleNoArrowDrawable;
+        } else {
+            protoDrawable = mOutgoingBubbleNoArrowDrawable;
+        }
+
+        int color;
+        if (selected) {
+            color = mSelectedBubbleColor;
+        } else if (incoming) {
+            if (isError) {
+                color = mIncomingErrorBubbleColor;
+            } else {
+                color = mThemeColor;
+            }
+        } else {
+            color = mOutgoingBubbleColor;
+        }
+
+        return ImageUtils.getTintedDrawable(mContext, protoDrawable, color);
+    }
+
+    private int getAudioButtonColor(final boolean incoming) {
+        return incoming ? mIncomingAudioButtonColor : mThemeColor;
+    }
+
+    public Drawable getPlayButtonDrawable(final boolean incoming) {
+        return ImageUtils.getTintedDrawable(
+                mContext, mAudioPlayButtonDrawable, getAudioButtonColor(incoming));
+    }
+
+    public Drawable getPauseButtonDrawable(final boolean incoming) {
+        return ImageUtils.getTintedDrawable(
+                mContext, mAudioPauseButtonDrawable, getAudioButtonColor(incoming));
+    }
+
+    public Drawable getAudioProgressDrawable(final boolean incoming) {
+        return ImageUtils.getTintedDrawable(
+                mContext, mAudioProgressForegroundDrawable, getAudioButtonColor(incoming));
+    }
+
+    public Drawable getAudioProgressBackgroundDrawable(final boolean incoming) {
+        return incoming ? mIncomingAudioProgressBackgroundDrawable :
+            mOutgoingAudioProgressBackgroundDrawable;
+    }
+
+    public Drawable getFastScrollThumbDrawable(final boolean pressed) {
+        if (pressed) {
+            return ImageUtils.getTintedDrawable(mContext, mFastScrollThumbPressedDrawable,
+                    mThemeColor);
+        } else {
+            return mFastScrollThumbDrawable;
+        }
+    }
+
+    public Drawable getFastScrollPreviewDrawable(boolean positionRight) {
+        Drawable protoDrawable = positionRight ? mFastScrollPreviewDrawableRight :
+            mFastScrollPreviewDrawableLeft;
+        return ImageUtils.getTintedDrawable(mContext, protoDrawable, mThemeColor);
+    }
+}
diff --git a/src/com/android/messaging/ui/CursorRecyclerAdapter.java b/src/com/android/messaging/ui/CursorRecyclerAdapter.java
new file mode 100644
index 0000000..750223a
--- /dev/null
+++ b/src/com/android/messaging/ui/CursorRecyclerAdapter.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.os.Handler;
+import androidx.recyclerview.widget.RecyclerView;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.FilterQueryProvider;
+
+/**
+ * Copy of CursorAdapter suited for RecyclerView.
+ *
+ * TODO: BUG 16327984. Replace this with a framework supported CursorAdapter for
+ * RecyclerView when one is available.
+ */
+public abstract class CursorRecyclerAdapter<VH extends RecyclerView.ViewHolder>
+        extends RecyclerView.Adapter<VH> {
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected boolean mDataValid;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected boolean mAutoRequery;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected Cursor mCursor;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected Context mContext;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected int mRowIDColumn;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected ChangeObserver mChangeObserver;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected DataSetObserver mDataSetObserver;
+    /**
+     * This field should be made private, so it is hidden from the SDK.
+     * {@hide}
+     */
+    protected FilterQueryProvider mFilterQueryProvider;
+
+    /**
+     * If set the adapter will call requery() on the cursor whenever a content change
+     * notification is delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER}.
+     *
+     * @deprecated This option is discouraged, as it results in Cursor queries
+     * being performed on the application's UI thread and thus can cause poor
+     * responsiveness or even Application Not Responding errors.  As an alternative,
+     * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
+     */
+    @Deprecated
+    public static final int FLAG_AUTO_REQUERY = 0x01;
+
+    /**
+     * If set the adapter will register a content observer on the cursor and will call
+     * {@link #onContentChanged()} when a notification comes in.  Be careful when
+     * using this flag: you will need to unset the current Cursor from the adapter
+     * to avoid leaks due to its registered observers.  This flag is not needed
+     * when using a CursorAdapter with a
+     * {@link android.content.CursorLoader}.
+     */
+    public static final int FLAG_REGISTER_CONTENT_OBSERVER = 0x02;
+
+    /**
+     * Recommended constructor.
+     *
+     * @param c The cursor from which to get the data.
+     * @param context The context
+     * @param flags Flags used to determine the behavior of the adapter; may
+     * be any combination of {@link #FLAG_AUTO_REQUERY} and
+     * {@link #FLAG_REGISTER_CONTENT_OBSERVER}.
+     */
+    public CursorRecyclerAdapter(final Context context, final Cursor c, final int flags) {
+        init(context, c, flags);
+    }
+
+    void init(final Context context, final Cursor c, int flags) {
+        if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) {
+            flags |= FLAG_REGISTER_CONTENT_OBSERVER;
+            mAutoRequery = true;
+        } else {
+            mAutoRequery = false;
+        }
+        final boolean cursorPresent = c != null;
+        mCursor = c;
+        mDataValid = cursorPresent;
+        mContext = context;
+        mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
+        if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {
+            mChangeObserver = new ChangeObserver();
+            mDataSetObserver = new MyDataSetObserver();
+        } else {
+            mChangeObserver = null;
+            mDataSetObserver = null;
+        }
+
+        if (cursorPresent) {
+            if (mChangeObserver != null) {
+                c.registerContentObserver(mChangeObserver);
+            }
+            if (mDataSetObserver != null) {
+                c.registerDataSetObserver(mDataSetObserver);
+            }
+        }
+    }
+
+    /**
+     * Returns the cursor.
+     * @return the cursor.
+     */
+    public Cursor getCursor() {
+        return mCursor;
+    }
+
+    @Override
+    public int getItemCount() {
+        if (mDataValid && mCursor != null) {
+            return mCursor.getCount();
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * @see androidx.recyclerview.widget.RecyclerView.Adapter#getItem(int)
+     */
+    public Object getItem(final int position) {
+        if (mDataValid && mCursor != null) {
+            mCursor.moveToPosition(position);
+            return mCursor;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see androidx.recyclerview.widget.RecyclerView.Adapter#getItemId(int)
+     */
+    @Override
+    public long getItemId(final int position) {
+        if (mDataValid && mCursor != null) {
+            if (mCursor.moveToPosition(position)) {
+                return mCursor.getLong(mRowIDColumn);
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public VH onCreateViewHolder(final ViewGroup parent, final int viewType) {
+        return createViewHolder(mContext, parent, viewType);
+    }
+
+    @Override
+    public void onBindViewHolder(final VH holder, final int position) {
+        if (!mDataValid) {
+            throw new IllegalStateException("this should only be called when the cursor is valid");
+        }
+        if (!mCursor.moveToPosition(position)) {
+            throw new IllegalStateException("couldn't move cursor to position " + position);
+        }
+        bindViewHolder(holder, mContext, mCursor);
+    }
+    /**
+     * Bind an existing view to the data pointed to by cursor
+     * @param view Existing view, returned earlier by newView
+     * @param context Interface to application's global information
+     * @param cursor The cursor from which to get the data. The cursor is already
+     * moved to the correct position.
+     */
+    public abstract void bindViewHolder(VH holder, Context context, Cursor cursor);
+
+    /**
+     * @see androidx.recyclerview.widget.RecyclerView.Adapter#createViewHolder(Context, ViewGroup, int)
+     */
+    public abstract VH createViewHolder(Context context, ViewGroup parent, int viewType);
+
+    /**
+     * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
+     * closed.
+     *
+     * @param cursor The new cursor to be used
+     */
+    public void changeCursor(final Cursor cursor) {
+        final Cursor old = swapCursor(cursor);
+        if (old != null) {
+            old.close();
+        }
+    }
+
+    /**
+     * Swap in a new Cursor, returning the old Cursor.  Unlike
+     * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
+     * closed.
+     *
+     * @param newCursor The new cursor to be used.
+     * @return Returns the previously set Cursor, or null if there wasa not one.
+     * If the given new Cursor is the same instance is the previously set
+     * Cursor, null is also returned.
+     */
+    public Cursor swapCursor(final Cursor newCursor) {
+        if (newCursor == mCursor) {
+            return null;
+        }
+        final Cursor oldCursor = mCursor;
+        if (oldCursor != null) {
+            if (mChangeObserver != null) {
+                oldCursor.unregisterContentObserver(mChangeObserver);
+            }
+            if (mDataSetObserver != null) {
+                oldCursor.unregisterDataSetObserver(mDataSetObserver);
+            }
+        }
+        mCursor = newCursor;
+        if (newCursor != null) {
+            if (mChangeObserver != null) {
+                newCursor.registerContentObserver(mChangeObserver);
+            }
+            if (mDataSetObserver != null) {
+                newCursor.registerDataSetObserver(mDataSetObserver);
+            }
+            mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
+            mDataValid = true;
+            // notify the observers about the new cursor
+            notifyDataSetChanged();
+        } else {
+            mRowIDColumn = -1;
+            mDataValid = false;
+            // notify the observers about the lack of a data set
+            notifyDataSetChanged();
+        }
+        return oldCursor;
+    }
+
+    /**
+     * <p>Converts the cursor into a CharSequence. Subclasses should override this
+     * method to convert their results. The default implementation returns an
+     * empty String for null values or the default String representation of
+     * the value.</p>
+     *
+     * @param cursor the cursor to convert to a CharSequence
+     * @return a CharSequence representing the value
+     */
+    public CharSequence convertToString(final Cursor cursor) {
+        return cursor == null ? "" : cursor.toString();
+    }
+
+    /**
+     * Called when the {@link ContentObserver} on the cursor receives a change notification.
+     * The default implementation provides the auto-requery logic, but may be overridden by
+     * sub classes.
+     *
+     * @see ContentObserver#onChange(boolean)
+     */
+    protected void onContentChanged() {
+        if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
+            if (false) {
+                Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
+            }
+            mDataValid = mCursor.requery();
+        }
+    }
+
+    private class ChangeObserver extends ContentObserver {
+        public ChangeObserver() {
+            super(new Handler());
+        }
+
+        @Override
+        public boolean deliverSelfNotifications() {
+            return true;
+        }
+
+        @Override
+        public void onChange(final boolean selfChange) {
+            onContentChanged();
+        }
+    }
+
+    private class MyDataSetObserver extends DataSetObserver {
+        @Override
+        public void onChanged() {
+            mDataValid = true;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public void onInvalidated() {
+            mDataValid = false;
+            notifyDataSetChanged();
+        }
+    }
+
+}
diff --git a/src/com/android/messaging/ui/CustomHeaderPagerListViewHolder.java b/src/com/android/messaging/ui/CustomHeaderPagerListViewHolder.java
new file mode 100644
index 0000000..1268c53
--- /dev/null
+++ b/src/com/android/messaging/ui/CustomHeaderPagerListViewHolder.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+
+import com.android.messaging.util.ImeUtil;
+
+/**
+ * Produces and holds a list view and its tab header to be displayed in a ViewPager.
+ */
+public abstract class CustomHeaderPagerListViewHolder extends BasePagerViewHolder
+        implements CustomHeaderPagerViewHolder {
+    private final Context mContext;
+    private final CursorAdapter mListAdapter;
+    private boolean mListCursorInitialized;
+    private ListView mListView;
+
+    public CustomHeaderPagerListViewHolder(final Context context,
+            final CursorAdapter adapter) {
+        mContext = context;
+        mListAdapter = adapter;
+    }
+
+    @Override
+    protected View createView(ViewGroup container) {
+        final LayoutInflater inflater = (LayoutInflater)
+                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View view = inflater.inflate(
+                getLayoutResId(),
+                null /* root */,
+                false /* attachToRoot */);
+        final ListView listView = (ListView) view.findViewById(getListViewResId());
+        listView.setAdapter(mListAdapter);
+        listView.setOnScrollListener(new OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(final AbsListView view, final int scrollState) {
+                if (scrollState != SCROLL_STATE_IDLE) {
+                    ImeUtil.get().hideImeKeyboard(mContext, view);
+                }
+            }
+
+            @Override
+            public void onScroll(final AbsListView view, final int firstVisibleItem,
+                    final int visibleItemCount, final int totalItemCount) {
+            }
+        });
+        mListView = listView;
+        maybeSetEmptyView();
+        return view;
+    }
+
+    public void onContactsCursorUpdated(final Cursor data) {
+        mListAdapter.swapCursor(data);
+        if (!mListCursorInitialized) {
+            // We set the emptyView here instead of in create so that the initial load won't show
+            // the empty UI - the system handles this and doesn't do what we would like.
+            mListCursorInitialized = true;
+            maybeSetEmptyView();
+        }
+    }
+
+    /**
+     *  We don't want to show the empty view hint until BOTH conditions are met:
+     *  1. The view has been created.
+     *  2. Cursor data has been loaded once.
+     *  Due to timing when data is loaded, the view may not be ready (and vice versa). So we
+     *  are calling this method from both onContactsCursorUpdated & createView.
+     */
+    private void maybeSetEmptyView() {
+        if (mView != null && mListCursorInitialized) {
+            final ListEmptyView emptyView = (ListEmptyView) mView.findViewById(getEmptyViewResId());
+            if (emptyView != null) {
+                emptyView.setTextHint(getEmptyViewTitleResId());
+                emptyView.setImageHint(getEmptyViewImageResId());
+                final ListView listView = (ListView) mView.findViewById(getListViewResId());
+                listView.setEmptyView(emptyView);
+            }
+        }
+    }
+
+    public void invalidateList() {
+        mListAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * In order for scene transition to work, we toggle the visibility for each individual list
+     * view items so that they can be properly tracked by the scene transition manager.
+     * @param show whether the pending transition is to show or hide the list.
+     */
+    public void toggleVisibilityForPendingTransition(final boolean show, final View epicenterView) {
+        if (mListView == null) {
+            return;
+        }
+        final int childCount = mListView.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View childView = mListView.getChildAt(i);
+            if (childView != epicenterView) {
+                childView.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
+            }
+        }
+    }
+
+    @Override
+    public CharSequence getPageTitle(Context context) {
+        return context.getString(getPageTitleResId());
+    }
+
+    protected abstract int getLayoutResId();
+    protected abstract int getPageTitleResId();
+    protected abstract int getEmptyViewResId();
+    protected abstract int getEmptyViewTitleResId();
+    protected abstract int getEmptyViewImageResId();
+    protected abstract int getListViewResId();
+}
diff --git a/src/com/android/messaging/ui/CustomHeaderPagerViewHolder.java b/src/com/android/messaging/ui/CustomHeaderPagerViewHolder.java
new file mode 100644
index 0000000..43802cd
--- /dev/null
+++ b/src/com/android/messaging/ui/CustomHeaderPagerViewHolder.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+
+/**
+ * An extension on the standard PagerViewHolder to return a custom header view to be used by
+ * CustomHeaderViewPager
+ */
+public interface CustomHeaderPagerViewHolder extends PagerViewHolder {
+    CharSequence getPageTitle(Context context);
+}
diff --git a/src/com/android/messaging/ui/CustomHeaderViewPager.java b/src/com/android/messaging/ui/CustomHeaderViewPager.java
new file mode 100644
index 0000000..31505c8
--- /dev/null
+++ b/src/com/android/messaging/ui/CustomHeaderViewPager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+
+/**
+ * A view that contains both a view pager and a tab strip wrapped in a linear layout.
+ */
+public class CustomHeaderViewPager extends LinearLayout {
+    public final static int DEFAULT_TAB_STRIP_SIZE = -1;
+    private final int mDefaultTabStripSize;
+    private ViewPager mViewPager;
+    private ViewPagerTabs mTabstrip;
+
+    public CustomHeaderViewPager(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        inflater.inflate(R.layout.custom_header_view_pager, this, true);
+        setOrientation(LinearLayout.VERTICAL);
+
+        mTabstrip = (ViewPagerTabs) findViewById(R.id.tab_strip);
+        mViewPager = (ViewPager) findViewById(R.id.pager);
+
+        TypedValue tv = new TypedValue();
+        context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
+        mDefaultTabStripSize = context.getResources().getDimensionPixelSize(tv.resourceId);
+    }
+
+    public void setCurrentItem(final int position) {
+        mViewPager.setCurrentItem(position);
+    }
+
+    public void setViewPagerTabHeight(final int tabHeight) {
+        mTabstrip.getLayoutParams().height = tabHeight == DEFAULT_TAB_STRIP_SIZE ?
+                mDefaultTabStripSize : tabHeight;
+    }
+
+    public void setViewHolders(final CustomHeaderPagerViewHolder[] viewHolders) {
+        Assert.notNull(mViewPager);
+        final PagerAdapter adapter = new CustomHeaderViewPagerAdapter(viewHolders);
+        mViewPager.setAdapter(adapter);
+        mTabstrip.setViewPager(mViewPager);
+        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
+
+            @Override
+            public void onPageScrollStateChanged(int state) {
+                mTabstrip.onPageScrollStateChanged(state);
+            }
+
+            @Override
+            public void onPageScrolled(int position, float positionOffset,
+                    int positionOffsetPixels) {
+                mTabstrip.onPageScrolled(position, positionOffset, positionOffsetPixels);
+            }
+
+            @Override
+            public void onPageSelected(int position) {
+                mTabstrip.onPageSelected(position);
+            }
+        });
+    }
+
+    public int getSelectedItemPosition() {
+        return mTabstrip.getSelectedItemPosition();
+    }
+}
diff --git a/src/com/android/messaging/ui/CustomHeaderViewPagerAdapter.java b/src/com/android/messaging/ui/CustomHeaderViewPagerAdapter.java
new file mode 100644
index 0000000..1a5cf6a
--- /dev/null
+++ b/src/com/android/messaging/ui/CustomHeaderViewPagerAdapter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import com.android.messaging.Factory;
+
+public class CustomHeaderViewPagerAdapter extends
+        FixedViewPagerAdapter<CustomHeaderPagerViewHolder> {
+
+    public CustomHeaderViewPagerAdapter(final CustomHeaderPagerViewHolder[] viewHolders) {
+        super(viewHolders);
+    }
+
+    @Override
+    public CharSequence getPageTitle(int position) {
+        // The tab strip will handle RTL internally so we should use raw position.
+        return getViewHolder(position, false /* rtlAware */)
+                .getPageTitle(Factory.get().getApplicationContext());
+    }
+}
diff --git a/src/com/android/messaging/ui/FixedViewPagerAdapter.java b/src/com/android/messaging/ui/FixedViewPagerAdapter.java
new file mode 100644
index 0000000..30e11e3
--- /dev/null
+++ b/src/com/android/messaging/ui/FixedViewPagerAdapter.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+import androidx.viewpager.widget.PagerAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * A PagerAdapter that provides a fixed number of paged Views provided by a fixed set of
+ * {@link PagerViewHolder}'s. This allows us to put a fixed number of Views, instead of fragments,
+ * into a given ViewPager.
+ */
+public class FixedViewPagerAdapter<T extends PagerViewHolder> extends PagerAdapter {
+    private final T[] mViewHolders;
+
+    public FixedViewPagerAdapter(final T[] viewHolders) {
+        Assert.notNull(viewHolders);
+        mViewHolders = viewHolders;
+    }
+
+    @Override
+    public Object instantiateItem(final ViewGroup container, final int position) {
+        final PagerViewHolder viewHolder = getViewHolder(position);
+        final View view = viewHolder.getView(container);
+        if (view == null) {
+            return null;
+        }
+        view.setTag(viewHolder);
+        container.addView(view);
+        return viewHolder;
+    }
+
+    @Override
+    public void destroyItem(final ViewGroup container, final int position, final Object object) {
+        final PagerViewHolder viewHolder = getViewHolder(position);
+        final View destroyedView = viewHolder.destroyView();
+        if (destroyedView != null) {
+            container.removeView(destroyedView);
+        }
+    }
+
+    @Override
+    public int getCount() {
+        return mViewHolders.length;
+    }
+
+    @Override
+    public boolean isViewFromObject(final View view, final Object object) {
+        return view.getTag() == object;
+    }
+
+    public T getViewHolder(final int i) {
+        return getViewHolder(i, true /* rtlAware */);
+    }
+
+    @VisibleForTesting
+    public T getViewHolder(final int i, final boolean rtlAware) {
+        return mViewHolders[rtlAware ? getRtlPosition(i) : i];
+    }
+
+    @Override
+    public Parcelable saveState() {
+        // The paged views in the view pager gets created and destroyed as the user scrolls through
+        // them. By default, only the pages to the immediate left and right of the current visible
+        // page are realized. Moreover, if the activity gets destroyed and recreated, the pages are
+        // automatically destroyed. Therefore, in order to preserve transient page UI states that
+        // are not persisted in the DB we'd like to store them in a Bundle when views get
+        // destroyed. When the views get recreated, we rehydrate them by passing them the saved
+        // data. When the activity gets destroyed, it invokes saveState() on this adapter to
+        // add this saved Bundle to the overall saved instance state.
+        final Bundle savedViewHolderState = new Bundle(Factory.get().getApplicationContext()
+                .getClassLoader());
+        for (int i = 0; i < mViewHolders.length; i++) {
+            final Parcelable pageState = getViewHolder(i).saveState();
+            savedViewHolderState.putParcelable(getInstanceStateKeyForPage(i), pageState);
+        }
+        return savedViewHolderState;
+    }
+
+    @Override
+    public void restoreState(final Parcelable state, final ClassLoader loader) {
+        if (state instanceof Bundle) {
+            final Bundle restoredViewHolderState = (Bundle) state;
+            ((Bundle) state).setClassLoader(Factory.get().getApplicationContext().getClassLoader());
+            for (int i = 0; i < mViewHolders.length; i++) {
+                final Parcelable pageState = restoredViewHolderState
+                        .getParcelable(getInstanceStateKeyForPage(i));
+                getViewHolder(i).restoreState(pageState);
+            }
+        } else {
+            super.restoreState(state, loader);
+        }
+    }
+
+    public void resetState() {
+        for (int i = 0; i < mViewHolders.length; i++) {
+            getViewHolder(i).resetState();
+        }
+    }
+
+    private String getInstanceStateKeyForPage(final int i) {
+        return getViewHolder(i).getClass().getCanonicalName() + "_savedstate_" + i;
+    }
+
+    protected int getRtlPosition(final int position) {
+        if (UiUtils.isRtlMode()) {
+            return mViewHolders.length - 1 - position;
+        }
+        return position;
+    }
+}
diff --git a/src/com/android/messaging/ui/ImeDetectFrameLayout.java b/src/com/android/messaging/ui/ImeDetectFrameLayout.java
new file mode 100644
index 0000000..32564ea
--- /dev/null
+++ b/src/com/android/messaging/ui/ImeDetectFrameLayout.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.LogUtil;
+
+public class ImeDetectFrameLayout extends FrameLayout {
+    public ImeDetectFrameLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int measuredHeight = getMeasuredHeight();
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(LogUtil.BUGLE_TAG, "ImeDetectFrameLayout " +
+                    "measuredHeight: " + measuredHeight + " getMeasuredHeight(): " +
+                    getMeasuredHeight());
+        }
+
+        if (measuredHeight != getMeasuredHeight() && getContext() instanceof ImeUtil.ImeStateHost) {
+            ((ImeUtil.ImeStateHost) getContext()).onDisplayHeightChanged(heightMeasureSpec);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/LicenseActivity.java b/src/com/android/messaging/ui/LicenseActivity.java
new file mode 100644
index 0000000..a28da81
--- /dev/null
+++ b/src/com/android/messaging/ui/LicenseActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+import com.android.messaging.R;
+
+public class LicenseActivity extends Activity {
+    private final String LICENSE_URL = "file:///android_asset/licenses.html";
+
+    @Override
+    public void onCreate(final Bundle bundle) {
+        super.onCreate(bundle);
+        setContentView(R.layout.license_activity);
+        final WebView webView = (WebView) findViewById(R.id.content);
+        webView.loadUrl(LICENSE_URL);
+    }
+}
diff --git a/src/com/android/messaging/ui/LineWrapLayout.java b/src/com/android/messaging/ui/LineWrapLayout.java
new file mode 100644
index 0000000..5219811
--- /dev/null
+++ b/src/com/android/messaging/ui/LineWrapLayout.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+
+/**
+* A line-wrapping flow layout. Arranges children in horizontal flow, packing as many
+* child views as possible on each line. When the current line does not
+* have enough horizontal space, the layout continues on the next line.
+*/
+public class LineWrapLayout extends ViewGroup {
+    public LineWrapLayout(Context context) {
+        this(context, null);
+    }
+
+    public LineWrapLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int startPadding = UiUtils.getPaddingStart(this);
+        final int endPadding = UiUtils.getPaddingEnd(this);
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec) - startPadding - endPadding;
+        final boolean isFixedSize = (widthMode == MeasureSpec.EXACTLY);
+
+        int height = 0;
+
+        int childCount = getChildCount();
+        int childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
+
+        int x = startPadding;
+        int currLineWidth = 0;
+        int currLineHeight = 0;
+        int maxLineWidth = 0;
+
+        for (int i = 0; i < childCount; i++) {
+            View currChild = getChildAt(i);
+            if (currChild.getVisibility() == GONE) {
+                continue;
+            }
+            LayoutParams layoutParams = (LayoutParams) currChild.getLayoutParams();
+            int startMargin = layoutParams.getStartMargin();
+            int endMargin = layoutParams.getEndMargin();
+            currChild.measure(childWidthSpec, MeasureSpec.UNSPECIFIED);
+            int childMeasuredWidth = currChild.getMeasuredWidth() + startMargin + endMargin;
+            int childMeasuredHeight = currChild.getMeasuredHeight() + layoutParams.topMargin +
+                    layoutParams.bottomMargin;
+
+            if ((x + childMeasuredWidth) > widthSize) {
+                // New line. Update the overall height and reset trackers.
+                height += currLineHeight;
+                currLineHeight = 0;
+                x = startPadding;
+                currLineWidth = 0;
+                startMargin = 0;
+            }
+
+            x += childMeasuredWidth;
+            currLineWidth += childMeasuredWidth;
+            currLineHeight = Math.max(currLineHeight, childMeasuredHeight);
+            maxLineWidth = Math.max(currLineWidth, maxLineWidth);
+        }
+        // And account for the height of the last line.
+        height += currLineHeight;
+
+        int width = isFixedSize ? widthSize : maxLineWidth;
+        setMeasuredDimension(width + startPadding + endPadding,
+                height + getPaddingTop() + getPaddingBottom());
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final int startPadding = UiUtils.getPaddingStart(this);
+        final int endPadding = UiUtils.getPaddingEnd(this);
+        int width = getWidth() - startPadding - endPadding;
+        int y = getPaddingTop();
+        int x = startPadding;
+        int childCount = getChildCount();
+
+        int currLineHeight = 0;
+
+        // Do a dry-run first to get the line heights.
+        final ArrayList<Integer> lineHeights = new ArrayList<Integer>();
+        for (int i = 0; i < childCount; i++) {
+            View currChild = getChildAt(i);
+            if (currChild.getVisibility() == GONE) {
+                continue;
+            }
+            LayoutParams layoutParams = (LayoutParams) currChild.getLayoutParams();
+            int childWidth = currChild.getMeasuredWidth();
+            int childHeight = currChild.getMeasuredHeight();
+            int startMargin = layoutParams.getStartMargin();
+            int endMargin = layoutParams.getEndMargin();
+
+            if ((x + childWidth + startMargin + endMargin) > width) {
+                // new line
+                lineHeights.add(currLineHeight);
+                currLineHeight = 0;
+                x = startPadding;
+                startMargin = 0;
+            }
+            currLineHeight = Math.max(currLineHeight, childHeight + layoutParams.topMargin +
+                    layoutParams.bottomMargin);
+            x += childWidth + startMargin + endMargin;
+        }
+        // Add the last line height.
+        lineHeights.add(currLineHeight);
+
+        // Now perform the actual layout.
+        x = startPadding;
+        currLineHeight = 0;
+        int lineIndex = 0;
+        for (int i = 0; i < childCount; i++) {
+            View currChild = getChildAt(i);
+            if (currChild.getVisibility() == GONE) {
+                continue;
+            }
+            LayoutParams layoutParams = (LayoutParams) currChild.getLayoutParams();
+            int childWidth = currChild.getMeasuredWidth();
+            int childHeight = currChild.getMeasuredHeight();
+            int startMargin = layoutParams.getStartMargin();
+            int endMargin = layoutParams.getEndMargin();
+
+            if ((x + childWidth + startMargin + endMargin) > width) {
+                // new line
+                y += currLineHeight;
+                currLineHeight = 0;
+                x = startPadding;
+                startMargin = 0;
+                lineIndex++;
+            }
+            final int startPositionX = x + startMargin;
+            int startPositionY = y + layoutParams.topMargin;    // default to top gravity
+            final int majorGravity = layoutParams.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+            if (majorGravity != Gravity.TOP && lineHeights.size() > lineIndex) {
+                final int lineHeight = lineHeights.get(lineIndex);
+                switch (majorGravity) {
+                    case Gravity.BOTTOM:
+                        startPositionY = y + lineHeight - childHeight - layoutParams.bottomMargin;
+                        break;
+
+                    case Gravity.CENTER_VERTICAL:
+                        startPositionY = y + (lineHeight - childHeight) / 2;
+                        break;
+                }
+            }
+
+            if (OsUtil.isAtLeastJB_MR2() && getResources().getConfiguration()
+                    .getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+                currChild.layout(width - startPositionX - childWidth, startPositionY,
+                        width - startPositionX, startPositionY + childHeight);
+            } else {
+                currChild.layout(startPositionX, startPositionY, startPositionX + childWidth,
+                        startPositionY + childHeight);
+            }
+            currLineHeight = Math.max(currLineHeight, childHeight + layoutParams.topMargin +
+                    layoutParams.bottomMargin);
+            x += childWidth + startMargin + endMargin;
+        }
+    }
+
+    @Override
+    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return new LayoutParams(p);
+    }
+
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected LayoutParams generateDefaultLayoutParams() {
+        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+    }
+
+    public static final class LayoutParams extends FrameLayout.LayoutParams {
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+        }
+
+        public int getStartMargin() {
+            if (OsUtil.isAtLeastJB_MR2()) {
+                return getMarginStart();
+            } else {
+                return leftMargin;
+            }
+        }
+
+        public int getEndMargin() {
+            if (OsUtil.isAtLeastJB_MR2()) {
+                return getMarginEnd();
+            } else {
+                return rightMargin;
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/ListEmptyView.java b/src/com/android/messaging/ui/ListEmptyView.java
new file mode 100644
index 0000000..8cf3049
--- /dev/null
+++ b/src/com/android/messaging/ui/ListEmptyView.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+
+/**
+ * A common reusable view that shows a hint image and text for an empty list view.
+ */
+public class ListEmptyView extends LinearLayout {
+    private ImageView mEmptyImageHint;
+    private TextView mEmptyTextHint;
+
+    public ListEmptyView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mEmptyImageHint = (ImageView) findViewById(R.id.empty_image_hint);
+        mEmptyTextHint = (TextView) findViewById(R.id.empty_text_hint);
+    }
+
+    public void setImageHint(final int resId) {
+        mEmptyImageHint.setImageResource(resId);
+    }
+
+    public void setTextHint(final int resId) {
+        mEmptyTextHint.setText(getResources().getText(resId));
+    }
+
+    public void setTextHint(final CharSequence hintText) {
+        mEmptyTextHint.setText(hintText);
+    }
+
+    public void setIsImageVisible(final boolean isImageVisible) {
+        mEmptyImageHint.setVisibility(isImageVisible ? VISIBLE : GONE);
+    }
+
+    public void setIsVerticallyCentered(final boolean isVerticallyCentered) {
+        int gravity =
+                isVerticallyCentered ? Gravity.CENTER : Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+        ((LinearLayout.LayoutParams) mEmptyImageHint.getLayoutParams()).gravity = gravity;
+        ((LinearLayout.LayoutParams) mEmptyTextHint.getLayoutParams()).gravity = gravity;
+        getLayoutParams().height =
+                isVerticallyCentered ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
+        requestLayout();
+    }
+}
diff --git a/src/com/android/messaging/ui/MaxHeightScrollView.java b/src/com/android/messaging/ui/MaxHeightScrollView.java
new file mode 100644
index 0000000..a000cd1
--- /dev/null
+++ b/src/com/android/messaging/ui/MaxHeightScrollView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.ScrollView;
+
+import com.android.messaging.R;
+
+/**
+ * A ScrollView that limits the maximum height that it can take. This is to work around android
+ * layout's limitation of not having android:maxHeight.
+ */
+public class MaxHeightScrollView extends ScrollView {
+    private static final int NO_MAX_HEIGHT = -1;
+
+    private final int mMaxHeight;
+
+    public MaxHeightScrollView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        final TypedArray attr = context.obtainStyledAttributes(attrs,
+                R.styleable.MaxHeightScrollView, 0, 0);
+        mMaxHeight = attr.getDimensionPixelSize(R.styleable.MaxHeightScrollView_android_maxHeight,
+                NO_MAX_HEIGHT);
+        attr.recycle();
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mMaxHeight != NO_MAX_HEIGHT) {
+            setMeasuredDimension(getMeasuredWidth(), Math.min(getMeasuredHeight(), mMaxHeight));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/MultiAttachmentLayout.java b/src/com/android/messaging/ui/MultiAttachmentLayout.java
new file mode 100644
index 0000000..5bae8a5
--- /dev/null
+++ b/src/com/android/messaging/ui/MultiAttachmentLayout.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.AnimationSet;
+import android.view.animation.ScaleAnimation;
+import android.view.animation.TranslateAnimation;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MediaPickerMessagePartData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.ui.AsyncImageView.AsyncImageViewDelayLoader;
+import com.android.messaging.ui.animation.PopupTransitionAnimation;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Holds and displays multiple attachments in a 4x2 grid. Each preview image "tile" can take
+ * one of three sizes - small (1x1), wide (2x1) and large (2x2). We have a number of predefined
+ * layout settings designed for holding 2, 3, 4+ attachments (these layout settings are
+ * tweakable by design request to allow for max flexibility). For a visual example, consider the
+ * following attachment layout:
+ *
+ * +---------------+----------------+
+ * |               |                |
+ * |               |       B        |
+ * |               |                |
+ * |       A       |-------+--------|
+ * |               |       |        |
+ * |               |   C   |    D   |
+ * |               |       |        |
+ * +---------------+-------+--------+
+ *
+ * In the above example, the layout consists of four tiles, A-D. A is a large tile, B is a
+ * wide tile and C & D are both small tiles. A starts at (0,0) and ends at (1,1), B starts at
+ * (2,0) and ends at (3,0), and so on. In our layout class we'd have these tiles in the order
+ * of A-D, so that we make sure the last tile is always the one where we can put the overflow
+ * indicator (e.g. "+2").
+ */
+public class MultiAttachmentLayout extends FrameLayout {
+
+    public interface OnAttachmentClickListener {
+        boolean onAttachmentClick(MessagePartData attachment, Rect viewBoundsOnScreen,
+                boolean longPress);
+    }
+
+    private static final int GRID_WIDTH = 4;    // in # of cells
+    private static final int GRID_HEIGHT = 2;   // in # of cells
+
+    /**
+     * Represents a preview image tile in the layout
+     */
+    private static class Tile {
+        public final int startX;
+        public final int startY;
+        public final int endX;
+        public final int endY;
+
+        private Tile(final int startX, final int startY, final int endX, final int endY) {
+            this.startX = startX;
+            this.startY = startY;
+            this.endX = endX;
+            this.endY = endY;
+        }
+
+        public int getWidthMeasureSpec(final int cellWidth, final int padding) {
+            return MeasureSpec.makeMeasureSpec((endX - startX + 1) * cellWidth - padding * 2,
+                    MeasureSpec.EXACTLY);
+        }
+
+        public int getHeightMeasureSpec(final int cellHeight, final int padding) {
+            return MeasureSpec.makeMeasureSpec((endY - startY + 1) * cellHeight - padding * 2,
+                    MeasureSpec.EXACTLY);
+        }
+
+        public static Tile large(final int startX, final int startY) {
+            return new Tile(startX, startY, startX + 1, startY + 1);
+        }
+
+        public static Tile wide(final int startX, final int startY) {
+            return new Tile(startX, startY, startX + 1, startY);
+        }
+
+        public static Tile small(final int startX, final int startY) {
+            return new Tile(startX, startY, startX, startY);
+        }
+    }
+
+    /**
+     * A layout simply contains a list of tiles, in the order of top-left -> bottom-right.
+     */
+    private static class Layout {
+        public final List<Tile> tiles;
+        public Layout(final Tile[] tilesArray) {
+            tiles = Arrays.asList(tilesArray);
+        }
+    }
+
+    /**
+     * List of predefined layout configurations w.r.t no. of attachments.
+     */
+    private static final Layout[] ATTACHMENT_LAYOUTS_BY_COUNT = {
+        null,   // Doesn't support zero attachments.
+        null,   // Doesn't support one attachment. Single attachment preview is used instead.
+        new Layout(new Tile[] { Tile.large(0, 0), Tile.large(2, 0) }),                  // 2 items
+        new Layout(new Tile[] { Tile.large(0, 0), Tile.wide(2, 0), Tile.wide(2, 1) }),  // 3 items
+        new Layout(new Tile[] { Tile.large(0, 0), Tile.wide(2, 0), Tile.small(2, 1),    // 4+ items
+                Tile.small(3, 1) }),
+    };
+
+    /**
+     * List of predefined RTL layout configurations w.r.t no. of attachments.
+     */
+    private static final Layout[] ATTACHMENT_RTL_LAYOUTS_BY_COUNT = {
+        null,   // Doesn't support zero attachments.
+        null,   // Doesn't support one attachment. Single attachment preview is used instead.
+        new Layout(new Tile[] { Tile.large(2, 0), Tile.large(0, 0)}),                   // 2 items
+        new Layout(new Tile[] { Tile.large(2, 0), Tile.wide(0, 0), Tile.wide(0, 1) }),  // 3 items
+        new Layout(new Tile[] { Tile.large(2, 0), Tile.wide(0, 0), Tile.small(1, 1),    // 4+ items
+                Tile.small(0, 1) }),
+    };
+
+    private Layout mCurrentLayout;
+    private ArrayList<ViewWrapper> mPreviewViews;
+    private int mPlusNumber;
+    private TextView mPlusTextView;
+    private OnAttachmentClickListener mAttachmentClickListener;
+    private AsyncImageViewDelayLoader mImageViewDelayLoader;
+
+    public MultiAttachmentLayout(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mPreviewViews = new ArrayList<ViewWrapper>();
+    }
+
+    public void bindAttachments(final Iterable<MessagePartData> attachments,
+            final Rect transitionRect, final int count) {
+        final ArrayList<ViewWrapper> previousViews = mPreviewViews;
+        mPreviewViews = new ArrayList<ViewWrapper>();
+        removeView(mPlusTextView);
+        mPlusTextView = null;
+
+        determineLayout(attachments, count);
+        buildViews(attachments, previousViews, transitionRect);
+
+        // Remove all previous views that couldn't be recycled.
+        for (final ViewWrapper viewWrapper : previousViews) {
+            removeView(viewWrapper.view);
+        }
+        requestLayout();
+    }
+
+    public OnAttachmentClickListener getOnAttachmentClickListener() {
+        return mAttachmentClickListener;
+    }
+
+    public void setOnAttachmentClickListener(final OnAttachmentClickListener listener) {
+        mAttachmentClickListener = listener;
+    }
+
+    public void setImageViewDelayLoader(final AsyncImageViewDelayLoader delayLoader) {
+        mImageViewDelayLoader = delayLoader;
+    }
+
+    public void setColorFilter(int color) {
+        for (ViewWrapper viewWrapper : mPreviewViews) {
+            if (viewWrapper.view instanceof AsyncImageView) {
+                ((AsyncImageView) viewWrapper.view).setColorFilter(color);
+            }
+        }
+    }
+
+    public void clearColorFilter() {
+        for (ViewWrapper viewWrapper : mPreviewViews) {
+            if (viewWrapper.view instanceof AsyncImageView) {
+                ((AsyncImageView) viewWrapper.view).clearColorFilter();
+            }
+        }
+    }
+
+    private void determineLayout(final Iterable<MessagePartData> attachments, final int count) {
+        Assert.isTrue(attachments != null);
+        final boolean isRtl = AccessibilityUtil.isLayoutRtl(getRootView());
+        if (isRtl) {
+            mCurrentLayout = ATTACHMENT_RTL_LAYOUTS_BY_COUNT[Math.min(count,
+                    ATTACHMENT_RTL_LAYOUTS_BY_COUNT.length - 1)];
+        } else {
+            mCurrentLayout = ATTACHMENT_LAYOUTS_BY_COUNT[Math.min(count,
+                    ATTACHMENT_LAYOUTS_BY_COUNT.length - 1)];
+        }
+
+        // We must have a valid layout for the current configuration.
+        Assert.notNull(mCurrentLayout);
+
+        mPlusNumber = count - mCurrentLayout.tiles.size();
+        Assert.isTrue(mPlusNumber >= 0);
+    }
+
+    private void buildViews(final Iterable<MessagePartData> attachments,
+            final ArrayList<ViewWrapper> previousViews, final Rect transitionRect) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+        final int count = mCurrentLayout.tiles.size();
+        int i = 0;
+        final Iterator<MessagePartData> iterator = attachments.iterator();
+        while (iterator.hasNext() && i < count) {
+            final MessagePartData attachment = iterator.next();
+            ViewWrapper attachmentWrapper = null;
+            // Try to recycle a previous view first
+            for (int j = 0; j < previousViews.size(); j++) {
+                final ViewWrapper previousView = previousViews.get(j);
+                if (previousView.attachment.equals(attachment) &&
+                        !(previousView.attachment instanceof PendingAttachmentData)) {
+                    attachmentWrapper = previousView;
+                    previousViews.remove(j);
+                    break;
+                }
+            }
+
+            if (attachmentWrapper == null) {
+                final View view = AttachmentPreviewFactory.createAttachmentPreview(layoutInflater,
+                        attachment, this, AttachmentPreviewFactory.TYPE_MULTIPLE,
+                        false /* startImageRequest */, mAttachmentClickListener);
+
+                if (view == null) {
+                    // createAttachmentPreview can return null if something goes wrong (e.g.
+                    // attachment has unsupported contentType)
+                    continue;
+                }
+                if (view instanceof AsyncImageView && mImageViewDelayLoader != null) {
+                    AsyncImageView asyncImageView = (AsyncImageView) view;
+                    asyncImageView.setDelayLoader(mImageViewDelayLoader);
+                }
+                addView(view);
+                attachmentWrapper = new ViewWrapper(view, attachment);
+                // Help animate from single to multi by copying over the prev location
+                if (count == 2 && i == 1 && transitionRect != null) {
+                    attachmentWrapper.prevLeft = transitionRect.left;
+                    attachmentWrapper.prevTop = transitionRect.top;
+                    attachmentWrapper.prevWidth = transitionRect.width();
+                    attachmentWrapper.prevHeight = transitionRect.height();
+                }
+            }
+            i++;
+            Assert.notNull(attachmentWrapper);
+            mPreviewViews.add(attachmentWrapper);
+
+            // The first view will animate in using PopupTransitionAnimation, but the remaining
+            // views will slide from their previous position to their new position within the
+            // layout
+            if (i == 0) {
+                if (attachment instanceof MediaPickerMessagePartData) {
+                    final Rect startRect = ((MediaPickerMessagePartData) attachment).getStartRect();
+                    new PopupTransitionAnimation(startRect, attachmentWrapper.view)
+                            .startAfterLayoutComplete();
+                }
+            }
+            attachmentWrapper.needsSlideAnimation = i > 0;
+        }
+
+        // Build the plus text view (e.g. "+2") for when there are more attachments than what
+        // this layout can display.
+        if (mPlusNumber > 0) {
+            mPlusTextView = (TextView) layoutInflater.inflate(R.layout.attachment_more_text_view,
+                    null /* parent */);
+            mPlusTextView.setText(getResources().getString(R.string.attachment_more_items,
+                    mPlusNumber));
+            addView(mPlusTextView);
+        }
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        final int maxWidth = getResources().getDimensionPixelSize(
+                R.dimen.multiple_attachment_preview_width);
+        final int maxHeight = getResources().getDimensionPixelSize(
+                R.dimen.multiple_attachment_preview_height);
+        final int width = Math.min(MeasureSpec.getSize(widthMeasureSpec), maxWidth);
+        final int height = maxHeight;
+        final int cellWidth = width / GRID_WIDTH;
+        final int cellHeight = height / GRID_HEIGHT;
+        final int count = mPreviewViews.size();
+        final int padding = getResources().getDimensionPixelOffset(
+                R.dimen.multiple_attachment_preview_padding);
+        for (int i = 0; i < count; i++) {
+            final View view =  mPreviewViews.get(i).view;
+            final Tile imageTile = mCurrentLayout.tiles.get(i);
+            view.measure(imageTile.getWidthMeasureSpec(cellWidth, padding),
+                    imageTile.getHeightMeasureSpec(cellHeight, padding));
+
+            // Now that we know the size, we can request an appropriately-sized image.
+            if (view instanceof AsyncImageView) {
+                final ImageRequestDescriptor imageRequest =
+                        AttachmentPreviewFactory.getImageRequestDescriptorForAttachment(
+                                mPreviewViews.get(i).attachment,
+                                view.getMeasuredWidth(),
+                                view.getMeasuredHeight());
+                ((AsyncImageView) view).setImageResourceId(imageRequest);
+            }
+
+            if (i == count - 1 && mPlusTextView != null) {
+                // The plus text view always covers the last attachment.
+                mPlusTextView.measure(imageTile.getWidthMeasureSpec(cellWidth, padding),
+                        imageTile.getHeightMeasureSpec(cellHeight, padding));
+            }
+        }
+        setMeasuredDimension(width, height);
+    }
+
+    @Override
+    protected void onLayout(final boolean changed, final int left, final int top, final int right,
+            final int bottom) {
+        final int cellWidth = getMeasuredWidth() / GRID_WIDTH;
+        final int cellHeight = getMeasuredHeight() / GRID_HEIGHT;
+        final int padding = getResources().getDimensionPixelOffset(
+                R.dimen.multiple_attachment_preview_padding);
+        final int count = mPreviewViews.size();
+        for (int i = 0; i < count; i++) {
+            final ViewWrapper viewWrapper =  mPreviewViews.get(i);
+            final View view = viewWrapper.view;
+            final Tile imageTile = mCurrentLayout.tiles.get(i);
+            final int tileLeft = imageTile.startX * cellWidth;
+            final int tileTop = imageTile.startY * cellHeight;
+            view.layout(tileLeft + padding, tileTop + padding,
+                    tileLeft + view.getMeasuredWidth(),
+                    tileTop + view.getMeasuredHeight());
+            if (viewWrapper.needsSlideAnimation) {
+                trySlideAttachmentView(viewWrapper);
+                viewWrapper.needsSlideAnimation = false;
+            } else {
+                viewWrapper.prevLeft = view.getLeft();
+                viewWrapper.prevTop = view.getTop();
+                viewWrapper.prevWidth = view.getWidth();
+                viewWrapper.prevHeight = view.getHeight();
+            }
+
+            if (i == count - 1 && mPlusTextView != null) {
+                // The plus text view always covers the last attachment.
+                mPlusTextView.layout(tileLeft + padding, tileTop + padding,
+                        tileLeft + mPlusTextView.getMeasuredWidth(),
+                        tileTop + mPlusTextView.getMeasuredHeight());
+            }
+        }
+    }
+
+    private void trySlideAttachmentView(final ViewWrapper viewWrapper) {
+        if (!(viewWrapper.attachment instanceof MediaPickerMessagePartData)) {
+            return;
+        }
+        final View view = viewWrapper.view;
+
+
+        final int xOffset = viewWrapper.prevLeft - view.getLeft();
+        final int yOffset = viewWrapper.prevTop - view.getTop();
+        final float scaleX = viewWrapper.prevWidth / (float) view.getWidth();
+        final float scaleY = viewWrapper.prevHeight / (float) view.getHeight();
+
+        if (xOffset == 0 && yOffset == 0 && scaleX == 1 && scaleY == 1) {
+            // Layout hasn't changed
+            return;
+        }
+
+        final AnimationSet animationSet = new AnimationSet(
+                true /* shareInterpolator */);
+        animationSet.addAnimation(new TranslateAnimation(xOffset, 0, yOffset, 0));
+        animationSet.addAnimation(new ScaleAnimation(scaleX, 1, scaleY, 1));
+        animationSet.setDuration(
+                UiUtils.MEDIAPICKER_TRANSITION_DURATION);
+        animationSet.setInterpolator(UiUtils.DEFAULT_INTERPOLATOR);
+        view.startAnimation(animationSet);
+        view.invalidate();
+        viewWrapper.prevLeft = view.getLeft();
+        viewWrapper.prevTop = view.getTop();
+        viewWrapper.prevWidth = view.getWidth();
+        viewWrapper.prevHeight = view.getHeight();
+    }
+
+    public View findViewForAttachment(final MessagePartData attachment) {
+        for (ViewWrapper wrapper : mPreviewViews) {
+            if (wrapper.attachment.equals(attachment) &&
+                    !(wrapper.attachment instanceof PendingAttachmentData)) {
+                return wrapper.view;
+            }
+        }
+        return null;
+    }
+
+    private static class ViewWrapper {
+        final View view;
+        final MessagePartData attachment;
+        boolean needsSlideAnimation;
+        int prevLeft;
+        int prevTop;
+        int prevWidth;
+        int prevHeight;
+
+        ViewWrapper(final View view, final MessagePartData attachment) {
+            this.view = view;
+            this.attachment = attachment;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/OrientedBitmapDrawable.java b/src/com/android/messaging/ui/OrientedBitmapDrawable.java
new file mode 100644
index 0000000..9242668
--- /dev/null
+++ b/src/com/android/messaging/ui/OrientedBitmapDrawable.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.Gravity;
+
+import com.android.messaging.util.exif.ExifInterface;
+
+/**
+ * A drawable that draws a bitmap in a flipped or rotated orientation without having to adjust the
+ * bitmap
+ */
+public class OrientedBitmapDrawable extends BitmapDrawable {
+    private final ExifInterface.OrientationParams mOrientationParams;
+    private final Rect mDstRect;
+    private int mCenterX;
+    private int mCenterY;
+    private boolean mApplyGravity;
+
+    public static BitmapDrawable create(final int orientation, Resources res, Bitmap bitmap) {
+        if (orientation <= ExifInterface.Orientation.TOP_LEFT) {
+            // No need to adjust the bitmap, so just use a regular BitmapDrawable
+            return new BitmapDrawable(res, bitmap);
+        } else {
+            // Create an oriented bitmap drawable
+            return new OrientedBitmapDrawable(orientation, res, bitmap);
+        }
+    }
+
+    private OrientedBitmapDrawable(final int orientation, Resources res, Bitmap bitmap) {
+        super(res, bitmap);
+        mOrientationParams = ExifInterface.getOrientationParams(orientation);
+        mApplyGravity = true;
+        mDstRect = new Rect();
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        if (mOrientationParams.invertDimensions) {
+            return super.getIntrinsicHeight();
+        }
+        return super.getIntrinsicWidth();
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        if (mOrientationParams.invertDimensions) {
+            return super.getIntrinsicWidth();
+        }
+        return super.getIntrinsicHeight();
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        super.onBoundsChange(bounds);
+        mApplyGravity = true;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        if (mApplyGravity) {
+            Gravity.apply(getGravity(), getIntrinsicWidth(), getIntrinsicHeight(), getBounds(),
+                    mDstRect);
+            mCenterX = mDstRect.centerX();
+            mCenterY = mDstRect.centerY();
+            if (mOrientationParams.invertDimensions) {
+                final Matrix matrix = new Matrix();
+                matrix.setRotate(mOrientationParams.rotation, mCenterX, mCenterY);
+                final RectF rotatedRect = new RectF(mDstRect);
+                matrix.mapRect(rotatedRect);
+                mDstRect.set((int) rotatedRect.left, (int) rotatedRect.top, (int) rotatedRect.right,
+                        (int) rotatedRect.bottom);
+            }
+
+            mApplyGravity = false;
+        }
+        canvas.save();
+        canvas.scale(mOrientationParams.scaleX, mOrientationParams.scaleY, mCenterX, mCenterY);
+        canvas.rotate(mOrientationParams.rotation, mCenterX, mCenterY);
+        canvas.drawBitmap(getBitmap(), (Rect) null, mDstRect, getPaint());
+        canvas.restore();
+    }
+}
diff --git a/src/com/android/messaging/ui/PagerViewHolder.java b/src/com/android/messaging/ui/PagerViewHolder.java
new file mode 100644
index 0000000..2f33a0f
--- /dev/null
+++ b/src/com/android/messaging/ui/PagerViewHolder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Holds reusable View(s) for a {@link FixedViewPagerAdapter} to display a page. By using
+ * reusable Views inside ViewPagers this allows us to get rid of nested fragments and the messy
+ * activity lifecycle problems they entail.
+ */
+public interface PagerViewHolder extends PersistentInstanceState {
+    /** Instructs the pager to clean up any view related resources
+     * @return the destroyed View so that the adapter may remove it from the container, or
+     * null if no View has been created. */
+    View destroyView();
+
+    /** @return The view that presents the page view to the user */
+    View getView(ViewGroup container);
+}
diff --git a/src/com/android/messaging/ui/PagingAwareViewPager.java b/src/com/android/messaging/ui/PagingAwareViewPager.java
new file mode 100644
index 0000000..34562dc
--- /dev/null
+++ b/src/com/android/messaging/ui/PagingAwareViewPager.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+import com.android.messaging.util.UiUtils;
+
+/**
+ * A simple extension on the standard ViewPager which lets you turn paging on/off.
+ */
+public class PagingAwareViewPager extends ViewPager {
+    private boolean mPagingEnabled = true;
+
+    public PagingAwareViewPager(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setCurrentItem(int item, boolean smoothScroll) {
+        super.setCurrentItem(getRtlPosition(item), smoothScroll);
+    }
+
+    @Override
+    public void setCurrentItem(int item) {
+        super.setCurrentItem(getRtlPosition(item));
+    }
+
+    @Override
+    public int getCurrentItem() {
+        int position = super.getCurrentItem();
+        return getRtlPosition(position);
+    }
+
+    /**
+     * Switches position in pager to be adjusted for if we are in RtL mode
+     *
+     * @param position
+     * @return position adjusted if in rtl mode
+     */
+    protected int getRtlPosition(final int position) {
+        final PagerAdapter adapter = getAdapter();
+        if (adapter != null && UiUtils.isRtlMode()) {
+            return adapter.getCount() - 1 - position;
+        }
+        return position;
+    }
+
+    @Override
+    public boolean onTouchEvent(final MotionEvent event) {
+        if (!mPagingEnabled) {
+            return false;
+        }
+        return super.onTouchEvent(event);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(final MotionEvent event) {
+        if (!mPagingEnabled) {
+            return false;
+        }
+        return super.onInterceptTouchEvent(event);
+    }
+
+    public void setPagingEnabled(final boolean enabled) {
+        this.mPagingEnabled = enabled;
+    }
+
+    /** This prevents touch-less scrolling eg. while doing accessibility navigation. */
+    @Override
+    public boolean canScrollHorizontally(int direction) {
+        if (mPagingEnabled) {
+            return super.canScrollHorizontally(direction);
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/PermissionCheckActivity.java b/src/com/android/messaging/ui/PermissionCheckActivity.java
new file mode 100644
index 0000000..1b8cedb
--- /dev/null
+++ b/src/com/android/messaging/ui/PermissionCheckActivity.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Activity to check if the user has required permissions. If not, it will try to prompt the user
+ * to grant permissions. However, the OS may not actually prompt the user if the user had
+ * previously checked the "Never ask again" checkbox while denying the required permissions.
+ */
+public class PermissionCheckActivity extends Activity {
+    private static final int REQUIRED_PERMISSIONS_REQUEST_CODE = 1;
+    private static final long AUTOMATED_RESULT_THRESHOLD_MILLLIS = 250;
+    private static final String PACKAGE_URI_PREFIX = "package:";
+    private long mRequestTimeMillis;
+    private TextView mNextView;
+    private TextView mSettingsView;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (redirectIfNeeded()) {
+            return;
+        }
+
+        setContentView(R.layout.permission_check_activity);
+        UiUtils.setStatusBarColor(this, getColor(R.color.permission_check_activity_background));
+
+        findViewById(R.id.exit).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                finish();
+            }
+        });
+
+        mNextView = (TextView) findViewById(R.id.next);
+        mNextView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                tryRequestPermission();
+            }
+        });
+
+        mSettingsView = (TextView) findViewById(R.id.settings);
+        mSettingsView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                        Uri.parse(PACKAGE_URI_PREFIX + getPackageName()));
+                startActivity(intent);
+            }
+        });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        if (redirectIfNeeded()) {
+            return;
+        }
+    }
+
+    private void tryRequestPermission() {
+        final String[] missingPermissions = OsUtil.getMissingRequiredPermissions();
+        if (missingPermissions.length == 0) {
+            redirect();
+            return;
+        }
+
+        mRequestTimeMillis = SystemClock.elapsedRealtime();
+        requestPermissions(missingPermissions, REQUIRED_PERMISSIONS_REQUEST_CODE);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (requestCode == REQUIRED_PERMISSIONS_REQUEST_CODE) {
+            // We do not use grantResults as some of the granted permissions might have been
+            // revoked while the permissions dialog box was being shown for the missing permissions.
+            if (!redirectIfNeeded()) {
+                final long currentTimeMillis = SystemClock.elapsedRealtime();
+                // If the permission request completes very quickly, it must be because the system
+                // automatically denied. This can happen if the user had previously denied it
+                // and checked the "Never ask again" check box.
+                if ((currentTimeMillis - mRequestTimeMillis) < AUTOMATED_RESULT_THRESHOLD_MILLLIS) {
+                    mNextView.setVisibility(View.GONE);
+
+                    mSettingsView.setVisibility(View.VISIBLE);
+                    findViewById(R.id.enable_permission_procedure).setVisibility(View.VISIBLE);
+                }
+            }
+        }
+    }
+
+    /** Returns true if the redirecting was performed */
+    private boolean redirectIfNeeded() {
+        if (!OsUtil.hasRequiredPermissions()) {
+            return false;
+        }
+
+        Factory.get().onRequiredPermissionsAcquired();
+        redirect();
+        return true;
+    }
+
+    private void redirect() {
+        UIIntents.get().launchConversationListActivity(this);
+        finish();
+    }
+}
diff --git a/src/com/android/messaging/ui/PersistentInstanceState.java b/src/com/android/messaging/ui/PersistentInstanceState.java
new file mode 100644
index 0000000..3cc1856
--- /dev/null
+++ b/src/com/android/messaging/ui/PersistentInstanceState.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.os.Parcelable;
+
+/**
+ * Wraps around functionality to save, restore and reset a particular UI component's state.
+ */
+public interface PersistentInstanceState {
+    /**
+     * Saves necessary information about the current state of the instance to later restore
+     * the instance to its original state.
+     */
+    Parcelable saveState();
+
+    /**
+     * Given a previously saved instance state, attempt to restore to its original view state.
+     */
+    void restoreState(Parcelable restoredState);
+
+    /**
+     * Called when any current/preserved state should be reset to zero state.
+     */
+    void resetState();
+}
diff --git a/src/com/android/messaging/ui/PersonItemView.java b/src/com/android/messaging/ui/PersonItemView.java
new file mode 100644
index 0000000..2db1219
--- /dev/null
+++ b/src/com/android/messaging/ui/PersonItemView.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.Intent;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.DetachableBinding;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.datamodel.data.PersonItemData.PersonItemDataListener;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Shows a view for a "person" - could be a contact or a participant. This always shows a
+ * contact icon on the left, and the person's display name on the right.
+ *
+ * This view is always bound to an abstract PersonItemData class, so to use it for a specific
+ * scenario, all you need to do is to create a concrete PersonItemData subclass that bridges
+ * between the underlying data (e.g. ParticipantData) and what the UI wants (e.g. display name).
+ */
+public class PersonItemView extends LinearLayout implements PersonItemDataListener,
+        OnLayoutChangeListener {
+    public interface PersonItemViewListener {
+        void onPersonClicked(PersonItemData data);
+        boolean onPersonLongClicked(PersonItemData data);
+    }
+
+    protected final DetachableBinding<PersonItemData> mBinding;
+    private TextView mNameTextView;
+    private TextView mDetailsTextView;
+    private ContactIconView mContactIconView;
+    private View mDetailsContainer;
+    private PersonItemViewListener mListener;
+    private boolean mAvatarOnly;
+
+    public PersonItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mBinding = BindingBase.createDetachableBinding(this);
+        LayoutInflater.from(getContext()).inflate(R.layout.person_item_view, this, true);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mNameTextView = (TextView) findViewById(R.id.name);
+        mDetailsTextView = (TextView) findViewById(R.id.details);
+        mContactIconView = (ContactIconView) findViewById(R.id.contact_icon);
+        mDetailsContainer = findViewById(R.id.details_container);
+        mNameTextView.addOnLayoutChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mBinding.isBound()) {
+            mBinding.detach();
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mBinding.reAttachIfPossible();
+    }
+
+    /**
+     * Binds to a person item data which will provide us info to be displayed.
+     * @param personData the PersonItemData to be bound to.
+     */
+    public void bind(final PersonItemData personData) {
+        if (mBinding.isBound()) {
+            if (mBinding.getData().equals(personData)) {
+                // Don't rebind if we are requesting the same data.
+                return;
+            }
+            mBinding.unbind();
+        }
+
+        if (personData != null) {
+            mBinding.bind(personData);
+            mBinding.getData().setListener(this);
+
+            // Accessibility reason : in case phone numbers are mixed in the display name,
+            // we need to vocalize it for talkback.
+            final String vocalizedDisplayName = AccessibilityUtil.getVocalizedPhoneNumber(
+                    getResources(), getDisplayName());
+            mNameTextView.setContentDescription(vocalizedDisplayName);
+        }
+        updateViewAppearance();
+    }
+
+    /**
+     * @return Display name, possibly comma-ellipsized.
+     */
+    private String getDisplayName() {
+        final int width = mNameTextView.getMeasuredWidth();
+        final String displayName = mBinding.getData().getDisplayName();
+        if (width == 0 || TextUtils.isEmpty(displayName) || !displayName.contains(",")) {
+            return displayName;
+        }
+        final String plusOneString = getContext().getString(R.string.plus_one);
+        final String plusNString = getContext().getString(R.string.plus_n);
+        return BidiFormatter.getInstance().unicodeWrap(
+                UiUtils.commaEllipsize(
+                        displayName,
+                        mNameTextView.getPaint(),
+                        width,
+                        plusOneString,
+                        plusNString).toString(),
+                TextDirectionHeuristicsCompat.LTR);
+    }
+
+    @Override
+    public void onLayoutChange(final View v, final int left, final int top, final int right,
+            final int bottom, final int oldLeft, final int oldTop, final int oldRight,
+            final int oldBottom) {
+        if (mBinding.isBound() && v == mNameTextView) {
+            setNameTextView();
+        }
+    }
+
+    /**
+     * When set to true, we display only the avatar of the person and hide everything else.
+     */
+    public void setAvatarOnly(final boolean avatarOnly) {
+        mAvatarOnly = avatarOnly;
+        mDetailsContainer.setVisibility(avatarOnly ? GONE : VISIBLE);
+    }
+
+    public boolean isAvatarOnly() {
+        return mAvatarOnly;
+    }
+
+    public void setNameTextColor(final int color) {
+        mNameTextView.setTextColor(color);
+    }
+
+    public void setDetailsTextColor(final int color) {
+        mDetailsTextView.setTextColor(color);
+    }
+
+    public void setListener(final PersonItemViewListener listener) {
+        mListener = listener;
+        if (mListener == null) {
+            return;
+        }
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                if (mListener != null && mBinding.isBound()) {
+                    mListener.onPersonClicked(mBinding.getData());
+                }
+            }
+        });
+        final OnLongClickListener onLongClickListener = new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                if (mListener != null && mBinding.isBound()) {
+                    return mListener.onPersonLongClicked(mBinding.getData());
+                }
+                return false;
+            }
+        };
+        setOnLongClickListener(onLongClickListener);
+        mContactIconView.setOnLongClickListener(onLongClickListener);
+    }
+
+    public void performClickOnAvatar() {
+        mContactIconView.performClick();
+    }
+
+    protected void updateViewAppearance() {
+        if (mBinding.isBound()) {
+            setNameTextView();
+
+            final String details = mBinding.getData().getDetails();
+            if (TextUtils.isEmpty(details)) {
+                mDetailsTextView.setVisibility(GONE);
+            } else {
+                mDetailsTextView.setVisibility(VISIBLE);
+                mDetailsTextView.setText(details);
+            }
+
+            mContactIconView.setImageResourceUri(mBinding.getData().getAvatarUri(),
+                    mBinding.getData().getContactId(), mBinding.getData().getLookupKey(),
+                    mBinding.getData().getNormalizedDestination());
+        } else {
+            mNameTextView.setText("");
+            mContactIconView.setImageResourceUri(null);
+        }
+    }
+
+    private void setNameTextView() {
+        final String displayName = getDisplayName();
+        if (TextUtils.isEmpty(displayName)) {
+            mNameTextView.setVisibility(GONE);
+        } else {
+            mNameTextView.setVisibility(VISIBLE);
+            mNameTextView.setText(displayName);
+        }
+    }
+
+    @Override
+    public void onPersonDataUpdated(final PersonItemData data) {
+        mBinding.ensureBound(data);
+        updateViewAppearance();
+    }
+
+    @Override
+    public void onPersonDataFailed(final PersonItemData data, final Exception exception) {
+        mBinding.ensureBound(data);
+        updateViewAppearance();
+    }
+
+    public Intent getClickIntent() {
+        return mBinding.getData().getClickIntent();
+    }
+}
diff --git a/src/com/android/messaging/ui/PlaceholderInsetDrawable.java b/src/com/android/messaging/ui/PlaceholderInsetDrawable.java
new file mode 100644
index 0000000..dda2e7b
--- /dev/null
+++ b/src/com/android/messaging/ui/PlaceholderInsetDrawable.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+
+/**
+ * A "placeholder" drawable that has the same sizing properties as the real UI element it
+ * replaces.
+ *
+ * This is an InsetDrawable that takes a placeholder drawable (an animation list, or simply
+ * a color drawable) and place it in the center of the inset drawable that's sized to the
+ * requested source width and height of the image that it replaces. Unlike the base
+ * InsetDrawable, this implementation returns the true width and height of the real image
+ * that it's placeholding, instead of the intrinsic size of the contained drawable, so that
+ * when used in an ImageView, it may be positioned/scaled/cropped the same way the real
+ * image is.
+ */
+public class PlaceholderInsetDrawable extends InsetDrawable {
+    // The dimensions of the real image that this drawable is replacing.
+    private final int mSourceWidth;
+    private final int mSourceHeight;
+
+    /**
+     * Given a source drawable, wraps it around in this placeholder drawable by placing the
+     * drawable at the center of the container if possible (or fill the container if the
+     * drawable doesn't have intrinsic size such as color drawable).
+     */
+    public static PlaceholderInsetDrawable fromDrawable(final Drawable drawable,
+            final int sourceWidth, final int sourceHeight) {
+        final int drawableWidth = drawable.getIntrinsicWidth();
+        final int drawableHeight = drawable.getIntrinsicHeight();
+        final int insetHorizontal = drawableWidth < 0 || drawableWidth > sourceWidth ?
+                0 : (sourceWidth - drawableWidth) / 2;
+        final int insetVertical = drawableHeight < 0 || drawableHeight > sourceHeight ?
+                0 : (sourceHeight - drawableHeight) / 2;
+        return new PlaceholderInsetDrawable(drawable, insetHorizontal, insetVertical,
+                insetHorizontal, insetVertical, sourceWidth, sourceHeight);
+    }
+
+    private PlaceholderInsetDrawable(final Drawable drawable, final int insetLeft,
+            final int insetTop, final int insetRight, final int insetBottom,
+            final int sourceWidth, final int sourceHeight) {
+        super(drawable, insetLeft, insetTop, insetRight, insetBottom);
+        mSourceWidth = sourceWidth;
+        mSourceHeight = sourceHeight;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mSourceWidth;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mSourceHeight;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/PlainTextEditText.java b/src/com/android/messaging/ui/PlainTextEditText.java
new file mode 100644
index 0000000..8d6e784
--- /dev/null
+++ b/src/com/android/messaging/ui/PlainTextEditText.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+/**
+ * We want the EditText used in Conversations to convert text to plain text on paste.  This
+ * conversion would happen anyway on send, so without this class it could appear to the user
+ * that we would send e.g. bold or italic formatting, but in the sent message it would just be
+ * plain text.
+ */
+public class PlainTextEditText extends EditText {
+    private static final char OBJECT_UNICODE = '\uFFFC';
+
+    public PlainTextEditText(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    // Intercept and modify the paste event. Let everything else through unchanged.
+    @Override
+    public boolean onTextContextMenuItem(final int id) {
+        if (id == android.R.id.paste) {
+            // We can use this to know where the text position was originally before we pasted
+            final int selectionStartPrePaste = getSelectionStart();
+
+            // Let the EditText's normal paste routine fire, then modify the content after.
+            // This is simpler than re-implementing the paste logic, which we'd have to do
+            // if we want to get the text from the clipboard ourselves and then modify it.
+
+            final boolean result = super.onTextContextMenuItem(id);
+            CharSequence text = getText();
+            int selectionStart = getSelectionStart();
+            int selectionEnd = getSelectionEnd();
+
+            // There is an option in the Chrome mobile app to copy image; however, instead of the
+            // image in the form of the uri, Chrome gives us the html source for the image, which
+            // the platform paste code turns into the unicode object character. The below section
+            // of code looks for that edge case and replaces it with the url for the image.
+            final int startIndex = selectionStart - 1;
+            final int pasteStringLength = selectionStart - selectionStartPrePaste;
+            // Only going to handle the case where the pasted object is the image
+            if (pasteStringLength == 1 && text.charAt(startIndex) == OBJECT_UNICODE) {
+                final ClipboardManager clipboard =
+                        (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+                final ClipData clip = clipboard.getPrimaryClip();
+                if (clip != null) {
+                    ClipData.Item item = clip.getItemAt(0);
+                    StringBuilder sb = new StringBuilder(text);
+                    final String url = item.getText().toString();
+                    sb.replace(selectionStartPrePaste, selectionStart, url);
+                    text = sb.toString();
+                    selectionStart = selectionStartPrePaste + url.length();
+                    selectionEnd = selectionStart;
+                }
+            }
+
+            // This removes the formatting due to the conversion to string.
+            setText(text.toString(), BufferType.EDITABLE);
+
+            // Restore the cursor selection state.
+            setSelection(selectionStart, selectionEnd);
+            return result;
+        } else {
+            return super.onTextContextMenuItem(id);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/PlaybackStateView.java b/src/com/android/messaging/ui/PlaybackStateView.java
new file mode 100644
index 0000000..8d9aac7
--- /dev/null
+++ b/src/com/android/messaging/ui/PlaybackStateView.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+/**
+ * An interface for a UI element ("View") that reflects the playback state of a piece of media
+ * content. It needs to support the ability to take common playback commands (play, pause, stop,
+ * restart) and reflect the state in UI (through timer or progress bar etc.)
+ */
+public interface PlaybackStateView {
+    /**
+     * Restart the playback.
+     */
+    void restart();
+
+    /**
+     * Reset ("stop") the playback to the starting position.
+     */
+    void reset();
+
+    /**
+     * Resume the playback, or start it if it hasn't been started yet.
+     */
+    void resume();
+
+    /**
+     * Pause the playback.
+     */
+    void pause();
+}
diff --git a/src/com/android/messaging/ui/RemoteInputEntrypointActivity.java b/src/com/android/messaging/ui/RemoteInputEntrypointActivity.java
new file mode 100644
index 0000000..c731164
--- /dev/null
+++ b/src/com/android/messaging/ui/RemoteInputEntrypointActivity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.telephony.TelephonyManager;
+
+import com.android.messaging.datamodel.NoConfirmationSmsSendService;
+import com.android.messaging.util.LogUtil;
+
+public class RemoteInputEntrypointActivity extends BaseBugleActivity {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        if (intent == null) {
+            LogUtil.w(TAG, "No intent attached");
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
+
+        // Perform some action depending on the intent
+        String action = intent.getAction();
+        if (Intent.ACTION_SENDTO.equals(action)) {
+            // Build and send the intent
+            final Intent sendIntent = new Intent(this, NoConfirmationSmsSendService.class);
+            sendIntent.setAction(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE);
+            sendIntent.putExtras(intent);
+            // Wear apparently passes all of its extras via the clip data. Must pass it along.
+            sendIntent.setClipData(intent.getClipData());
+            startService(sendIntent);
+            setResult(RESULT_OK);
+        } else {
+            LogUtil.w(TAG, "Unrecognized intent action: " + action);
+            setResult(RESULT_CANCELED);
+        }
+        // This activity should never stick around after processing the intent
+        finish();
+    }
+}
diff --git a/src/com/android/messaging/ui/SmsStorageLowWarningActivity.java b/src/com/android/messaging/ui/SmsStorageLowWarningActivity.java
new file mode 100644
index 0000000..6b3e84b
--- /dev/null
+++ b/src/com/android/messaging/ui/SmsStorageLowWarningActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+
+/**
+ * Activity to contain the dialog of warning sms storage low.
+ */
+public class SmsStorageLowWarningActivity extends BaseBugleFragmentActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FragmentTransaction ft = getFragmentManager().beginTransaction();
+        SmsStorageLowWarningFragment fragment =
+                SmsStorageLowWarningFragment.newInstance();
+        ft.add(fragment, null/*tag*/);
+        ft.commit();
+    }
+}
diff --git a/src/com/android/messaging/ui/SmsStorageLowWarningFragment.java b/src/com/android/messaging/ui/SmsStorageLowWarningFragment.java
new file mode 100644
index 0000000..3ebfdcf
--- /dev/null
+++ b/src/com/android/messaging/ui/SmsStorageLowWarningFragment.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.action.HandleLowStorageAction;
+import com.android.messaging.sms.SmsReleaseStorage;
+import com.android.messaging.sms.SmsReleaseStorage.Duration;
+import com.android.messaging.sms.SmsStorageStatusManager;
+import com.android.messaging.util.Assert;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Dialog to show the sms storage low warning
+ */
+public class SmsStorageLowWarningFragment extends Fragment {
+    private SmsStorageLowWarningFragment() {
+    }
+
+    public static SmsStorageLowWarningFragment newInstance() {
+        return new SmsStorageLowWarningFragment();
+    }
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final FragmentTransaction ft = getFragmentManager().beginTransaction();
+        final ChooseActionDialogFragment dialog = ChooseActionDialogFragment.newInstance();
+        dialog.setTargetFragment(this, 0/*requestCode*/);
+        dialog.show(ft, null/*tag*/);
+    }
+
+    /**
+     * Perform confirm action for a specific action
+     *
+     * @param actionIndex
+     */
+    private void confirm(final int actionIndex) {
+        final FragmentTransaction ft = getFragmentManager().beginTransaction();
+        final ConfirmationDialog dialog = ConfirmationDialog.newInstance(actionIndex);
+        dialog.setTargetFragment(this, 0/*requestCode*/);
+        dialog.show(ft, null/*tag*/);
+    }
+
+    /**
+     * The dialog is cancelled at any step
+     */
+    private void cancel() {
+        getActivity().finish();
+    }
+
+    /**
+     * The dialog to show for user to choose what delete actions to take when storage is low
+     */
+    private static class ChooseActionDialogFragment extends DialogFragment {
+        public static ChooseActionDialogFragment newInstance() {
+            return new ChooseActionDialogFragment();
+        }
+
+        @Override
+        public Dialog onCreateDialog(final Bundle savedInstanceState) {
+            final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+            final LayoutInflater inflater = getActivity().getLayoutInflater();
+            final View dialogLayout = inflater.inflate(
+                    R.layout.sms_storage_low_warning_dialog, null);
+            final ListView actionListView = (ListView) dialogLayout.findViewById(
+                    R.id.free_storage_action_list);
+            final List<String> actions = loadFreeStorageActions(getActivity().getResources());
+            final ActionListAdapter listAdapter = new ActionListAdapter(getActivity(), actions);
+            actionListView.setAdapter(listAdapter);
+
+            builder.setTitle(R.string.sms_storage_low_title)
+                    .setView(dialogLayout)
+                    .setNegativeButton(R.string.ignore, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int id) {
+                            dialog.cancel();
+                        }
+                    });
+
+            final Dialog dialog = builder.create();
+            dialog.setCanceledOnTouchOutside(false);
+            return dialog;
+        }
+
+        @Override
+        public void onCancel(final DialogInterface dialog) {
+            ((SmsStorageLowWarningFragment) getTargetFragment()).cancel();
+        }
+
+        private class ActionListAdapter extends ArrayAdapter<String> {
+            public ActionListAdapter(final Context context, final List<String> actions) {
+                super(context, R.layout.sms_free_storage_action_item_view, actions);
+            }
+
+            @Override
+            public View getView(final int position, final View view, final ViewGroup parent) {
+                TextView actionItemView;
+                if (view == null || !(view instanceof TextView)) {
+                    final LayoutInflater inflater = LayoutInflater.from(getContext());
+                    actionItemView = (TextView) inflater.inflate(
+                            R.layout.sms_free_storage_action_item_view, parent, false);
+                } else {
+                    actionItemView = (TextView) view;
+                }
+
+                final String action = getItem(position);
+                actionItemView.setText(action);
+                actionItemView.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(final View view) {
+                        dismiss();
+                        ((SmsStorageLowWarningFragment) getTargetFragment()).confirm(position);
+                    }
+                });
+                return actionItemView;
+            }
+        }
+    }
+
+    private static final String KEY_ACTION_INDEX = "action_index";
+
+    /**
+     * The dialog to confirm user's delete action
+     */
+    private static class ConfirmationDialog extends DialogFragment {
+        private Duration mDuration;
+        private String mDurationString;
+
+        public static ConfirmationDialog newInstance(final int actionIndex) {
+            final ConfirmationDialog dialog = new ConfirmationDialog();
+            final Bundle args = new Bundle();
+            args.putInt(KEY_ACTION_INDEX, actionIndex);
+            dialog.setArguments(args);
+            return dialog;
+        }
+
+        @Override
+        public void onCancel(final DialogInterface dialog) {
+            ((SmsStorageLowWarningFragment) getTargetFragment()).cancel();
+        }
+
+        @Override
+        public Dialog onCreateDialog(final Bundle savedInstanceState) {
+            mDuration = SmsReleaseStorage.parseMessageRetainingDuration();
+            mDurationString = SmsReleaseStorage.getMessageRetainingDurationString(mDuration);
+
+            final int actionIndex = getArguments().getInt(KEY_ACTION_INDEX);
+            if (actionIndex < 0 || actionIndex > 1) {
+                return null;
+            }
+            final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+            builder.setTitle(R.string.sms_storage_low_title)
+                    .setMessage(getConfirmDialogMessage(actionIndex))
+                    .setNegativeButton(android.R.string.cancel,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(final DialogInterface dialog,
+                                        final int button) {
+                                    dismiss();
+                                    ((SmsStorageLowWarningFragment) getTargetFragment()).cancel();
+                                }
+                    })
+                    .setPositiveButton(android.R.string.ok,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(final DialogInterface dialog,
+                                        final int button) {
+                                    dismiss();
+                                    handleAction(actionIndex);
+                                    getActivity().finish();
+                                    SmsStorageStatusManager.cancelStorageLowNotification();
+                                }
+                    });
+            return builder.create();
+        }
+
+        private void handleAction(final int actionIndex) {
+            final long durationInMillis =
+                    SmsReleaseStorage.durationToTimeInMillis(mDuration);
+            switch (actionIndex) {
+                case 0:
+                    HandleLowStorageAction.handleDeleteMediaMessages(durationInMillis);
+                    break;
+
+                case 1:
+                    HandleLowStorageAction.handleDeleteOldMessages(durationInMillis);
+                    break;
+
+                default:
+                    Assert.fail("Unsupported action");
+                    break;
+            }
+        }
+
+        /**
+         * Get the confirm dialog text for a specific delete action
+         * @param index The action index
+         * @return
+         */
+        private String getConfirmDialogMessage(final int index) {
+            switch (index) {
+                case 0:
+                    return getString(R.string.delete_all_media_confirmation, mDurationString);
+                case 1:
+                    return getString(R.string.delete_oldest_messages_confirmation, mDurationString);
+                case 2:
+                    return getString(R.string.auto_delete_oldest_messages_confirmation,
+                            mDurationString);
+            }
+            throw new IllegalArgumentException(
+                    "SmsStorageLowWarningFragment: invalid action index " + index);
+        }
+    }
+
+    /**
+     * Load the text of delete message actions
+     *
+     * @param resources
+     * @return
+     */
+    private static List<String> loadFreeStorageActions(final Resources resources) {
+        final Duration duration = SmsReleaseStorage.parseMessageRetainingDuration();
+        final String durationString = SmsReleaseStorage.getMessageRetainingDurationString(duration);
+        final List<String> actions = Lists.newArrayList();
+        actions.add(resources.getString(R.string.delete_all_media));
+        actions.add(resources.getString(R.string.delete_oldest_messages, durationString));
+
+        // TODO: Auto-purging is disabled for Bugle V1.
+        // actions.add(resources.getString(R.string.auto_delete_oldest_messages, durationString));
+        return actions;
+    }
+}
diff --git a/src/com/android/messaging/ui/SnackBar.java b/src/com/android/messaging/ui/SnackBar.java
new file mode 100644
index 0000000..2f85461
--- /dev/null
+++ b/src/com/android/messaging/ui/SnackBar.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SnackBar {
+    public static final int LONG_DURATION_IN_MS = 5000;
+    public static final int SHORT_DURATION_IN_MS = 1000;
+    public static final int MAX_DURATION_IN_MS = 10000;
+
+    public interface SnackBarListener {
+        void onActionClick();
+    }
+
+    /**
+     * Defines an action to be performed when the user clicks on the action button on the snack bar
+     */
+    public static class Action {
+        private final Runnable mActionRunnable;
+        private final String mActionLabel;
+
+        public final static int SNACK_BAR_UNDO = 0;
+        public final static int SNACK_BAR_RETRY = 1;
+
+        private Action(@Nullable Runnable actionRunnable, @Nullable String actionLabel) {
+            mActionRunnable = actionRunnable;
+            mActionLabel = actionLabel;
+        }
+
+        Runnable getActionRunnable() {
+            return mActionRunnable;
+        }
+
+        String getActionLabel() {
+            return mActionLabel;
+        }
+
+        public static Action createUndoAction(final Runnable undoRunnable) {
+            return createCustomAction(undoRunnable, Factory.get().getApplicationContext()
+                    .getString(R.string.snack_bar_undo));
+        }
+
+        public static Action createRetryAction(final Runnable retryRunnable) {
+            return createCustomAction(retryRunnable, Factory.get().getApplicationContext()
+                    .getString(R.string.snack_bar_retry));
+        }
+
+
+        public static Action createCustomAction(final Runnable runnable, final String actionLabel) {
+            return new Action(runnable, actionLabel);
+        }
+    }
+
+    /**
+     * Defines the placement of the snack bar (e.g. anchored view, anchor gravity).
+     */
+    public static class Placement {
+        private final View mAnchorView;
+        private final boolean mAnchorAbove;
+
+        private Placement(@NonNull final View anchorView, final boolean anchorAbove) {
+            Assert.notNull(anchorView);
+            mAnchorView = anchorView;
+            mAnchorAbove = anchorAbove;
+        }
+
+        public View getAnchorView() {
+            return mAnchorView;
+        }
+
+        public boolean getAnchorAbove() {
+            return mAnchorAbove;
+        }
+
+        /**
+         * Anchor the snack bar above the given {@code anchorView}.
+         */
+        public static Placement above(final View anchorView) {
+            return new Placement(anchorView, true);
+        }
+
+        /**
+         * Anchor the snack bar below the given {@code anchorView}.
+         */
+        public static Placement below(final View anchorView) {
+            return new Placement(anchorView, false);
+        }
+    }
+
+    public static class Builder {
+        private static final List<SnackBarInteraction> NO_INTERACTIONS = 
+            new ArrayList<SnackBarInteraction>();
+
+        private final Context mContext;
+        private final SnackBarManager mSnackBarManager;
+
+        private String mSnackBarMessage;
+        private int mDuration = LONG_DURATION_IN_MS;
+        private List<SnackBarInteraction> mInteractions = NO_INTERACTIONS;
+        private Action mAction;
+        private Placement mPlacement;
+        // The parent view is only used to get a window token and doesn't affect the layout
+        private View mParentView;
+
+        public Builder(final SnackBarManager snackBarManager, final View parentView) {
+            Assert.notNull(snackBarManager);
+            Assert.notNull(parentView);
+            mSnackBarManager = snackBarManager;
+            mContext = parentView.getContext();
+            mParentView = parentView;
+        }
+
+        public Builder setText(final String snackBarMessage) {
+            Assert.isTrue(!TextUtils.isEmpty(snackBarMessage));
+            mSnackBarMessage = snackBarMessage;
+            return this;
+        }
+
+        public Builder setAction(final Action action) {
+            mAction = action;
+            return this;
+        }
+
+        /**
+         * Sets the duration to show this toast for in milliseconds.
+         */
+        public Builder setDuration(final int duration) {
+            Assert.isTrue(0 < duration && duration < MAX_DURATION_IN_MS);
+            mDuration = duration;
+            return this;
+        }
+
+        /**
+         * Sets the components that this toast's animation will interact with. These components may
+         * be animated to make room for the toast.
+         */
+        public Builder withInteractions(final List<SnackBarInteraction> interactions) {
+            mInteractions = interactions;
+            return this;
+        }
+
+        /**
+         * Place the snack bar with the given placement requirement.
+         */
+        public Builder withPlacement(final Placement placement) {
+            Assert.isNull(mPlacement);
+            mPlacement = placement;
+            return this;
+        }
+
+        public SnackBar build() {
+            return new SnackBar(this);
+        }
+
+        public void show() {
+            mSnackBarManager.show(build());
+        }
+    }
+
+    private final View mRootView;
+    private final Context mContext;
+    private final View mSnackBarView;
+    private final String mText;
+    private final int mDuration;
+    private final List<SnackBarInteraction> mInteractions;
+    private final Action mAction;
+    private final Placement mPlacement;
+    private final TextView mActionTextView;
+    private final TextView mMessageView;
+    private final FrameLayout mMessageWrapper;
+    private final View mParentView;
+
+    private SnackBarListener mListener;
+
+    private SnackBar(final Builder builder) {
+        mContext = builder.mContext;
+        mRootView = LayoutInflater.from(mContext).inflate(R.layout.snack_bar,
+            null /* WindowManager will show this in show() below */);
+        mSnackBarView = mRootView.findViewById(R.id.snack_bar);
+        mText = builder.mSnackBarMessage;
+        mDuration = builder.mDuration;
+        mAction = builder.mAction;
+        mPlacement = builder.mPlacement;
+        mParentView = builder.mParentView;
+        if (builder.mInteractions == null) {
+            mInteractions = new ArrayList<SnackBarInteraction>();
+        } else {
+            mInteractions = builder.mInteractions;
+        }
+
+        mActionTextView = (TextView) mRootView.findViewById(R.id.snack_bar_action);
+        mMessageView = (TextView) mRootView.findViewById(R.id.snack_bar_message);
+        mMessageWrapper = (FrameLayout) mRootView.findViewById(R.id.snack_bar_message_wrapper);
+
+        setUpButton();
+        setUpTextLines();
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    public View getRootView() {
+        return mRootView;
+    }
+
+    public View getParentView() {
+        return mParentView;
+    }
+
+    public View getSnackBarView() {
+        return mSnackBarView;
+    }
+
+    public String getMessageText() {
+        return mText;
+    }
+
+    public String getActionLabel() {
+        if (mAction == null) {
+            return null;
+        }
+        return mAction.getActionLabel();
+    }
+
+    public int getDuration() {
+        return mDuration;
+    }
+
+    public Placement getPlacement() {
+        return mPlacement;
+    }
+
+    public List<SnackBarInteraction> getInteractions() {
+        return mInteractions;
+    }
+
+    public void setEnabled(final boolean enabled) {
+        mActionTextView.setClickable(enabled);
+    }
+
+    public void setListener(final SnackBarListener snackBarListener) {
+        mListener = snackBarListener;
+    }
+
+    private void setUpButton() {
+        if (mAction == null || mAction.getActionRunnable() == null) {
+            mActionTextView.setVisibility(View.GONE);
+            // In the XML layout we add left/right padding to the button to add space between
+            // the message text and the button and on the right side we add padding to put space
+            // between the button and the edge of the snack bar. This is so the button can use the
+            // padding area as part of it's click target. Since we have no button, we need to put
+            // some margin on the right side. While the left margin is already set on the wrapper,
+            // we're setting it again to not have to make a special case for RTL.
+            final MarginLayoutParams lp = (MarginLayoutParams) mMessageWrapper.getLayoutParams();
+            final int leftRightMargin = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.snack_bar_left_right_margin);
+            lp.leftMargin = leftRightMargin;
+            lp.rightMargin = leftRightMargin;
+            mMessageWrapper.setLayoutParams(lp);
+        } else {
+            mActionTextView.setVisibility(View.VISIBLE);
+            mActionTextView.setText(mAction.getActionLabel());
+            mActionTextView.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(final View v) {
+                    mAction.getActionRunnable().run();
+                    if (mListener != null) {
+                        mListener.onActionClick();
+                    }
+                }
+            });
+        }
+    }
+
+    private void setUpTextLines() {
+        if (mText == null) {
+            mMessageView.setVisibility(View.GONE);
+        } else {
+            mMessageView.setVisibility(View.VISIBLE);
+            mMessageView.setText(mText);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/SnackBarInteraction.java b/src/com/android/messaging/ui/SnackBarInteraction.java
new file mode 100644
index 0000000..f723caa
--- /dev/null
+++ b/src/com/android/messaging/ui/SnackBarInteraction.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * An interface that defines how a component can be animated with an {@link SnackBar}.
+ */
+public interface SnackBarInteraction {
+    /**
+     * Returns the animator that will be run in reaction to the given SnackBar being shown.
+     *
+     * Implementations may return null here if it determines that the given SnackBar does not need
+     * to animate this component.
+     */
+    ViewPropertyAnimator animateOnSnackBarShow(SnackBar snackBar);
+
+    /**
+     * Returns the animator that will be run in reaction to the given SnackBar being dismissed.
+     *
+     * Implementations may return null here if it determines that the given SnackBar does not need
+     * to animate this component.
+     */
+    ViewPropertyAnimator animateOnSnackBarDismiss(SnackBar snackBar);
+
+    /**
+     * A basic implementation of {@link SnackBarInteraction} that assumes that the
+     * {@link SnackBar} is always shown with {@link Gravity#BOTTOM} and that the provided View will
+     * always need to be translated up to make room for the SnackBar.
+     */
+    public static class BasicSnackBarInteraction implements SnackBarInteraction {
+        private final View mView;
+
+        public BasicSnackBarInteraction(final View view) {
+            mView = Preconditions.checkNotNull(view);
+        }
+
+        @Override
+        public ViewPropertyAnimator animateOnSnackBarShow(final SnackBar snackBar) {
+            final View rootView = snackBar.getRootView();
+            return mView.animate().translationY(-rootView.getMeasuredHeight());
+        }
+
+        @Override
+        public ViewPropertyAnimator animateOnSnackBarDismiss(final SnackBar snackBar) {
+            return mView.animate().translationY(0);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/SnackBarManager.java b/src/com/android/messaging/ui/SnackBarManager.java
new file mode 100644
index 0000000..d5ca870
--- /dev/null
+++ b/src/com/android/messaging/ui/SnackBarManager.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.WindowManager;
+import android.widget.PopupWindow;
+import android.widget.PopupWindow.OnDismissListener;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.ui.SnackBar.Placement;
+import com.android.messaging.ui.SnackBar.SnackBarListener;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.TextUtil;
+import com.android.messaging.util.UiUtils;
+import com.google.common.base.Joiner;
+
+import java.util.List;
+
+public class SnackBarManager {
+
+    private static SnackBarManager sInstance;
+
+    public static SnackBarManager get() {
+        if (sInstance == null) {
+            synchronized (SnackBarManager.class) {
+                if (sInstance == null) {
+                    sInstance = new SnackBarManager();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    private final Runnable mDismissRunnable = new Runnable() {
+        @Override
+        public void run() {
+            dismiss();
+        }
+    };
+
+    private final OnTouchListener mDismissOnTouchListener = new OnTouchListener() {
+        @Override
+        public boolean onTouch(final View view, final MotionEvent event) {
+            // Dismiss the {@link SnackBar} but don't consume the event.
+            dismiss();
+            return false;
+        }
+    };
+
+    private final SnackBarListener mDismissOnUserTapListener = new SnackBarListener() {
+        @Override
+        public void onActionClick() {
+            dismiss();
+        }
+    };
+
+    private final OnAttachStateChangeListener mAttachStateChangeListener =
+            new OnAttachStateChangeListener() {
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                    // Dismiss the PopupWindow and clear SnackBarManager state.
+                    mHideHandler.removeCallbacks(mDismissRunnable);
+                    mPopupWindow.dismiss();
+
+                    mCurrentSnackBar = null;
+                    mNextSnackBar = null;
+                    mIsCurrentlyDismissing = false;
+                }
+
+                @Override
+                public void onViewAttachedToWindow(View v) {}
+            };
+
+    private final int mTranslationDurationMs;
+    private final Handler mHideHandler;
+
+    private SnackBar mCurrentSnackBar;
+    private SnackBar mLatestSnackBar;
+    private SnackBar mNextSnackBar;
+    private boolean mIsCurrentlyDismissing;
+    private PopupWindow mPopupWindow;
+
+    private SnackBarManager() {
+        mTranslationDurationMs = Factory.get().getApplicationContext().getResources().getInteger(
+                R.integer.snackbar_translation_duration_ms);
+        mHideHandler = new Handler();
+    }
+
+    public SnackBar getLatestSnackBar() {
+        return mLatestSnackBar;
+    }
+
+    public SnackBar.Builder newBuilder(final View parentView) {
+        return new SnackBar.Builder(this, parentView);
+    }
+
+    /**
+     * The given snackBar is not guaranteed to be shown. If the previous snackBar is animating away,
+     * and another snackBar is requested to show after this one, this snackBar will be skipped.
+     */
+    public void show(final SnackBar snackBar) {
+        Assert.notNull(snackBar);
+
+        if (mCurrentSnackBar != null) {
+            LogUtil.d(LogUtil.BUGLE_TAG, "Showing snack bar, but currentSnackBar was not null.");
+
+            // Dismiss the current snack bar. That will cause the next snack bar to be shown on
+            // completion.
+            mNextSnackBar = snackBar;
+            mLatestSnackBar = snackBar;
+            dismiss();
+            return;
+        }
+
+        mCurrentSnackBar = snackBar;
+        mLatestSnackBar = snackBar;
+
+        // We want to know when either button was tapped so we can dismiss.
+        snackBar.setListener(mDismissOnUserTapListener);
+
+        // Cancel previous dismisses & set dismiss for the delay time.
+        mHideHandler.removeCallbacks(mDismissRunnable);
+        mHideHandler.postDelayed(mDismissRunnable, snackBar.getDuration());
+
+        snackBar.setEnabled(false);
+
+        // For some reason, the addView function does not respect layoutParams.
+        // We need to explicitly set it first here.
+        final View rootView = snackBar.getRootView();
+
+        if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+            LogUtil.d(LogUtil.BUGLE_TAG, "Showing snack bar: " + snackBar);
+        }
+        // Measure the snack bar root view so we know how much to translate by.
+        measureSnackBar(snackBar);
+        mPopupWindow = new PopupWindow(snackBar.getContext());
+        mPopupWindow.setWidth(LayoutParams.MATCH_PARENT);
+        mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);
+        mPopupWindow.setBackgroundDrawable(null);
+        mPopupWindow.setContentView(rootView);
+        final Placement placement = snackBar.getPlacement();
+        if (placement == null) {
+            mPopupWindow.showAtLocation(
+                    snackBar.getParentView(), Gravity.BOTTOM | Gravity.START,
+                    0, getScreenBottomOffset(snackBar));
+        } else {
+            final View anchorView = placement.getAnchorView();
+
+            // You'd expect PopupWindow.showAsDropDown to ensure the popup moves with the anchor
+            // view, which it does for scrolling, but not layout changes, so we have to manually
+            // update while the snackbar is showing
+            final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
+                @Override
+                public void onGlobalLayout() {
+                    mPopupWindow.update(anchorView, 0, getRelativeOffset(snackBar),
+                            anchorView.getWidth(), LayoutParams.WRAP_CONTENT);
+                }
+            };
+            anchorView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
+            mPopupWindow.setOnDismissListener(new OnDismissListener() {
+                @Override
+                public void onDismiss() {
+                    anchorView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
+                }
+            });
+            mPopupWindow.showAsDropDown(anchorView, 0, getRelativeOffset(snackBar));
+        }
+
+        snackBar.getParentView().addOnAttachStateChangeListener(mAttachStateChangeListener);
+
+        // Animate the toast bar into view.
+        placeSnackBarOffScreen(snackBar);
+        animateSnackBarOnScreen(snackBar).withEndAction(new Runnable() {
+            @Override
+            public void run() {
+                mCurrentSnackBar.setEnabled(true);
+                makeCurrentSnackBarDismissibleOnTouch();
+                // Fire an accessibility event as needed
+                String snackBarText = snackBar.getMessageText();
+                if (!TextUtils.isEmpty(snackBarText) &&
+                        TextUtils.getTrimmedLength(snackBarText) > 0) {
+                    snackBarText = snackBarText.trim();
+                    final String snackBarActionText = snackBar.getActionLabel();
+                    if (!TextUtil.isAllWhitespace(snackBarActionText)) {
+                        snackBarText = Joiner.on(", ").join(snackBarText, snackBarActionText);
+                    }
+                    AccessibilityUtil.announceForAccessibilityCompat(snackBar.getSnackBarView(),
+                            null /*accessibilityManager*/, snackBarText);
+                }
+            }
+        });
+
+        // Animate any interaction views out of the way.
+        animateInteractionsOnShow(snackBar);
+    }
+
+    /**
+     * Dismisses the current toast that is showing. If there is a toast waiting to be shown, that
+     * toast will be shown when the current one has been dismissed.
+     */
+    public void dismiss() {
+        mHideHandler.removeCallbacks(mDismissRunnable);
+
+        if (mCurrentSnackBar == null || mIsCurrentlyDismissing) {
+            return;
+        }
+
+        final SnackBar snackBar = mCurrentSnackBar;
+
+        LogUtil.d(LogUtil.BUGLE_TAG, "Dismissing snack bar.");
+        mIsCurrentlyDismissing = true;
+
+        snackBar.setEnabled(false);
+
+        // Animate the toast bar down.
+        final View rootView = snackBar.getRootView();
+        animateSnackBarOffScreen(snackBar).withEndAction(new Runnable() {
+            @Override
+            public void run() {
+                rootView.setVisibility(View.GONE);
+                try {
+                    mPopupWindow.dismiss();
+                } catch (IllegalArgumentException e) {
+                    // PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
+                    // has already ended while we were animating
+                }
+                snackBar.getParentView()
+                        .removeOnAttachStateChangeListener(mAttachStateChangeListener);
+
+                mCurrentSnackBar = null;
+                mIsCurrentlyDismissing = false;
+
+                // Show the next toast if one is waiting.
+                if (mNextSnackBar != null) {
+                    final SnackBar localNextSnackBar = mNextSnackBar;
+                    mNextSnackBar = null;
+                    show(localNextSnackBar);
+                }
+            }
+        });
+
+        // Animate any interaction views back.
+        animateInteractionsOnDismiss(snackBar);
+    }
+
+    private void makeCurrentSnackBarDismissibleOnTouch() {
+        // Set touching on the entire view, the {@link SnackBar} itself, as
+        // well as the button's dismiss the toast.
+        mCurrentSnackBar.getRootView().setOnTouchListener(mDismissOnTouchListener);
+        mCurrentSnackBar.getSnackBarView().setOnTouchListener(mDismissOnTouchListener);
+    }
+
+    private void measureSnackBar(final SnackBar snackBar) {
+        final View rootView = snackBar.getRootView();
+        final Point displaySize = new Point();
+        getWindowManager(snackBar.getContext()).getDefaultDisplay().getSize(displaySize);
+        final int widthSpec = ViewGroup.getChildMeasureSpec(
+                MeasureSpec.makeMeasureSpec(displaySize.x, MeasureSpec.EXACTLY),
+                0, LayoutParams.MATCH_PARENT);
+        final int heightSpec = ViewGroup.getChildMeasureSpec(
+                MeasureSpec.makeMeasureSpec(displaySize.y, MeasureSpec.EXACTLY),
+                0, LayoutParams.WRAP_CONTENT);
+        rootView.measure(widthSpec, heightSpec);
+    }
+
+    private void placeSnackBarOffScreen(final SnackBar snackBar) {
+        final View rootView = snackBar.getRootView();
+        final View snackBarView = snackBar.getSnackBarView();
+        snackBarView.setTranslationY(rootView.getMeasuredHeight());
+    }
+
+    private ViewPropertyAnimator animateSnackBarOnScreen(final SnackBar snackBar) {
+        final View snackBarView = snackBar.getSnackBarView();
+        return normalizeAnimator(snackBarView.animate()).translationX(0).translationY(0);
+    }
+
+    private ViewPropertyAnimator animateSnackBarOffScreen(final SnackBar snackBar) {
+        final View rootView = snackBar.getRootView();
+        final View snackBarView = snackBar.getSnackBarView();
+        return normalizeAnimator(snackBarView.animate()).translationY(rootView.getHeight());
+    }
+
+    private void animateInteractionsOnShow(final SnackBar snackBar) {
+        final List<SnackBarInteraction> interactions = snackBar.getInteractions();
+        for (final SnackBarInteraction interaction : interactions) {
+            if (interaction != null) {
+                final ViewPropertyAnimator animator = interaction.animateOnSnackBarShow(snackBar);
+                if (animator != null) {
+                    normalizeAnimator(animator);
+                }
+            }
+        }
+    }
+
+    private void animateInteractionsOnDismiss(final SnackBar snackBar) {
+        final List<SnackBarInteraction> interactions = snackBar.getInteractions();
+        for (final SnackBarInteraction interaction : interactions) {
+            if (interaction != null) {
+                final ViewPropertyAnimator animator =
+                        interaction.animateOnSnackBarDismiss(snackBar);
+                if (animator != null) {
+                    normalizeAnimator(animator);
+                }
+            }
+        }
+    }
+
+    private ViewPropertyAnimator normalizeAnimator(final ViewPropertyAnimator animator) {
+        return animator
+                .setInterpolator(UiUtils.DEFAULT_INTERPOLATOR)
+                .setDuration(mTranslationDurationMs);
+    }
+
+    private WindowManager getWindowManager(final Context context) {
+        return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+    }
+
+    /**
+     * Get the offset from the bottom of the screen where the snack bar should be placed.
+     */
+    private int getScreenBottomOffset(final SnackBar snackBar) {
+        final WindowManager windowManager = getWindowManager(snackBar.getContext());
+        final DisplayMetrics displayMetrics = new DisplayMetrics();
+        if (OsUtil.isAtLeastL()) {
+            windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
+        } else {
+            windowManager.getDefaultDisplay().getMetrics(displayMetrics);
+        }
+        final int screenHeight = displayMetrics.heightPixels;
+
+        if (OsUtil.isAtLeastL()) {
+            // In L, the navigation bar is included in the space for the popup window, so we have to
+            // offset by the size of the navigation bar
+            final Rect displayRect = new Rect();
+            snackBar.getParentView().getRootView().getWindowVisibleDisplayFrame(displayRect);
+            return screenHeight - displayRect.bottom;
+        }
+
+        return 0;
+    }
+
+    private int getRelativeOffset(final SnackBar snackBar) {
+        final Placement placement = snackBar.getPlacement();
+        Assert.notNull(placement);
+        final View anchorView = placement.getAnchorView();
+        if (placement.getAnchorAbove()) {
+            return -snackBar.getRootView().getMeasuredHeight() - anchorView.getHeight();
+        } else {
+            // Use the default dropdown positioning
+            return 0;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/TestActivity.java b/src/com/android/messaging/ui/TestActivity.java
new file mode 100644
index 0000000..fc3c706
--- /dev/null
+++ b/src/com/android/messaging/ui/TestActivity.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import androidx.fragment.app.FragmentActivity;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.util.LogUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * An empty activity that can be used to host a fragment or view for unit testing purposes. Lives in
+ * app code vs test code due to requirement of ActivityInstrumentationTestCase2.
+ */
+public class TestActivity extends FragmentActivity {
+    private FragmentEventListener mFragmentEventListener;
+
+    public interface FragmentEventListener {
+        public void onAttachFragment(Fragment fragment);
+    }
+
+    @Override
+    protected void onCreate(final Bundle bundle) {
+        super.onCreate(bundle);
+
+        if (bundle != null) {
+            // The test case may have configured the fragment, and recreating the activity will
+            // lose that configuration. The real activity is the only activity that would know
+            // how to reapply that configuration.
+            throw new IllegalStateException("TestActivity cannot get recreated");
+        }
+
+        // There is a race condition, but this often makes it possible for tests to run with the
+        // key guard up
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
+                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
+                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+
+        setContentView(R.layout.test_activity);
+    }
+
+    @VisibleForTesting
+    public void setFragment(final Fragment fragment) {
+        LogUtil.i(LogUtil.BUGLE_TAG, "TestActivity.setFragment");
+        getFragmentManager()
+                .beginTransaction()
+                .replace(R.id.test_content, fragment)
+                .commit();
+        getFragmentManager().executePendingTransactions();
+    }
+
+    @VisibleForTesting
+    public void setView(final View view) {
+        LogUtil.i(LogUtil.BUGLE_TAG, "TestActivity.setView");
+        ((FrameLayout) findViewById(R.id.test_content)).addView(view);
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        if (mFragmentEventListener != null) {
+            mFragmentEventListener.onAttachFragment(fragment);
+        }
+    }
+
+    public void setFragmentEventListener(final FragmentEventListener fragmentEventListener) {
+        mFragmentEventListener = fragmentEventListener;
+    }
+}
diff --git a/src/com/android/messaging/ui/UIIntents.java b/src/com/android/messaging/ui/UIIntents.java
new file mode 100644
index 0000000..bf5edd7
--- /dev/null
+++ b/src/com/android/messaging/ui/UIIntents.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.util.ConversationIdSet;
+
+/**
+ * A central repository of Intents used to start activities.
+ */
+public abstract class UIIntents {
+    public static UIIntents get() {
+        return Factory.get().getUIIntents();
+    }
+
+    // Intent extras
+    public static final String UI_INTENT_EXTRA_CONVERSATION_ID = "conversation_id";
+
+    // Sending draft data (from share intent / message forwarding) to the ConversationActivity.
+    public static final String UI_INTENT_EXTRA_DRAFT_DATA = "draft_data";
+
+    // The request code for picking a media from the Document picker.
+    public static final int REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER = 1400;
+
+    // The request code for picking a contact card from existing Contacts apps.
+    public static final int REQUEST_PICK_CONTACT_CARD = 1500;
+
+    // Indicates what type of notification this applies to (See BugleNotifications:
+    // UPDATE_NONE, UPDATE_MESSAGES, UPDATE_ERRORS, UPDATE_ALL)
+    public static final String UI_INTENT_EXTRA_NOTIFICATIONS_UPDATE = "notifications_update";
+
+    // Pass a set of conversation id's.
+    public static final String UI_INTENT_EXTRA_CONVERSATION_ID_SET = "conversation_id_set";
+
+    // Sending class zero message to its activity
+    public static final String UI_INTENT_EXTRA_MESSAGE_VALUES = "message_values";
+
+    // For the widget to go to the ConversationList from the Conversation.
+    public static final String UI_INTENT_EXTRA_GOTO_CONVERSATION_LIST = "goto_conv_list";
+
+    // Indicates whether a conversation is launched with custom transition.
+    public static final String UI_INTENT_EXTRA_WITH_CUSTOM_TRANSITION = "with_custom_transition";
+
+    public static final String ACTION_RESET_NOTIFICATIONS =
+            "com.android.messaging.reset_notifications";
+
+    // Sending VCard uri to VCard detail activity
+    public static final String UI_INTENT_EXTRA_VCARD_URI = "vcard_uri";
+
+    public static final String CMAS_COMPONENT = "com.android.cellbroadcastreceiver";
+
+    // Intent action for local broadcast receiver for conversation self id change.
+    public static final String CONVERSATION_SELF_ID_CHANGE_BROADCAST_ACTION =
+            "conversation_self_id_change";
+
+    // Conversation self id
+    public static final String UI_INTENT_EXTRA_CONVERSATION_SELF_ID = "conversation_self_id";
+
+    // For opening an APN editor on a particular row in the apn database.
+    public static final String UI_INTENT_EXTRA_APN_ROW_ID = "apn_row_id";
+
+    // Subscription id
+    public static final String UI_INTENT_EXTRA_SUB_ID = "sub_id";
+
+    // Per-Subscription setting activity title
+    public static final String UI_INTENT_EXTRA_PER_SUBSCRIPTION_SETTING_TITLE =
+            "per_sub_setting_title";
+
+    // Is application settings launched as the top level settings activity?
+    public static final String UI_INTENT_EXTRA_TOP_LEVEL_SETTINGS = "top_level_settings";
+
+    // Sending attachment uri from widget
+    public static final String UI_INTENT_EXTRA_ATTACHMENT_URI = "attachment_uri";
+
+    // Sending attachment content type from widget
+    public static final String UI_INTENT_EXTRA_ATTACHMENT_TYPE = "attachment_type";
+
+    public static final String ACTION_WIDGET_CONVERSATION =
+            "com.android.messaging.widget_conversation:";
+
+    public static final String UI_INTENT_EXTRA_REQUIRES_MMS = "requires_mms";
+
+    public static final String UI_INTENT_EXTRA_SELF_ID = "self_id";
+
+    // Message position to scroll to.
+    public static final String UI_INTENT_EXTRA_MESSAGE_POSITION = "message_position";
+
+    /**
+     * Launch the permission check activity
+     */
+    public abstract void launchPermissionCheckActivity(final Context context);
+
+    public abstract void launchConversationListActivity(final Context context);
+
+    /**
+     * Launch an activity to show a conversation. This method by default provides no additional
+     * activity options.
+     */
+    public void launchConversationActivity(final Context context,
+            final String conversationId, final MessageData draft) {
+        launchConversationActivity(context, conversationId, draft, null,
+                false /* withCustomTransition */);
+    }
+
+    /**
+     * Launch an activity to show a conversation.
+     */
+    public abstract void launchConversationActivity(final Context context,
+            final String conversationId, final MessageData draft, final Bundle activityOptions,
+            final boolean withCustomTransition);
+
+
+    /**
+     * Launch an activity to show conversation with conversation list in back stack.
+     */
+    public abstract void launchConversationActivityWithParentStack(Context context,
+            String conversationId, String smsBody);
+
+    /**
+     * Launch an activity to show a conversation as a new task.
+     */
+    public abstract void launchConversationActivityNewTask(final Context context,
+            final String conversationId);
+
+    /**
+     * Launch an activity to start a new conversation
+     */
+    public abstract void launchCreateNewConversationActivity(final Context context,
+            final MessageData draft);
+
+    /**
+     * Launch debug activity to set MMS config options.
+     */
+    public abstract void launchDebugMmsConfigActivity(final Context context);
+
+    /**
+     * Launch an activity to change settings.
+     */
+    public abstract void launchSettingsActivity(final Context context);
+
+    /**
+     * Launch an activity to add a contact with a given destination.
+     */
+    public abstract void launchAddContactActivity(final Context context, final String destination);
+
+    /**
+     * Launch an activity to show the document picker to pick an image/video/audio.
+     *
+     * @param fragment the requesting fragment
+     */
+    public abstract void launchDocumentImagePicker(final Fragment fragment);
+
+    /**
+     * Launch an activity to show the contacts list to pick one.
+     *
+     * @param fragment the requesting fragment
+     */
+    public abstract void launchContactCardPicker(final Fragment fragment);
+
+    /**
+     * Launch an activity to show people & options for a given conversation.
+     */
+    public abstract void launchPeopleAndOptionsActivity(final Activity context,
+            final String conversationId);
+
+    /**
+     * Launch an external activity to handle a phone call
+     * @param phoneNumber the phone number to call
+     * @param clickPosition is the location tapped to start this launch for transition use
+     */
+    public abstract void launchPhoneCallActivity(final Context context, final String phoneNumber,
+                                                 final Point clickPosition);
+
+    /**
+     * Launch an activity to show archived conversations.
+     */
+    public abstract void launchArchivedConversationsActivity(final Context context);
+
+    /**
+     * Launch an activity to show blocked participants.
+     */
+    public abstract void launchBlockedParticipantsActivity(final Context context);
+
+    /**
+     * Launch an activity to show a class zero message
+     */
+    public abstract void launchClassZeroActivity(Context context, ContentValues messageValues);
+
+    /**
+     * Launch an activity to let the user forward a message
+     */
+    public abstract void launchForwardMessageActivity(Context context, MessageData message);
+
+    /**
+     * Launch an activity to show details for a VCard
+     */
+    public abstract void launchVCardDetailActivity(Context context, Uri vcardUri);
+
+    /**
+     * Launch an external activity that handles the intent to add VCard to contacts
+     */
+    public abstract void launchSaveVCardToContactsActivity(Context context, Uri vcardUri);
+
+    /**
+     * Launch an activity to let the user select & unselect the list of attachments to send.
+     */
+    public abstract void launchAttachmentChooserActivity(final Activity activity,
+            final String conversationId, final int requestCode);
+
+    /**
+     * Launch full screen video viewer.
+     */
+    public abstract void launchFullScreenVideoViewer(Context context, Uri videoUri);
+
+    /**
+     * Launch full screen photo viewer.
+     */
+    public abstract void launchFullScreenPhotoViewer(Activity activity, Uri initialPhoto,
+            Rect initialPhotoBounds, Uri photosUri);
+
+    /**
+     * Launch an activity to show general app settings
+     * @param topLevel indicates whether the app settings is launched as the top-level settings
+     *        activity (instead of SettingsActivity which shows a collapsed view of the app
+     *        settings + one settings item per subscription). This is true when there's only one
+     *        active SIM in the system so we can show this activity directly.
+     */
+    public abstract void launchApplicationSettingsActivity(Context context, boolean topLevel);
+
+    /**
+     * Launch an activity to show per-subscription settings
+     */
+    public abstract void launchPerSubscriptionSettingsActivity(Context context, int subId,
+            String settingTitle);
+
+    /**
+     * Get a ACTION_VIEW intent
+     * @param url display the data in the url to users
+     */
+    public abstract Intent getViewUrlIntent(final String url);
+
+    /**
+     * Get an intent to launch the ringtone picker
+     * @param title the title to show in the ringtone picker
+     * @param existingUri the currently set uri
+     * @param defaultUri the default uri if none is currently set
+     * @param toneType type of ringtone to pick, maybe any of RingtoneManager.TYPE_*
+     */
+    public abstract Intent getRingtonePickerIntent(final String title, final Uri existingUri,
+            final Uri defaultUri, final int toneType);
+
+    /**
+     * Get an intent to launch the wireless alert viewer.
+     */
+    public abstract Intent getWirelessAlertsIntent();
+
+    /**
+     * Get an intent to launch the dialog for changing the default SMS App.
+     */
+    public abstract Intent getChangeDefaultSmsAppIntent(final Activity activity);
+
+    /**
+     * Broadcast conversation self id change so it may be reflected in the message compose UI.
+     */
+    public abstract void broadcastConversationSelfIdChange(final Context context,
+            final String conversationId, final String conversationSelfId);
+
+    /**
+     * Get a PendingIntent for starting conversation list from notifications.
+     */
+    public abstract PendingIntent getPendingIntentForConversationListActivity(
+            final Context context);
+
+    /**
+     * Get a PendingIntent for starting conversation list from widget.
+     */
+    public abstract PendingIntent getWidgetPendingIntentForConversationListActivity(
+            final Context context);
+
+    /**
+     * Get a PendingIntent for showing a conversation from notifications.
+     */
+    public abstract PendingIntent getPendingIntentForConversationActivity(final Context context,
+            final String conversationId, final MessageData draft);
+
+    /**
+     * Get an Intent for showing a conversation from the widget.
+     */
+    public abstract Intent getIntentForConversationActivity(final Context context,
+            final String conversationId, final MessageData draft);
+
+    /**
+     * Get a PendingIntent for sending a message to a conversation, without opening the Bugle UI.
+     *
+     * <p>This is intended to be used by the Android Wear companion app when sending transcribed
+     * voice replies.
+     */
+    public abstract PendingIntent getPendingIntentForSendingMessageToConversation(
+            final Context context, final String conversationId, final String selfId,
+            final boolean requiresMms, final int requestCode);
+
+    /**
+     * Get a PendingIntent for clearing notifications.
+     *
+     * <p>This is intended to be used by notifications.
+     */
+    public abstract PendingIntent getPendingIntentForClearingNotifications(final Context context,
+            final int updateTargets, final ConversationIdSet conversationIdSet,
+            final int requestCode);
+
+    /**
+     * Get a PendingIntent for showing low storage notifications.
+     */
+    public abstract PendingIntent getPendingIntentForLowStorageNotifications(final Context context);
+
+    /**
+     * Get a PendingIntent for showing a new message to a secondary user.
+     */
+    public abstract PendingIntent getPendingIntentForSecondaryUserNewMessageNotification(
+            final Context context);
+
+    /**
+     * Get an intent for showing the APN editor.
+     */
+    public abstract Intent getApnEditorIntent(final Context context, final String rowId, int subId);
+
+    /**
+     * Get an intent for showing the APN settings.
+     */
+    public abstract Intent getApnSettingsIntent(final Context context, final int subId);
+
+    /**
+     * Get an intent for showing advanced settings.
+     */
+    public abstract Intent getAdvancedSettingsIntent(final Context context);
+
+    /**
+     * Get an intent for the LaunchConversationActivity.
+     */
+    public abstract Intent getLaunchConversationActivityIntent(final Context context);
+
+    /**
+     *  Tell MediaScanner to re-scan the specified volume.
+     */
+    public abstract void kickMediaScanner(final Context context, final String volume);
+
+    /**
+     * Launch to browser for a url.
+     */
+    public abstract void launchBrowserForUrl(final Context context, final String url);
+
+    /**
+     * Get a PendingIntent for the widget conversation template.
+     */
+    public abstract PendingIntent getWidgetPendingIntentForConversationActivity(
+            final Context context, final String conversationId, final int requestCode);
+
+    /**
+     * Get a PendingIntent for the conversation widget configuration activity template.
+     */
+    public abstract PendingIntent getWidgetPendingIntentForConfigurationActivity(
+            final Context context, final int appWidgetId);
+
+}
diff --git a/src/com/android/messaging/ui/UIIntentsImpl.java b/src/com/android/messaging/ui/UIIntentsImpl.java
new file mode 100644
index 0000000..8a1224a
--- /dev/null
+++ b/src/com/android/messaging/ui/UIIntentsImpl.java
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
+import android.provider.MediaStore;
+import android.provider.Telephony;
+import androidx.annotation.Nullable;
+import androidx.core.app.TaskStackBuilder;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import android.text.TextUtils;
+
+import com.android.ex.photo.Intents.PhotoViewIntentBuilder;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.ConversationImagePartsView;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.receiver.NotificationReceiver;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.ui.appsettings.ApnEditorActivity;
+import com.android.messaging.ui.appsettings.ApnSettingsActivity;
+import com.android.messaging.ui.appsettings.ApplicationSettingsActivity;
+import com.android.messaging.ui.appsettings.PerSubscriptionSettingsActivity;
+import com.android.messaging.ui.appsettings.SettingsActivity;
+import com.android.messaging.ui.attachmentchooser.AttachmentChooserActivity;
+import com.android.messaging.ui.conversation.ConversationActivity;
+import com.android.messaging.ui.conversation.LaunchConversationActivity;
+import com.android.messaging.ui.conversationlist.ArchivedConversationListActivity;
+import com.android.messaging.ui.conversationlist.ConversationListActivity;
+import com.android.messaging.ui.conversationlist.ForwardMessageActivity;
+import com.android.messaging.ui.conversationsettings.PeopleAndOptionsActivity;
+import com.android.messaging.ui.debug.DebugMmsConfigActivity;
+import com.android.messaging.ui.photoviewer.BuglePhotoViewActivity;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ConversationIdSet;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * A central repository of Intents used to start activities.
+ */
+public class UIIntentsImpl extends UIIntents {
+    private static final String CELL_BROADCAST_LIST_ACTIVITY =
+            "com.android.cellbroadcastreceiver.CellBroadcastListActivity";
+    private static final String CALL_TARGET_CLICK_KEY = "touchPoint";
+    private static final String CALL_TARGET_CLICK_EXTRA_KEY =
+            "android.telecom.extra.OUTGOING_CALL_EXTRAS";
+    private static final String MEDIA_SCANNER_CLASS =
+            "com.android.providers.media.MediaScannerService";
+    private static final String MEDIA_SCANNER_PACKAGE = "com.android.providers.media";
+    private static final String MEDIA_SCANNER_SCAN_ACTION = "android.media.IMediaScannerService";
+
+    /**
+     * Get an intent which takes you to a conversation
+     */
+    private Intent getConversationActivityIntent(final Context context,
+            final String conversationId, final MessageData draft,
+            final boolean withCustomTransition) {
+        final Intent intent = new Intent(context, ConversationActivity.class);
+
+        // Always try to reuse the same ConversationActivity in the current task so that we don't
+        // have two conversation activities in the back stack.
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+        // Otherwise we're starting a new conversation
+        if (conversationId != null) {
+            intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        }
+        if (draft != null) {
+            intent.putExtra(UI_INTENT_EXTRA_DRAFT_DATA, draft);
+
+            // If draft attachments came from an external content provider via a share intent, we
+            // need to propagate the URI permissions through to ConversationActivity. This requires
+            // putting the URIs into the ClipData (setData also works, but accepts only one URI).
+            ClipData clipData = null;
+            for (final MessagePartData partData : draft.getParts()) {
+                if (partData.isAttachment()) {
+                    final Uri uri = partData.getContentUri();
+                    if (clipData == null) {
+                        clipData = ClipData.newRawUri("Attachments", uri);
+                    } else {
+                        clipData.addItem(new ClipData.Item(uri));
+                    }
+                }
+            }
+            if (clipData != null) {
+                intent.setClipData(clipData);
+                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
+        }
+        if (withCustomTransition) {
+            intent.putExtra(UI_INTENT_EXTRA_WITH_CUSTOM_TRANSITION, true);
+        }
+
+        if (!(context instanceof Activity)) {
+            // If the caller supplies an application context, and not an activity context, we must
+            // include this flag
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        }
+        return intent;
+    }
+
+    @Override
+    public void launchPermissionCheckActivity(final Context context) {
+        final Intent intent = new Intent(context, PermissionCheckActivity.class);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Get an intent which takes you to the conversation list
+     */
+    private Intent getConversationListActivityIntent(final Context context) {
+        return new Intent(context, ConversationListActivity.class);
+    }
+
+    @Override
+    public void launchConversationListActivity(final Context context) {
+        final Intent intent = getConversationListActivityIntent(context);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Get an intent which shows the low storage warning activity.
+     */
+    private Intent getSmsStorageLowWarningActivityIntent(final Context context) {
+        return new Intent(context, SmsStorageLowWarningActivity.class);
+    }
+
+    @Override
+    public void launchConversationActivity(final Context context,
+            final String conversationId, final MessageData draft, final Bundle activityOptions,
+            final boolean withCustomTransition) {
+        Assert.isTrue(!withCustomTransition || activityOptions != null);
+        final Intent intent = getConversationActivityIntent(context, conversationId, draft,
+                withCustomTransition);
+        context.startActivity(intent, activityOptions);
+    }
+
+    @Override
+    public void launchConversationActivityNewTask(
+            final Context context, final String conversationId) {
+        final Intent intent = getConversationActivityIntent(context, conversationId, null,
+                false /* withCustomTransition */);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchConversationActivityWithParentStack(final Context context,
+                final String conversationId, final String smsBody) {
+        final MessageData messageData = TextUtils.isEmpty(smsBody)
+                ? null
+                : MessageData.createDraftSmsMessage(conversationId, null, smsBody);
+        TaskStackBuilder.create(context)
+                .addNextIntentWithParentStack(
+                        getConversationActivityIntent(context, conversationId, messageData,
+                                false /* withCustomTransition */))
+                .startActivities();
+    }
+
+    @Override
+    public void launchCreateNewConversationActivity(final Context context,
+            final MessageData draft) {
+        final Intent intent = getConversationActivityIntent(context, null, draft,
+                false /* withCustomTransition */);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchDebugMmsConfigActivity(final Context context) {
+        context.startActivity(new Intent(context, DebugMmsConfigActivity.class));
+    }
+
+    @Override
+    public void launchAddContactActivity(final Context context, final String destination) {
+        final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+        final String destinationType = MmsSmsUtils.isEmailAddress(destination) ?
+                Intents.Insert.EMAIL : Intents.Insert.PHONE;
+        intent.setType(Contacts.CONTENT_ITEM_TYPE);
+        intent.putExtra(destinationType, destination);
+        startExternalActivity(context, intent);
+    }
+
+    @Override
+    public void launchSettingsActivity(final Context context) {
+        final Intent intent = new Intent(context, SettingsActivity.class);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchArchivedConversationsActivity(final Context context) {
+        final Intent intent = new Intent(context, ArchivedConversationListActivity.class);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchBlockedParticipantsActivity(final Context context) {
+        final Intent intent = new Intent(context, BlockedParticipantsActivity.class);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchDocumentImagePicker(final Fragment fragment) {
+        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.putExtra(Intent.EXTRA_MIME_TYPES, MessagePartData.ACCEPTABLE_GALLERY_MEDIA_TYPES);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType(ContentType.ANY_TYPE);
+
+        fragment.startActivityForResult(intent, REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER);
+    }
+
+    @Override
+    public void launchContactCardPicker(final Fragment fragment) {
+        final Intent intent = new Intent(Intent.ACTION_PICK);
+        intent.setType(Contacts.CONTENT_TYPE);
+
+        try {
+            fragment.startActivityForResult(intent, REQUEST_PICK_CONTACT_CARD);
+        } catch (final ActivityNotFoundException ex) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't find activity:", ex);
+            UiUtils.showToastAtBottom(R.string.activity_not_found_message);
+        }
+    }
+
+    @Override
+    public void launchPeopleAndOptionsActivity(final Activity activity,
+            final String conversationId) {
+        final Intent intent = new Intent(activity, PeopleAndOptionsActivity.class);
+        intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        activity.startActivityForResult(intent, 0);
+    }
+
+    @Override
+    public void launchPhoneCallActivity(final Context context, final String phoneNumber,
+                                        final Point clickPosition) {
+        final Intent intent = new Intent(Intent.ACTION_CALL,
+                Uri.parse(UriUtil.SCHEME_TEL + phoneNumber));
+        final Bundle extras = new Bundle();
+        extras.putParcelable(CALL_TARGET_CLICK_KEY, clickPosition);
+        intent.putExtra(CALL_TARGET_CLICK_EXTRA_KEY, extras);
+        startExternalActivity(context, intent);
+    }
+
+    @Override
+    public void launchClassZeroActivity(final Context context, final ContentValues messageValues) {
+        final Intent classZeroIntent = new Intent(context, ClassZeroActivity.class)
+                .putExtra(UI_INTENT_EXTRA_MESSAGE_VALUES, messageValues)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+        context.startActivity(classZeroIntent);
+    }
+
+    @Override
+    public void launchForwardMessageActivity(final Context context, final MessageData message) {
+        final Intent forwardMessageIntent = new Intent(context, ForwardMessageActivity.class)
+                .putExtra(UI_INTENT_EXTRA_DRAFT_DATA, message);
+        context.startActivity(forwardMessageIntent);
+    }
+
+    @Override
+    public void launchVCardDetailActivity(final Context context, final Uri vcardUri) {
+        final Intent vcardDetailIntent = new Intent(context, VCardDetailActivity.class)
+                .putExtra(UI_INTENT_EXTRA_VCARD_URI, vcardUri);
+        context.startActivity(vcardDetailIntent);
+    }
+
+    @Override
+    public void launchSaveVCardToContactsActivity(final Context context, final Uri vcardUri) {
+        Assert.isTrue(MediaScratchFileProvider.isMediaScratchSpaceUri(vcardUri));
+        final Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_VIEW);
+        intent.setDataAndType(vcardUri, ContentType.TEXT_VCARD.toLowerCase());
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        startExternalActivity(context, intent);
+    }
+
+    @Override
+    public void launchAttachmentChooserActivity(final Activity activity,
+            final String conversationId, final int requestCode) {
+        final Intent intent = new Intent(activity, AttachmentChooserActivity.class);
+        intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        activity.startActivityForResult(intent, requestCode);
+    }
+
+    @Override
+    public void launchFullScreenVideoViewer(final Context context, final Uri videoUri) {
+        final Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        // So we don't see "surrounding" images in Gallery
+        intent.putExtra("SingleItemOnly", true);
+        intent.setDataAndType(videoUri, ContentType.VIDEO_UNSPECIFIED);
+        startExternalActivity(context, intent);
+    }
+
+    @Override
+    public void launchFullScreenPhotoViewer(final Activity activity, final Uri initialPhoto,
+            final Rect initialPhotoBounds, final Uri photosUri) {
+        final PhotoViewIntentBuilder builder =
+                com.android.ex.photo.Intents.newPhotoViewIntentBuilder(
+                        activity, BuglePhotoViewActivity.class);
+        builder.setPhotosUri(photosUri.toString());
+        builder.setInitialPhotoUri(initialPhoto.toString());
+        builder.setProjection(ConversationImagePartsView.PhotoViewQuery.PROJECTION);
+
+        // Set the location of the imageView so that the photoviewer can animate from that location
+        // to full screen.
+        builder.setScaleAnimation(initialPhotoBounds.left, initialPhotoBounds.top,
+                initialPhotoBounds.width(), initialPhotoBounds.height());
+
+        builder.setDisplayThumbsFullScreen(false);
+        builder.setMaxInitialScale(8);
+        activity.startActivity(builder.build());
+        activity.overridePendingTransition(0, 0);
+    }
+
+    @Override
+    public void launchApplicationSettingsActivity(final Context context, final boolean topLevel) {
+        final Intent intent = new Intent(context, ApplicationSettingsActivity.class);
+        intent.putExtra(UI_INTENT_EXTRA_TOP_LEVEL_SETTINGS, topLevel);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void launchPerSubscriptionSettingsActivity(final Context context, final int subId,
+            final String settingTitle) {
+        final Intent intent = getPerSubscriptionSettingsIntent(context, subId, settingTitle);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public Intent getViewUrlIntent(final String url) {
+        final Uri uri = Uri.parse(url);
+        return new Intent(Intent.ACTION_VIEW, uri);
+    }
+
+    @Override
+    public void broadcastConversationSelfIdChange(final Context context,
+            final String conversationId, final String conversationSelfId) {
+        final Intent intent = new Intent(CONVERSATION_SELF_ID_CHANGE_BROADCAST_ACTION);
+        intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_SELF_ID, conversationSelfId);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForConversationListActivity(final Context context) {
+        final Intent intent = getConversationListActivityIntent(context);
+        return getPendingIntentWithParentStack(context, intent, 0);
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForConversationActivity(final Context context,
+            final String conversationId, final MessageData draft) {
+        final Intent intent = getConversationActivityIntent(context, conversationId, draft,
+                false /* withCustomTransition */);
+        // Ensure that the platform doesn't reuse PendingIntents across conversations
+        intent.setData(MessagingContentProvider.buildConversationMetadataUri(conversationId));
+        return getPendingIntentWithParentStack(context, intent, 0);
+    }
+
+    @Override
+    public Intent getIntentForConversationActivity(final Context context,
+            final String conversationId, final MessageData draft) {
+        final Intent intent = getConversationActivityIntent(context, conversationId, draft,
+                false /* withCustomTransition */);
+        return intent;
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForSendingMessageToConversation(final Context context,
+            final String conversationId, final String selfId, final boolean requiresMms,
+            final int requestCode) {
+        final Intent intent = new Intent(context, RemoteInputEntrypointActivity.class);
+        intent.setAction(Intent.ACTION_SENDTO);
+        // Ensure that the platform doesn't reuse PendingIntents across conversations
+        intent.setData(MessagingContentProvider.buildConversationMetadataUri(conversationId));
+        intent.putExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        intent.putExtra(UIIntents.UI_INTENT_EXTRA_SELF_ID, selfId);
+        intent.putExtra(UIIntents.UI_INTENT_EXTRA_REQUIRES_MMS, requiresMms);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        return getPendingIntentWithParentStack(context, intent, requestCode);
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForClearingNotifications(final Context context,
+            final int updateTargets, final ConversationIdSet conversationIdSet,
+            final int requestCode) {
+        final Intent intent = new Intent(context, NotificationReceiver.class);
+        intent.setAction(ACTION_RESET_NOTIFICATIONS);
+        intent.putExtra(UI_INTENT_EXTRA_NOTIFICATIONS_UPDATE, updateTargets);
+        if (conversationIdSet != null) {
+            intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID_SET,
+                    conversationIdSet.getDelimitedString());
+        }
+        return PendingIntent.getBroadcast(context,
+                requestCode, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    /**
+     * Gets a PendingIntent associated with an Intent to start an Activity. All notifications
+     * that starts an Activity must use this method to get a PendingIntent, which achieves two
+     * goals:
+     * 1. The target activities will be created, with any existing ones destroyed. This ensures
+     *    we don't end up with multiple instances of ConversationListActivity, for example.
+     * 2. The target activity, when launched, will have its backstack correctly constructed so
+     *    back navigation will work correctly.
+     */
+    private static PendingIntent getPendingIntentWithParentStack(final Context context,
+            final Intent intent, final int requestCode) {
+        final TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
+        // Adds the back stack for the Intent (plus the Intent itself)
+        stackBuilder.addNextIntentWithParentStack(intent);
+        final PendingIntent resultPendingIntent =
+            stackBuilder.getPendingIntent(requestCode, PendingIntent.FLAG_UPDATE_CURRENT);
+        return resultPendingIntent;
+    }
+
+    @Override
+    public Intent getRingtonePickerIntent(final String title, final Uri existingUri,
+            final Uri defaultUri, final int toneType) {
+        return new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
+                .putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, toneType)
+                .putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, title)
+                .putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existingUri)
+                .putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, defaultUri);
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForLowStorageNotifications(final Context context) {
+        final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
+        final Intent conversationListIntent = getConversationListActivityIntent(context);
+        taskStackBuilder.addNextIntent(conversationListIntent);
+        taskStackBuilder.addNextIntentWithParentStack(
+                getSmsStorageLowWarningActivityIntent(context));
+
+        return taskStackBuilder.getPendingIntent(
+                0, PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    @Override
+    public PendingIntent getPendingIntentForSecondaryUserNewMessageNotification(
+            final Context context) {
+        return getPendingIntentForConversationListActivity(context);
+    }
+
+    @Override
+    public Intent getWirelessAlertsIntent() {
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setComponent(new ComponentName(CMAS_COMPONENT, CELL_BROADCAST_LIST_ACTIVITY));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+
+    @Override
+    public Intent getApnEditorIntent(final Context context, final String rowId, final int subId) {
+        final Intent intent = new Intent(context, ApnEditorActivity.class);
+        intent.putExtra(UI_INTENT_EXTRA_APN_ROW_ID, rowId);
+        intent.putExtra(UI_INTENT_EXTRA_SUB_ID, subId);
+        return intent;
+    }
+
+    @Override
+    public Intent getApnSettingsIntent(final Context context, final int subId) {
+        final Intent intent = new Intent(context, ApnSettingsActivity.class)
+                .putExtra(UI_INTENT_EXTRA_SUB_ID, subId);
+        return intent;
+    }
+
+    @Override
+    public Intent getAdvancedSettingsIntent(final Context context) {
+        return getPerSubscriptionSettingsIntent(context, ParticipantData.DEFAULT_SELF_SUB_ID, null);
+    }
+
+    @Override
+    public Intent getChangeDefaultSmsAppIntent(final Activity activity) {
+        final Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
+        intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, activity.getPackageName());
+        return intent;
+    }
+
+    @Override
+    public void launchBrowserForUrl(final Context context, final String url) {
+        final Intent intent = getViewUrlIntent(url);
+        startExternalActivity(context, intent);
+    }
+
+    /**
+     * Provides a safe way to handle external activities which may not exist.
+     */
+    private void startExternalActivity(final Context context, final Intent intent) {
+        try {
+            context.startActivity(intent);
+        } catch (final ActivityNotFoundException ex) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't find activity:", ex);
+            UiUtils.showToastAtBottom(R.string.activity_not_found_message);
+        }
+    }
+
+    private Intent getPerSubscriptionSettingsIntent(final Context context, final int subId,
+            @Nullable final String settingTitle) {
+        return new Intent(context, PerSubscriptionSettingsActivity.class)
+            .putExtra(UI_INTENT_EXTRA_SUB_ID, subId)
+            .putExtra(UI_INTENT_EXTRA_PER_SUBSCRIPTION_SETTING_TITLE, settingTitle);
+    }
+
+    @Override
+    public Intent getLaunchConversationActivityIntent(final Context context) {
+        final Intent intent = new Intent(context, LaunchConversationActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
+        return intent;
+    }
+
+    @Override
+    public void kickMediaScanner(final Context context, final String volume) {
+        final Intent intent = new Intent(MEDIA_SCANNER_SCAN_ACTION)
+            .putExtra(MediaStore.MEDIA_SCANNER_VOLUME, volume)
+            .setClassName(MEDIA_SCANNER_PACKAGE, MEDIA_SCANNER_CLASS);
+        context.startService(intent);
+    }
+
+    @Override
+    public PendingIntent getWidgetPendingIntentForConversationActivity(final Context context,
+            final String conversationId, final int requestCode) {
+        final Intent intent = getConversationActivityIntent(context, null, null,
+                false /* withCustomTransition */);
+        if (conversationId != null) {
+            intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+
+            // Set the action to something unique to this conversation so if someone calls this
+            // function again on a different conversation, they'll get a new PendingIntent instead
+            // of the old one.
+            intent.setAction(ACTION_WIDGET_CONVERSATION + conversationId);
+        }
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return getPendingIntentWithParentStack(context, intent, requestCode);
+    }
+
+    @Override
+    public PendingIntent getWidgetPendingIntentForConversationListActivity(
+            final Context context) {
+        final Intent intent = getConversationListActivityIntent(context);
+        return getPendingIntentWithParentStack(context, intent, 0);
+    }
+
+    @Override
+    public PendingIntent getWidgetPendingIntentForConfigurationActivity(final Context context,
+            final int appWidgetId) {
+        final Intent configureIntent = new Intent(context, WidgetPickConversationActivity.class);
+        configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+        configureIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+        configureIntent.setData(Uri.parse(configureIntent.toUri(Intent.URI_INTENT_SCHEME)));
+        configureIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
+        return getPendingIntentWithParentStack(context, configureIntent, 0);
+    }
+}
diff --git a/src/com/android/messaging/ui/VCardDetailActivity.java b/src/com/android/messaging/ui/VCardDetailActivity.java
new file mode 100644
index 0000000..b9fb3d1
--- /dev/null
+++ b/src/com/android/messaging/ui/VCardDetailActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+
+/**
+ * An activity that hosts VCardDetailFragment that shows the content of a VCard that contains one
+ * or more contacts.
+ */
+public class VCardDetailActivity extends BugleActionBarActivity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.vcard_detail_activity);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        if (fragment instanceof VCardDetailFragment) {
+            final Uri vCardUri =
+                    getIntent().getParcelableExtra(UIIntents.UI_INTENT_EXTRA_VCARD_URI);
+            Assert.notNull(vCardUri);
+            final VCardDetailFragment vCardDetailFragment = (VCardDetailFragment) fragment;
+            vCardDetailFragment.setVCardUri(vCardUri);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                // Treat the home press as back press so that when we go back to
+                // ConversationActivity, it doesn't lose its original intent (conversation id etc.)
+                onBackPressed();
+                return true;
+
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/VCardDetailAdapter.java b/src/com/android/messaging/ui/VCardDetailAdapter.java
new file mode 100644
index 0000000..cfdd836
--- /dev/null
+++ b/src/com/android/messaging/ui/VCardDetailAdapter.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.media.VCardResourceEntry;
+import com.android.messaging.datamodel.media.VCardResourceEntry.VCardResourceEntryDestinationItem;
+
+import java.util.List;
+
+/**
+ * Displays a list of expandable contact cards shown in the VCardDetailActivity.
+ */
+public class VCardDetailAdapter extends BaseExpandableListAdapter {
+    private final List<VCardResourceEntry> mVCards;
+    private final LayoutInflater mInflater;
+
+    public VCardDetailAdapter(final Context context, final List<VCardResourceEntry> vCards) {
+        mVCards = vCards;
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    @Override
+    public Object getChild(final int groupPosition, final int childPosition) {
+        return mVCards.get(groupPosition).getContactInfo().get(childPosition);
+    }
+
+    @Override
+    public long getChildId(final int groupPosition, final int childPosition) {
+        return childPosition;
+    }
+
+    @Override
+    public View getChildView(final int groupPosition, final int childPosition,
+            final boolean isLastChild, final View convertView, final ViewGroup parent) {
+        PersonItemView v;
+        if (convertView == null) {
+            v = instantiateView(parent);
+        } else {
+            v = (PersonItemView) convertView;
+        }
+
+        final VCardResourceEntryDestinationItem item = (VCardResourceEntryDestinationItem)
+                getChild(groupPosition, childPosition);
+
+        v.bind(item.getDisplayItem());
+        return v;
+    }
+
+    @Override
+    public int getChildrenCount(final int groupPosition) {
+        return mVCards.get(groupPosition).getContactInfo().size();
+    }
+
+    @Override
+    public Object getGroup(final int groupPosition) {
+        return mVCards.get(groupPosition);
+    }
+
+    @Override
+    public int getGroupCount() {
+        return mVCards.size();
+    }
+
+    @Override
+    public long getGroupId(final int groupPosition) {
+        return groupPosition;
+    }
+
+    @Override
+    public View getGroupView(final int groupPosition, final boolean isExpanded,
+            final View convertView, final ViewGroup parent) {
+        PersonItemView v;
+        if (convertView == null) {
+            v = instantiateView(parent);
+        } else {
+            v = (PersonItemView) convertView;
+        }
+
+        final VCardResourceEntry item = (VCardResourceEntry) getGroup(groupPosition);
+        v.bind(item.getDisplayItem());
+        return v;
+    }
+
+    @Override
+    public boolean isChildSelectable(final int groupPosition, final int childPosition) {
+        return true;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    private PersonItemView instantiateView(final ViewGroup parent) {
+        final PersonItemView v = (PersonItemView) mInflater.inflate(R.layout.people_list_item_view,
+                parent, false);
+        v.setClickable(false);
+        return v;
+    }
+}
diff --git a/src/com/android/messaging/ui/VCardDetailFragment.java b/src/com/android/messaging/ui/VCardDetailFragment.java
new file mode 100644
index 0000000..1b2b88d
--- /dev/null
+++ b/src/com/android/messaging/ui/VCardDetailFragment.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.ExpandableListView.OnChildClickListener;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.datamodel.data.VCardContactItemData;
+import com.android.messaging.datamodel.data.PersonItemData.PersonItemDataListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * A fragment that shows the content of a VCard that contains one or more contacts.
+ */
+public class VCardDetailFragment extends Fragment implements PersonItemDataListener {
+    private final Binding<VCardContactItemData> mBinding =
+            BindingBase.createBinding(this);
+    private ExpandableListView mListView;
+    private VCardDetailAdapter mAdapter;
+    private Uri mVCardUri;
+
+    /**
+     * We need to persist the VCard in the scratch directory before letting the user view it.
+     * We save this Uri locally, so that if the user cancels the action and re-perform the add
+     * to contacts action we don't have to persist it again.
+     */
+    private Uri mScratchSpaceUri;
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        Assert.notNull(mVCardUri);
+        final View view = inflater.inflate(R.layout.vcard_detail_fragment, container, false);
+        mListView = (ExpandableListView) view.findViewById(R.id.list);
+        mListView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(final View v, final int left, final int top, final int right,
+                    final int bottom, final int oldLeft, final int oldTop, final int oldRight,
+                    final int oldBottom) {
+                mListView.setIndicatorBounds(mListView.getWidth() - getResources()
+                        .getDimensionPixelSize(R.dimen.vcard_detail_group_indicator_width),
+                        mListView.getWidth());
+            }
+        });
+        mListView.setOnChildClickListener(new OnChildClickListener() {
+            @Override
+            public boolean onChildClick(ExpandableListView expandableListView, View clickedView,
+                    int groupPosition, int childPosition, long childId) {
+                if (!(clickedView instanceof PersonItemView)) {
+                    return false;
+                }
+                final Intent intent = ((PersonItemView) clickedView).getClickIntent();
+                if (intent != null) {
+                    try {
+                        startActivity(intent);
+                    } catch (ActivityNotFoundException e) {
+                        return false;
+                    }
+                    return true;
+                }
+                return false;
+            }
+        });
+        mBinding.bind(DataModel.get().createVCardContactItemData(getActivity(), mVCardUri));
+        mBinding.getData().setListener(this);
+        return view;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mBinding.isBound()) {
+            mBinding.unbind();
+        }
+        mListView.setAdapter((ExpandableListAdapter) null);
+    }
+
+    private boolean shouldShowAddToContactsItem() {
+        return mBinding.isBound() && mBinding.getData().hasValidVCard();
+    }
+
+    @Override
+    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        inflater.inflate(R.menu.vcard_detail_fragment_menu, menu);
+        final MenuItem addToContactsItem = menu.findItem(R.id.action_add_contact);
+        addToContactsItem.setVisible(shouldShowAddToContactsItem());
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_add_contact:
+                mBinding.ensureBound();
+                final Uri vCardUri = mBinding.getData().getVCardUri();
+
+                // We have to do things in the background in case we need to copy the vcard data.
+                new SafeAsyncTask<Void, Void, Uri>() {
+                    @Override
+                    protected Uri doInBackgroundTimed(final Void... params) {
+                        // We can't delete the persisted vCard file because we don't know when to
+                        // delete it, since the app that uses it (contacts, dialer) may start or
+                        // shut down at any point. Therefore, we rely on the system to clean up
+                        // the cache directory for us.
+                        return mScratchSpaceUri != null ? mScratchSpaceUri :
+                            UriUtil.persistContentToScratchSpace(vCardUri);
+                    }
+
+                    @Override
+                    protected void onPostExecute(final Uri result) {
+                        if (result != null) {
+                            mScratchSpaceUri = result;
+                            if (getActivity() != null) {
+                                MediaScratchFileProvider.addUriToDisplayNameEntry(
+                                        result, mBinding.getData().getDisplayName());
+                                UIIntents.get().launchSaveVCardToContactsActivity(getActivity(),
+                                        result);
+                            }
+                        }
+                    }
+                }.executeOnThreadPool();
+                return true;
+
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    public void setVCardUri(final Uri vCardUri) {
+        Assert.isTrue(!mBinding.isBound());
+        mVCardUri = vCardUri;
+    }
+
+    @Override
+    public void onPersonDataUpdated(final PersonItemData data) {
+        Assert.isTrue(data instanceof VCardContactItemData);
+        mBinding.ensureBound();
+        final VCardContactItemData vCardData = (VCardContactItemData) data;
+        Assert.isTrue(vCardData.hasValidVCard());
+        mAdapter = new VCardDetailAdapter(getActivity(), vCardData.getVCardResource().getVCards());
+        mListView.setAdapter(mAdapter);
+
+        // Expand the contact card if there's only one contact.
+        if (mAdapter.getGroupCount() == 1) {
+            mListView.expandGroup(0);
+        }
+        getActivity().invalidateOptionsMenu();
+    }
+
+    @Override
+    public void onPersonDataFailed(final PersonItemData data, final Exception exception) {
+        mBinding.ensureBound();
+        UiUtils.showToastAtBottom(R.string.failed_loading_vcard);
+        getActivity().finish();
+    }
+}
diff --git a/src/com/android/messaging/ui/VideoThumbnailView.java b/src/com/android/messaging/ui/VideoThumbnailView.java
new file mode 100644
index 0000000..966336e
--- /dev/null
+++ b/src/com/android/messaging/ui/VideoThumbnailView.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ImageView.ScaleType;
+import android.widget.VideoView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.datamodel.media.MessagePartVideoThumbnailRequestDescriptor;
+import com.android.messaging.datamodel.media.VideoThumbnailRequest;
+import com.android.messaging.util.Assert;
+
+/**
+ * View that encapsulates a video preview (either as a thumbnail image, or video player), and the
+ * a play button to overlay it.  Ensures that the video preview maintains the aspect ratio of the
+ * original video while trying to respect minimum width/height and constraining to the available
+ * bounds
+ */
+public class VideoThumbnailView extends FrameLayout {
+    /**
+     * When in this mode the VideoThumbnailView is a lightweight AsyncImageView with an ImageButton
+     * to play the video.  Clicking play will launch a full screen player
+     */
+    private static final int MODE_IMAGE_THUMBNAIL = 0;
+
+    /**
+     * When in this mode the VideoThumbnailVideo will include a VideoView, and the play button will
+     * play the video inline.  When in this mode, the loop and playOnLoad attributes can be applied
+     * to auto-play or loop the video.
+     */
+    private static final int MODE_PLAYABLE_VIDEO = 1;
+
+    private final int mMode;
+    private final boolean mPlayOnLoad;
+    private final boolean mAllowCrop;
+    private final VideoView mVideoView;
+    private final ImageButton mPlayButton;
+    private final AsyncImageView mThumbnailImage;
+    private int mVideoWidth;
+    private int mVideoHeight;
+    private Uri mVideoSource;
+    private boolean mAnimating;
+    private boolean mVideoLoaded;
+
+    public VideoThumbnailView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        final TypedArray typedAttributes =
+                context.obtainStyledAttributes(attrs, R.styleable.VideoThumbnailView);
+
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        inflater.inflate(R.layout.video_thumbnail_view, this, true);
+
+        mPlayOnLoad = typedAttributes.getBoolean(R.styleable.VideoThumbnailView_playOnLoad, false);
+        final boolean loop =
+                typedAttributes.getBoolean(R.styleable.VideoThumbnailView_loop, false);
+        mMode = typedAttributes.getInt(R.styleable.VideoThumbnailView_mode, MODE_IMAGE_THUMBNAIL);
+        mAllowCrop = typedAttributes.getBoolean(R.styleable.VideoThumbnailView_allowCrop, false);
+
+        mVideoWidth = ImageRequest.UNSPECIFIED_SIZE;
+        mVideoHeight = ImageRequest.UNSPECIFIED_SIZE;
+
+        if (mMode == MODE_PLAYABLE_VIDEO) {
+            mVideoView = new VideoView(context);
+            // Video view tries to request focus on start which pulls focus from the user's intended
+            // focus when we add this control.  Remove focusability to prevent this.  The play
+            // button can still be focused
+            mVideoView.setFocusable(false);
+            mVideoView.setFocusableInTouchMode(false);
+            mVideoView.clearFocus();
+            addView(mVideoView, 0, new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+            mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+                @Override
+                public void onPrepared(final MediaPlayer mediaPlayer) {
+                    mVideoLoaded = true;
+                    mVideoWidth = mediaPlayer.getVideoWidth();
+                    mVideoHeight = mediaPlayer.getVideoHeight();
+                    mediaPlayer.setLooping(loop);
+                    trySwitchToVideo();
+                }
+            });
+            mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(final MediaPlayer mediaPlayer) {
+                    mPlayButton.setVisibility(View.VISIBLE);
+                }
+            });
+            mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(final MediaPlayer mediaPlayer, final int i, final int i2) {
+                    return true;
+                }
+            });
+        } else {
+            mVideoView = null;
+        }
+
+        mPlayButton = (ImageButton) findViewById(R.id.video_thumbnail_play_button);
+        if (loop) {
+            mPlayButton.setVisibility(View.GONE);
+        } else {
+            mPlayButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(final View view) {
+                    if (mVideoSource == null) {
+                        return;
+                    }
+
+                    if (mMode == MODE_PLAYABLE_VIDEO) {
+                        mVideoView.seekTo(0);
+                        start();
+                    } else {
+                        UIIntents.get().launchFullScreenVideoViewer(getContext(), mVideoSource);
+                    }
+                }
+            });
+            mPlayButton.setOnLongClickListener(new OnLongClickListener() {
+                @Override
+                public boolean onLongClick(final View view) {
+                    // Button prevents long click from propagating up, do it manually
+                    VideoThumbnailView.this.performLongClick();
+                    return true;
+                }
+            });
+        }
+
+        mThumbnailImage = (AsyncImageView) findViewById(R.id.video_thumbnail_image);
+        if (mAllowCrop) {
+            mThumbnailImage.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
+            mThumbnailImage.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+            mThumbnailImage.setScaleType(ScaleType.CENTER_CROP);
+        } else {
+            // This is the default setting in the layout, so No-op.
+        }
+        final int maxHeight = typedAttributes.getDimensionPixelSize(
+                R.styleable.VideoThumbnailView_android_maxHeight, ImageRequest.UNSPECIFIED_SIZE);
+        if (maxHeight != ImageRequest.UNSPECIFIED_SIZE) {
+            mThumbnailImage.setMaxHeight(maxHeight);
+            mThumbnailImage.setAdjustViewBounds(true);
+        }
+
+        typedAttributes.recycle();
+    }
+
+    @Override
+    protected void onAnimationStart() {
+        super.onAnimationStart();
+        mAnimating = true;
+    }
+
+    @Override
+    protected void onAnimationEnd() {
+        super.onAnimationEnd();
+        mAnimating = false;
+        trySwitchToVideo();
+    }
+
+    private void trySwitchToVideo() {
+        if (mAnimating) {
+            // Don't start video or hide image until after animation completes
+            return;
+        }
+
+        if (!mVideoLoaded) {
+            // Video hasn't loaded, nothing more to do
+            return;
+        }
+
+        if (mPlayOnLoad) {
+            start();
+        } else {
+            mVideoView.seekTo(0);
+        }
+    }
+
+    private boolean hasVideoSize() {
+        return mVideoWidth != ImageRequest.UNSPECIFIED_SIZE &&
+                mVideoHeight != ImageRequest.UNSPECIFIED_SIZE;
+    }
+
+    public void start() {
+        Assert.equals(MODE_PLAYABLE_VIDEO, mMode);
+        mPlayButton.setVisibility(View.GONE);
+        mThumbnailImage.setVisibility(View.GONE);
+        mVideoView.start();
+    }
+
+    // TODO: The check could be added to MessagePartData itself so that all users of MessagePartData
+    // get the right behavior, instead of requiring all the users to do similar checks.
+    private static boolean shouldUseGenericVideoIcon(final boolean incomingMessage) {
+        return incomingMessage && !VideoThumbnailRequest.shouldShowIncomingVideoThumbnails();
+    }
+
+    public void setSource(final MessagePartData part, final boolean incomingMessage) {
+        if (part == null) {
+            clearSource();
+        } else {
+            mVideoSource = part.getContentUri();
+            if (shouldUseGenericVideoIcon(incomingMessage)) {
+                mThumbnailImage.setImageResource(R.drawable.generic_video_icon);
+                mVideoWidth = ImageRequest.UNSPECIFIED_SIZE;
+                mVideoHeight = ImageRequest.UNSPECIFIED_SIZE;
+            } else {
+                mThumbnailImage.setImageResourceId(
+                        new MessagePartVideoThumbnailRequestDescriptor(part));
+                if (mVideoView != null) {
+                    mVideoView.setVideoURI(mVideoSource);
+                }
+                mVideoWidth = part.getWidth();
+                mVideoHeight = part.getHeight();
+            }
+        }
+    }
+
+    public void setSource(final Uri videoSource, final boolean incomingMessage) {
+        if (videoSource == null) {
+            clearSource();
+        } else {
+            mVideoSource = videoSource;
+            if (shouldUseGenericVideoIcon(incomingMessage)) {
+                mThumbnailImage.setImageResource(R.drawable.generic_video_icon);
+                mVideoWidth = ImageRequest.UNSPECIFIED_SIZE;
+                mVideoHeight = ImageRequest.UNSPECIFIED_SIZE;
+            } else {
+                mThumbnailImage.setImageResourceId(
+                        new MessagePartVideoThumbnailRequestDescriptor(videoSource));
+                if (mVideoView != null) {
+                    mVideoView.setVideoURI(videoSource);
+                }
+            }
+        }
+    }
+
+    private void clearSource() {
+        mVideoSource = null;
+        mThumbnailImage.setImageResourceId(null);
+        mVideoWidth = ImageRequest.UNSPECIFIED_SIZE;
+        mVideoHeight = ImageRequest.UNSPECIFIED_SIZE;
+        if (mVideoView != null) {
+            mVideoView.setVideoURI(null);
+        }
+    }
+
+    @Override
+    public void setMinimumWidth(final int minWidth) {
+        super.setMinimumWidth(minWidth);
+        if (mVideoView != null) {
+            mVideoView.setMinimumWidth(minWidth);
+        }
+    }
+
+    @Override
+    public void setMinimumHeight(final int minHeight) {
+        super.setMinimumHeight(minHeight);
+        if (mVideoView != null) {
+            mVideoView.setMinimumHeight(minHeight);
+        }
+    }
+
+    public void setColorFilter(int color) {
+        mThumbnailImage.setColorFilter(color);
+        mPlayButton.setColorFilter(color);
+    }
+
+    public void clearColorFilter() {
+        mThumbnailImage.clearColorFilter();
+        mPlayButton.clearColorFilter();
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        if (mAllowCrop) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+        int desiredWidth = 1;
+        int desiredHeight = 1;
+        if (mVideoView != null) {
+            mVideoView.measure(widthMeasureSpec, heightMeasureSpec);
+        }
+        mThumbnailImage.measure(widthMeasureSpec, heightMeasureSpec);
+        if (hasVideoSize()) {
+            desiredWidth = mVideoWidth;
+            desiredHeight = mVideoHeight;
+        } else {
+            desiredWidth = mThumbnailImage.getMeasuredWidth();
+            desiredHeight = mThumbnailImage.getMeasuredHeight();
+        }
+
+        final int minimumWidth = getMinimumWidth();
+        final int minimumHeight = getMinimumHeight();
+
+        // Constrain the scale to fit within the supplied size
+        final float maxScale = Math.max(
+                MeasureSpec.getSize(widthMeasureSpec) / (float) desiredWidth,
+                MeasureSpec.getSize(heightMeasureSpec) / (float) desiredHeight);
+
+        // Scale up to reach minimum width/height
+        final float widthScale = Math.max(1, minimumWidth / (float) desiredWidth);
+        final float heightScale = Math.max(1, minimumHeight / (float) desiredHeight);
+        final float scale = Math.min(maxScale, Math.max(widthScale, heightScale));
+        desiredWidth = (int) (desiredWidth * scale);
+        desiredHeight = (int) (desiredHeight * scale);
+
+        setMeasuredDimension(desiredWidth, desiredHeight);
+    }
+
+    @Override
+    protected void onLayout(final boolean changed, final int left, final int top, final int right,
+            final int bottom) {
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.layout(0, 0, right - left, bottom - top);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/ViewPagerTabStrip.java b/src/com/android/messaging/ui/ViewPagerTabStrip.java
new file mode 100644
index 0000000..e088296
--- /dev/null
+++ b/src/com/android/messaging/ui/ViewPagerTabStrip.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.util.OsUtil;
+
+public class ViewPagerTabStrip extends LinearLayout {
+    private int mSelectedUnderlineThickness;
+    private final Paint mSelectedUnderlinePaint;
+
+    private int mIndexForSelection;
+    private float mSelectionOffset;
+
+    public ViewPagerTabStrip(Context context) {
+        this(context, null);
+    }
+
+    public ViewPagerTabStrip(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        final Resources res = context.getResources();
+
+        mSelectedUnderlineThickness =
+                res.getDimensionPixelSize(R.dimen.pager_tab_underline_selected);
+        int underlineColor = res.getColor(R.color.contact_picker_tab_underline);
+        int backgroundColor = res.getColor(R.color.action_bar_background_color);
+
+        mSelectedUnderlinePaint = new Paint();
+        mSelectedUnderlinePaint.setColor(underlineColor);
+
+        setBackgroundColor(backgroundColor);
+        setWillNotDraw(false);
+    }
+
+    /**
+     * Notifies this view that view pager has been scrolled. We save the tab index
+     * and selection offset for interpolating the position and width of selection
+     * underline.
+     */
+    void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        mIndexForSelection = position;
+        mSelectionOffset = positionOffset;
+        invalidate();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        int childCount = getChildCount();
+
+        // Thick colored underline below the current selection
+        if (childCount > 0) {
+            View selectedTitle = getChildAt(mIndexForSelection);
+            int selectedLeft = selectedTitle.getLeft();
+            int selectedRight = selectedTitle.getRight();
+            final boolean isRtl = isRtl();
+            final boolean hasNextTab = isRtl ? mIndexForSelection > 0
+                    : (mIndexForSelection < (getChildCount() - 1));
+            if ((mSelectionOffset > 0.0f) && hasNextTab) {
+                // Draw the selection partway between the tabs
+                View nextTitle = getChildAt(mIndexForSelection + (isRtl ? -1 : 1));
+                int nextLeft = nextTitle.getLeft();
+                int nextRight = nextTitle.getRight();
+
+                selectedLeft = (int) (mSelectionOffset * nextLeft +
+                        (1.0f - mSelectionOffset) * selectedLeft);
+                selectedRight = (int) (mSelectionOffset * nextRight +
+                        (1.0f - mSelectionOffset) * selectedRight);
+            }
+
+            int height = getHeight();
+            canvas.drawRect(selectedLeft, height - mSelectedUnderlineThickness,
+                    selectedRight, height, mSelectedUnderlinePaint);
+        }
+    }
+
+    private boolean isRtl() {
+        return OsUtil.isAtLeastJB_MR2() ? getLayoutDirection() == View.LAYOUT_DIRECTION_RTL : false;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/ViewPagerTabs.java b/src/com/android/messaging/ui/ViewPagerTabs.java
new file mode 100644
index 0000000..bb4aaaf
--- /dev/null
+++ b/src/com/android/messaging/ui/ViewPagerTabs.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Outline;
+import android.graphics.drawable.ColorDrawable;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Lightweight implementation of ViewPager tabs. This looks similar to traditional actionBar tabs,
+ * but allows for the view containing the tabs to be placed anywhere on screen. Text-related
+ * attributes can also be assigned in XML - these will get propogated to the child TextViews
+ * automatically.
+ *
+ * Note: this file is taken from the AOSP /packages/apps/ContactsCommon/src/com/android/contacts/
+ * common/list/ViewPagerTabs.java. Some platform specific API calls (e.g. ViewOutlineProvider which
+ * assumes L and above) have been modified to support down to Api Level 16.
+ */
+public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnPageChangeListener {
+
+    ViewPager mPager;
+    private ViewPagerTabStrip mTabStrip;
+
+    /**
+     * Linearlayout that will contain the TextViews serving as tabs. This is the only child
+     * of the parent HorizontalScrollView.
+     */
+    final int mTextStyle;
+    final ColorStateList mTextColor;
+    final int mTextSize;
+    final boolean mTextAllCaps;
+    int mPrevSelected = -1;
+    int mSidePadding;
+
+    private static final int TAB_SIDE_PADDING_IN_DPS = 10;
+
+    // TODO: This should use <declare-styleable> in the future
+    private static final int[] ATTRS = new int[] {
+        android.R.attr.textSize,
+        android.R.attr.textStyle,
+        android.R.attr.textColor,
+        android.R.attr.textAllCaps
+    };
+
+    /**
+     * Shows a toast with the tab description when long-clicked.
+     */
+    private class OnTabLongClickListener implements OnLongClickListener {
+        final String mTabDescription;
+
+        public OnTabLongClickListener(String tabDescription) {
+            mTabDescription = tabDescription;
+        }
+
+        @Override
+        public boolean onLongClick(View v) {
+            final int[] screenPos = new int[2];
+            getLocationOnScreen(screenPos);
+
+            final Context context = getContext();
+            final int width = getWidth();
+            final int height = getHeight();
+            final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+
+            Toast toast = Toast.makeText(context, mTabDescription, Toast.LENGTH_SHORT);
+
+            // Show the toast under the tab
+            toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
+                    (screenPos[0] + width / 2) - screenWidth / 2, screenPos[1] + height);
+
+            toast.show();
+            return true;
+        }
+    }
+
+    public ViewPagerTabs(Context context) {
+        this(context, null);
+    }
+
+    public ViewPagerTabs(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ViewPagerTabs(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        setFillViewport(true);
+
+        mSidePadding = (int) (getResources().getDisplayMetrics().density * TAB_SIDE_PADDING_IN_DPS);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
+        mTextSize = a.getDimensionPixelSize(0, 0);
+        mTextStyle = a.getInt(1, 0);
+        mTextColor = a.getColorStateList(2);
+        mTextAllCaps = a.getBoolean(3, false);
+
+        mTabStrip = new ViewPagerTabStrip(context);
+        addView(mTabStrip,
+                new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
+        a.recycle();
+
+        // enable shadow casting from view bounds
+        if (OsUtil.isAtLeastL()) {
+            setOutlineProvider(new ViewOutlineProvider() {
+                @Override
+                public void getOutline(View view, Outline outline) {
+                    outline.setRect(0, 0, view.getWidth(), view.getHeight());
+                }
+            });
+        }
+    }
+
+    public void setViewPager(ViewPager viewPager) {
+        mPager = viewPager;
+        addTabs(mPager.getAdapter());
+    }
+
+    private void addTabs(PagerAdapter adapter) {
+        mTabStrip.removeAllViews();
+
+        final int count = adapter.getCount();
+        for (int i = 0; i < count; i++) {
+            addTab(adapter.getPageTitle(i), i);
+        }
+    }
+
+    private void addTab(CharSequence tabTitle, final int position) {
+        final TextView textView = new TextView(getContext());
+        textView.setText(tabTitle);
+        textView.setBackgroundResource(R.drawable.contact_picker_tab_background_selector);
+        textView.setGravity(Gravity.CENTER);
+        textView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mPager.setCurrentItem(getRtlPosition(position));
+            }
+        });
+
+        // Assign various text appearance related attributes to child views.
+        if (mTextStyle > 0) {
+            textView.setTypeface(textView.getTypeface(), mTextStyle);
+        }
+        if (mTextSize > 0) {
+            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
+        }
+        if (mTextColor != null) {
+            textView.setTextColor(mTextColor);
+        }
+        textView.setAllCaps(mTextAllCaps);
+        textView.setPadding(mSidePadding, 0, mSidePadding, 0);
+        mTabStrip.addView(textView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
+                LayoutParams.MATCH_PARENT, 1));
+        // Default to the first child being selected
+        if (position == 0) {
+            mPrevSelected = 0;
+            textView.setSelected(true);
+        }
+    }
+
+    @Override
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        position = getRtlPosition(position);
+        int tabStripChildCount = mTabStrip.getChildCount();
+        if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
+            return;
+        }
+
+        mTabStrip.onPageScrolled(position, positionOffset, positionOffsetPixels);
+    }
+
+    @Override
+    public void onPageSelected(int position) {
+        position = getRtlPosition(position);
+        int tabStripChildCount = mTabStrip.getChildCount();
+        if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
+            return;
+        }
+
+        if (mPrevSelected >= 0 && mPrevSelected < tabStripChildCount) {
+            mTabStrip.getChildAt(mPrevSelected).setSelected(false);
+        }
+        final View selectedChild = mTabStrip.getChildAt(position);
+        selectedChild.setSelected(true);
+
+        // Update scroll position
+        final int scrollPos = selectedChild.getLeft() - (getWidth() - selectedChild.getWidth()) / 2;
+        smoothScrollTo(scrollPos, 0);
+        mPrevSelected = position;
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int state) {
+    }
+
+    private int getRtlPosition(int position) {
+        if (OsUtil.isAtLeastJB_MR2() && Factory.get().getApplicationContext().getResources()
+                .getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+            return mTabStrip.getChildCount() - 1 - position;
+        }
+        return position;
+    }
+
+    public int getSelectedItemPosition() {
+        return mPrevSelected;
+    }
+}
diff --git a/src/com/android/messaging/ui/WidgetPickConversationActivity.java b/src/com/android/messaging/ui/WidgetPickConversationActivity.java
new file mode 100644
index 0000000..60e1318
--- /dev/null
+++ b/src/com/android/messaging/ui/WidgetPickConversationActivity.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.appwidget.AppWidgetManager;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.ui.conversationlist.ShareIntentFragment;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.widget.WidgetConversationProvider;
+
+public class WidgetPickConversationActivity extends BaseBugleActivity implements
+        ShareIntentFragment.HostInterface {
+
+    private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+
+        // Set the result to CANCELED.  This will cause the widget host to cancel
+        // out of the widget placement if they press the back button.
+        setResult(RESULT_CANCELED);
+
+        // Find the widget id from the intent.
+        final Intent intent = getIntent();
+        final Bundle extras = intent.getExtras();
+        if (extras != null) {
+            mAppWidgetId = extras.getInt(
+                    AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
+        }
+
+        // If they gave us an intent without the widget id, just bail.
+        if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
+            finish();
+        }
+
+        final ShareIntentFragment convPicker = new ShareIntentFragment();
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(ShareIntentFragment.HIDE_NEW_CONVERSATION_BUTTON_KEY, true);
+        convPicker.setArguments(bundle);
+        convPicker.show(getFragmentManager(), "ShareIntentFragment");
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        final Intent intent = getIntent();
+        final String action = intent.getAction();
+        if (!AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)) {
+            // Unsupported action.
+            Assert.fail("Unsupported action type: " + action);
+        }
+    }
+
+    @Override
+    public void onConversationClick(final ConversationListItemData conversationListItemData) {
+        saveConversationidPref(mAppWidgetId, conversationListItemData.getConversationId());
+
+        // Push widget update to surface with newly set prefix
+        WidgetConversationProvider.rebuildWidget(this, mAppWidgetId);
+
+        // Make sure we pass back the original appWidgetId
+        Intent resultValue = new Intent();
+        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
+        setResult(RESULT_OK, resultValue);
+        finish();
+    }
+
+    @Override
+    public void onCreateConversationClick() {
+        // We should never get here because we're hiding the new conversation button in the
+        // ShareIntentFragment by setting HIDE_NEW_CONVERSATION_BUTTON_KEY in the arguments.
+        finish();
+    }
+
+    // Write the ConversationId to the SharedPreferences object for this widget
+    static void saveConversationidPref(int appWidgetId, String conversationId) {
+        final BuglePrefs prefs = Factory.get().getWidgetPrefs();
+        prefs.putString(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID + appWidgetId, conversationId);
+    }
+
+    // Read the ConversationId from the SharedPreferences object for this widget.
+    public static String getConversationIdPref(int appWidgetId) {
+        final BuglePrefs prefs = Factory.get().getWidgetPrefs();
+        return prefs.getString(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID + appWidgetId, null);
+    }
+
+    // Delete the ConversationId preference from the SharedPreferences object for this widget.
+    public static void deleteConversationIdPref(int appWidgetId) {
+        final BuglePrefs prefs = Factory.get().getWidgetPrefs();
+        prefs.remove(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID + appWidgetId);
+    }
+
+}
diff --git a/src/com/android/messaging/ui/animation/PopupTransitionAnimation.java b/src/com/android/messaging/ui/animation/PopupTransitionAnimation.java
new file mode 100644
index 0000000..e14d16e
--- /dev/null
+++ b/src/com/android/messaging/ui/animation/PopupTransitionAnimation.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.animation;
+
+import android.animation.TypeEvaluator;
+import android.app.Activity;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.widget.PopupWindow;
+
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.ThreadUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Animates viewToAnimate from startRect to the place where it is in the layout,  viewToAnimate
+ * should be in its final destination location before startAfterLayoutComplete is called.
+ * viewToAnimate will be drawn scaled and offset in a popupWindow.
+ * This class handles the case where the viewToAnimate moves during the animation
+ */
+public class PopupTransitionAnimation extends Animation {
+    /** The view we're animating */
+    private final View mViewToAnimate;
+
+    /** The rect to start the slide in animation from */
+    private final Rect mStartRect;
+
+    /** The rect of the currently animated view */
+    private Rect mCurrentRect;
+
+    /** The rect that we're animating to.  This can change during the animation */
+    private final Rect mDestRect;
+
+    /** The bounds of the popup in window coordinates.  Does not include notification bar */
+    private final Rect mPopupRect;
+
+    /** The bounds of the action bar in window coordinates.  We clip the popup to below this */
+    private final Rect mActionBarRect;
+
+    /** Interpolates between the start and end rect for every animation tick */
+    private final TypeEvaluator<Rect> mRectEvaluator;
+
+    /** The popup window that holds contains the animating view */
+    private PopupWindow mPopupWindow;
+
+    /** The layout root for the popup which is where the animated view is rendered */
+    private View mPopupRoot;
+
+    /** The action bar's view */
+    private final View mActionBarView;
+
+    private Runnable mOnStartCallback;
+    private Runnable mOnStopCallback;
+
+    public PopupTransitionAnimation(final Rect startRect, final View viewToAnimate) {
+        mViewToAnimate = viewToAnimate;
+        mStartRect = startRect;
+        mCurrentRect = new Rect(mStartRect);
+        mDestRect = new Rect();
+        mPopupRect = new Rect();
+        mActionBarRect = new Rect();
+        mActionBarView = viewToAnimate.getRootView().findViewById(
+                androidx.appcompat.R.id.action_bar);
+        mRectEvaluator = RectEvaluatorCompat.create();
+        setDuration(UiUtils.MEDIAPICKER_TRANSITION_DURATION);
+        setInterpolator(UiUtils.DEFAULT_INTERPOLATOR);
+        setAnimationListener(new AnimationListener() {
+            @Override
+            public void onAnimationStart(final Animation animation) {
+                if (mOnStartCallback != null) {
+                    mOnStartCallback.run();
+                }
+                mEvents.append("oAS,");
+            }
+
+            @Override
+            public void onAnimationEnd(final Animation animation) {
+                if (mOnStopCallback != null) {
+                    mOnStopCallback.run();
+                }
+                dismiss();
+                mEvents.append("oAE,");
+            }
+
+            @Override
+            public void onAnimationRepeat(final Animation animation) {
+            }
+        });
+    }
+
+    private final StringBuilder mEvents = new StringBuilder();
+    private final Runnable mCleanupRunnable = new Runnable() {
+        @Override
+        public void run() {
+            LogUtil.w(LogUtil.BUGLE_TAG, "PopupTransitionAnimation: " + mEvents);
+        }
+    };
+
+    /**
+     * Ensures the animation is ready before starting the animation.
+     * viewToAnimate must first be layed out so we know where we will animate to
+     */
+    public void startAfterLayoutComplete() {
+        // We want layout to occur, and then we immediately animate it in, so hide it initially to
+        // reduce jank on the first frame
+        mViewToAnimate.setVisibility(View.INVISIBLE);
+        mViewToAnimate.setAlpha(0);
+
+        final Runnable startAnimation = new Runnable() {
+            boolean mRunComplete = false;
+            boolean mFirstTry = true;
+
+            @Override
+            public void run() {
+                if (mRunComplete) {
+                    return;
+                }
+
+                mViewToAnimate.getGlobalVisibleRect(mDestRect);
+                // In Android views which are visible but haven't computed their size yet have a
+                // size of 1x1 because anything with a size of 0x0 is considered hidden.  We can't
+                // start the animation until after the size is greater than 1x1
+                if (mDestRect.width() <= 1 || mDestRect.height() <= 1) {
+                    // Layout hasn't occurred yet
+                    if (!mFirstTry) {
+                        // Give up if this is not the first try, since layout change still doesn't
+                        // yield a size for the view. This is likely because the media picker is
+                        // full screen so there's no space left for the animated view. We give up
+                        // on animation, but need to make sure the view that was initially
+                        // hidden is re-shown.
+                        mViewToAnimate.setAlpha(1);
+                        mViewToAnimate.setVisibility(View.VISIBLE);
+                    } else {
+                        mFirstTry = false;
+                        UiUtils.doOnceAfterLayoutChange(mViewToAnimate, this);
+                    }
+                    return;
+                }
+
+                mRunComplete = true;
+                mViewToAnimate.startAnimation(PopupTransitionAnimation.this);
+                mViewToAnimate.invalidate();
+                // http://b/20856505: The PopupWindow sometimes does not get dismissed.
+                ThreadUtil.getMainThreadHandler().postDelayed(mCleanupRunnable, getDuration() * 2);
+            }
+        };
+
+        startAnimation.run();
+    }
+
+    public PopupTransitionAnimation setOnStartCallback(final Runnable onStart) {
+        mOnStartCallback = onStart;
+        return this;
+    }
+
+    public PopupTransitionAnimation setOnStopCallback(final Runnable onStop) {
+        mOnStopCallback = onStop;
+        return this;
+    }
+
+    @Override
+    protected void applyTransformation(final float interpolatedTime, final Transformation t) {
+        if (mPopupWindow == null) {
+            initPopupWindow();
+        }
+        // Update mDestRect as it may have moved during the animation
+        mPopupRect.set(UiUtils.getMeasuredBoundsOnScreen(mPopupRoot));
+        mActionBarRect.set(UiUtils.getMeasuredBoundsOnScreen(mActionBarView));
+        computeDestRect();
+
+        // Update currentRect to the new animated coordinates, and request mPopupRoot to redraw
+        // itself at the new coordinates
+        mCurrentRect = mRectEvaluator.evaluate(interpolatedTime, mStartRect, mDestRect);
+        mPopupRoot.invalidate();
+
+        if (interpolatedTime >= 0.98) {
+            mEvents.append("aT").append(interpolatedTime).append(',');
+        }
+        if (interpolatedTime == 1) {
+            dismiss();
+        }
+    }
+
+    private void dismiss() {
+        mEvents.append("d,");
+        mViewToAnimate.setAlpha(1);
+        mViewToAnimate.setVisibility(View.VISIBLE);
+        // Delay dismissing the popup window to let mViewToAnimate draw under it and reduce the
+        // flash
+        ThreadUtil.getMainThreadHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mPopupWindow.dismiss();
+                } catch (IllegalArgumentException e) {
+                    // PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
+                    // has already ended while we were animating
+                }
+                ThreadUtil.getMainThreadHandler().removeCallbacks(mCleanupRunnable);
+            }
+        });
+    }
+
+    @Override
+    public boolean willChangeBounds() {
+        return false;
+    }
+
+    /**
+     * Computes mDestRect (the position in window space of the placeholder view that we should
+     * animate to).  Some frames during the animation fail to compute getGlobalVisibleRect, so use
+     * the last known values in that case
+     */
+    private void computeDestRect() {
+        final int prevTop = mDestRect.top;
+        final int prevLeft = mDestRect.left;
+        final int prevRight = mDestRect.right;
+        final int prevBottom = mDestRect.bottom;
+
+        if (!getViewScreenMeasureRect(mViewToAnimate, mDestRect)) {
+            mDestRect.top = prevTop;
+            mDestRect.left = prevLeft;
+            mDestRect.bottom = prevBottom;
+            mDestRect.right = prevRight;
+        }
+    }
+
+    /**
+     * Sets up the PopupWindow that the view will animate in.  Animating the size and position of a
+     * popup can be choppy, so instead we make the popup fill the entire space of the screen, and
+     * animate the position of viewToAnimate within the popup using a Transformation
+     */
+    private void initPopupWindow() {
+        mPopupRoot = new View(mViewToAnimate.getContext()) {
+            @Override
+            protected void onDraw(final Canvas canvas) {
+                canvas.save();
+                canvas.clipRect(getLeft(), mActionBarRect.bottom - mPopupRect.top, getRight(),
+                        getBottom());
+                canvas.drawColor(Color.TRANSPARENT);
+                final float previousAlpha = mViewToAnimate.getAlpha();
+                mViewToAnimate.setAlpha(1);
+                // The view's global position includes the notification bar height, but
+                // the popup window may or may not cover the notification bar (depending on screen
+                // rotation, IME status etc.), so we need to compensate for this difference by
+                // offseting vertically.
+                canvas.translate(mCurrentRect.left, mCurrentRect.top - mPopupRect.top);
+
+                final float viewWidth = mViewToAnimate.getWidth();
+                final float viewHeight = mViewToAnimate.getHeight();
+                if (viewWidth > 0 && viewHeight > 0) {
+                    canvas.scale(mCurrentRect.width() / viewWidth,
+                            mCurrentRect.height() / viewHeight);
+                }
+                canvas.clipRect(0, 0, mCurrentRect.width(), mCurrentRect.height());
+                if (!mPopupRect.isEmpty()) {
+                    // HACK: Layout is unstable until mPopupRect is non-empty.
+                    mViewToAnimate.draw(canvas);
+                }
+                mViewToAnimate.setAlpha(previousAlpha);
+                canvas.restore();
+            }
+        };
+        mPopupWindow = new PopupWindow(mViewToAnimate.getContext());
+        mPopupWindow.setBackgroundDrawable(null);
+        mPopupWindow.setContentView(mPopupRoot);
+        mPopupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
+        mPopupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
+        mPopupWindow.setTouchable(false);
+        // We must pass a non-zero value for the y offset, or else the system resets the status bar
+        // color to black (M only) during the animation. The actual position of the window (and
+        // the animated view inside it) are still correct, regardless of what we pass for the y
+        // parameter (e.g. 1 and 100 both work). Not entirely sure why this works.
+        mPopupWindow.showAtLocation(mViewToAnimate, Gravity.TOP, 0, 1);
+    }
+
+    private static boolean getViewScreenMeasureRect(final View view, final Rect outRect) {
+        outRect.set(UiUtils.getMeasuredBoundsOnScreen(view));
+        return !outRect.isEmpty();
+    }
+}
diff --git a/src/com/android/messaging/ui/animation/RectEvaluatorCompat.java b/src/com/android/messaging/ui/animation/RectEvaluatorCompat.java
new file mode 100644
index 0000000..e3c60fc
--- /dev/null
+++ b/src/com/android/messaging/ui/animation/RectEvaluatorCompat.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.animation;
+
+import android.animation.RectEvaluator;
+import android.animation.TypeEvaluator;
+import android.graphics.Rect;
+
+import com.android.messaging.util.OsUtil;
+
+/**
+ * This evaluator can be used to perform type interpolation between <code>Rect</code> values.
+ * It's backward compatible to Api Level 11.
+ */
+public class RectEvaluatorCompat implements TypeEvaluator<Rect> {
+    public static TypeEvaluator<Rect> create() {
+        if (OsUtil.isAtLeastJB_MR2()) {
+            return new RectEvaluator();
+        } else {
+            return new RectEvaluatorCompat();
+        }
+    }
+
+    @Override
+    public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
+        int left = startValue.left + (int) ((endValue.left - startValue.left) * fraction);
+        int top = startValue.top + (int) ((endValue.top - startValue.top) * fraction);
+        int right = startValue.right + (int) ((endValue.right - startValue.right) * fraction);
+        int bottom = startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction);
+        return new Rect(left, top, right, bottom);
+    }
+}
diff --git a/src/com/android/messaging/ui/animation/ViewGroupItemVerticalExplodeAnimation.java b/src/com/android/messaging/ui/animation/ViewGroupItemVerticalExplodeAnimation.java
new file mode 100644
index 0000000..7dc41fb
--- /dev/null
+++ b/src/com/android/messaging/ui/animation/ViewGroupItemVerticalExplodeAnimation.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.animation;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import androidx.core.view.ViewCompat;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
+import android.view.ViewOverlay;
+import android.widget.FrameLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * <p>
+ * Shows a vertical "explode" animation for any view inside a view group (e.g. views inside a
+ * ListView). During the animation, a snapshot is taken for the view to the animated and
+ * presented in a popup window or view overlay on top of the original view group. The background
+ * of the view (a highlight) vertically expands (explodes) during the animation.
+ * </p>
+ * <p>
+ * The exact implementation of the animation depends on platform API level. For JB_MR2 and later,
+ * the implementation utilizes ViewOverlay to perform highly performant overlay animations; for
+ * older API levels, the implementation falls back to using a full screen popup window to stage
+ * the animation.
+ * </p>
+ * <p>
+ * To start this animation, call {@link #startAnimationForView(ViewGroup, View, View, boolean, int)}
+ * </p>
+ */
+public class ViewGroupItemVerticalExplodeAnimation {
+    /**
+     * Starts a vertical explode animation for a given view situated in a given container.
+     *
+     * @param container the container of the view which determines the explode animation's final
+     *        size
+     * @param viewToAnimate the view to be animated. The view will be highlighted by the explode
+     *        highlight, which expands from the size of the view to the size of the container.
+     * @param animationStagingView the view that stages the animation. Since viewToAnimate may be
+     *        removed from the view tree during the animation, we need a view that'll be alive
+     *        for the duration of the animation so that the animation won't get cancelled.
+     * @param snapshotView whether a snapshot of the view to animate is needed.
+     */
+    public static void startAnimationForView(final ViewGroup container, final View viewToAnimate,
+            final View animationStagingView, final boolean snapshotView, final int duration) {
+        if (OsUtil.isAtLeastJB_MR2() && (viewToAnimate.getContext() instanceof Activity)) {
+            new ViewExplodeAnimationJellyBeanMR2(viewToAnimate, container, snapshotView, duration)
+                .startAnimation();
+        } else {
+            // Pre JB_MR2, this animation can cause rendering failures which causes the framework
+            // to fall back to software rendering where camera preview isn't supported (b/18264647)
+            // just skip the animation to avoid this case.
+        }
+    }
+
+    /**
+     * Implementation class for API level >= 18.
+     */
+    @TargetApi(18)
+    private static class ViewExplodeAnimationJellyBeanMR2 {
+        private final View mViewToAnimate;
+        private final ViewGroup mContainer;
+        private final View mSnapshot;
+        private final Bitmap mViewBitmap;
+        private final int mDuration;
+
+        public ViewExplodeAnimationJellyBeanMR2(final View viewToAnimate, final ViewGroup container,
+                final boolean snapshotView, final int duration) {
+            mViewToAnimate = viewToAnimate;
+            mContainer = container;
+            mDuration = duration;
+            if (snapshotView) {
+                mViewBitmap = snapshotView(viewToAnimate);
+                mSnapshot = new View(viewToAnimate.getContext());
+            } else {
+                mSnapshot = null;
+                mViewBitmap = null;
+            }
+        }
+
+        public void startAnimation() {
+            final Context context = mViewToAnimate.getContext();
+            final Resources resources = context.getResources();
+            final View decorView = ((Activity) context).getWindow().getDecorView();
+            final ViewOverlay viewOverlay = decorView.getOverlay();
+            if (viewOverlay instanceof ViewGroupOverlay) {
+                final ViewGroupOverlay overlay = (ViewGroupOverlay) viewOverlay;
+
+                // Add a shadow layer to the overlay.
+                final FrameLayout shadowContainerLayer = new FrameLayout(context);
+                final Drawable oldBackground = mViewToAnimate.getBackground();
+                final Rect containerRect = UiUtils.getMeasuredBoundsOnScreen(mContainer);
+                final Rect decorRect = UiUtils.getMeasuredBoundsOnScreen(decorView);
+                // Position the container rect relative to the decor rect since the decor rect
+                // defines whether the view overlay will be positioned.
+                containerRect.offset(-decorRect.left, -decorRect.top);
+                shadowContainerLayer.setLeft(containerRect.left);
+                shadowContainerLayer.setTop(containerRect.top);
+                shadowContainerLayer.setBottom(containerRect.bottom);
+                shadowContainerLayer.setRight(containerRect.right);
+                shadowContainerLayer.setBackgroundColor(resources.getColor(
+                        R.color.open_conversation_animation_background_shadow));
+                // Per design request, temporarily clear out the background of the item content
+                // to not show any ripple effects during animation.
+                if (!(oldBackground instanceof ColorDrawable)) {
+                    mViewToAnimate.setBackground(null);
+                }
+                overlay.add(shadowContainerLayer);
+
+                // Add a expand layer and position it with in the shadow background, so it can
+                // be properly clipped to the container bounds during the animation.
+                final View expandLayer = new View(context);
+                final int elevation = resources.getDimensionPixelSize(
+                        R.dimen.explode_animation_highlight_elevation);
+                final Rect viewRect = UiUtils.getMeasuredBoundsOnScreen(mViewToAnimate);
+                // Frame viewRect from screen space to containerRect space.
+                viewRect.offset(-containerRect.left - decorRect.left,
+                        -containerRect.top - decorRect.top);
+                // Since the expand layer expands at the same rate above and below, we need to
+                // compute the expand scale using the bigger of the top/bottom distances.
+                final int expandLayerHalfHeight = viewRect.height() / 2;
+                final int topDist = viewRect.top;
+                final int bottomDist = containerRect.height() - viewRect.bottom;
+                final float scale = expandLayerHalfHeight == 0 ? 1 :
+                        ((float) Math.max(topDist, bottomDist) + expandLayerHalfHeight) /
+                        expandLayerHalfHeight;
+                // Position the expand layer initially to exactly match the animated item.
+                shadowContainerLayer.addView(expandLayer);
+                expandLayer.setLeft(viewRect.left);
+                expandLayer.setTop(viewRect.top);
+                expandLayer.setBottom(viewRect.bottom);
+                expandLayer.setRight(viewRect.right);
+                expandLayer.setBackgroundColor(resources.getColor(
+                        R.color.conversation_background));
+                ViewCompat.setElevation(expandLayer, elevation);
+
+                // Conditionally stage the snapshot in the overlay.
+                if (mSnapshot != null) {
+                    shadowContainerLayer.addView(mSnapshot);
+                    mSnapshot.setLeft(viewRect.left);
+                    mSnapshot.setTop(viewRect.top);
+                    mSnapshot.setBottom(viewRect.bottom);
+                    mSnapshot.setRight(viewRect.right);
+                    mSnapshot.setBackground(new BitmapDrawable(resources, mViewBitmap));
+                    ViewCompat.setElevation(mSnapshot, elevation);
+                }
+
+                // Apply a scale animation to scale to full screen.
+                expandLayer.animate().scaleY(scale)
+                    .setDuration(mDuration)
+                    .setInterpolator(UiUtils.EASE_IN_INTERPOLATOR)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            // Clean up the views added to overlay on animation finish.
+                            overlay.remove(shadowContainerLayer);
+                            mViewToAnimate.setBackground(oldBackground);
+                            if (mViewBitmap != null) {
+                                mViewBitmap.recycle();
+                            }
+                        }
+                });
+            }
+        }
+    }
+
+    /**
+     * Take a snapshot of the given review, return a Bitmap object that's owned by the caller.
+     */
+    static Bitmap snapshotView(final View view) {
+        // Save the content of the view into a bitmap.
+        final Bitmap viewBitmap = Bitmap.createBitmap(view.getWidth(),
+                view.getHeight(), Bitmap.Config.ARGB_8888);
+        // Strip the view of its background when taking a snapshot so that things like touch
+        // feedback don't get accidentally snapshotted.
+        final Drawable viewBackground = view.getBackground();
+        ImageUtils.setBackgroundDrawableOnView(view, null);
+        view.draw(new Canvas(viewBitmap));
+        ImageUtils.setBackgroundDrawableOnView(view, viewBackground);
+        return viewBitmap;
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/ApnEditorActivity.java b/src/com/android/messaging/ui/appsettings/ApnEditorActivity.java
new file mode 100644
index 0000000..5d19a83
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/ApnEditorActivity.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.provider.Telephony;
+import androidx.core.app.NavUtils;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.BugleApnSettingsLoader;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.PhoneUtils;
+
+public class ApnEditorActivity extends BugleActionBarActivity {
+    private static final int ERROR_DIALOG_ID = 0;
+    private static final String ERROR_MESSAGE_KEY = "error_msg";
+    private ApnEditorFragment mApnEditorFragment;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        // Display the fragment as the main content.
+        mApnEditorFragment = new ApnEditorFragment();
+        mApnEditorFragment.setSubId(getIntent().getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
+                ParticipantData.DEFAULT_SELF_SUB_ID));
+        getFragmentManager().beginTransaction()
+            .replace(android.R.id.content, mApnEditorFragment)
+            .commit();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                NavUtils.navigateUpFromSameTask(this);
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    protected Dialog onCreateDialog(int id, Bundle args) {
+
+        if (id == ERROR_DIALOG_ID) {
+            String msg = args.getString(ERROR_MESSAGE_KEY);
+
+            return new AlertDialog.Builder(this)
+                .setPositiveButton(android.R.string.ok, null)
+                .setMessage(msg)
+                .create();
+        }
+
+        return super.onCreateDialog(id);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK: {
+                if (mApnEditorFragment.validateAndSave(false)) {
+                    finish();
+                }
+                return true;
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+        super.onPrepareDialog(id, dialog);
+
+        if (id == ERROR_DIALOG_ID) {
+            final String msg = args.getString(ERROR_MESSAGE_KEY);
+
+            if (msg != null) {
+                ((AlertDialog) dialog).setMessage(msg);
+            }
+        }
+    }
+
+    public static class ApnEditorFragment extends PreferenceFragment implements
+        SharedPreferences.OnSharedPreferenceChangeListener {
+
+        private static final String SAVED_POS = "pos";
+
+        private static final int MENU_DELETE = Menu.FIRST;
+        private static final int MENU_SAVE = Menu.FIRST + 1;
+        private static final int MENU_CANCEL = Menu.FIRST + 2;
+
+        private EditTextPreference mMmsProxy;
+        private EditTextPreference mMmsPort;
+        private EditTextPreference mName;
+        private EditTextPreference mMmsc;
+        private EditTextPreference mMcc;
+        private EditTextPreference mMnc;
+        private static String sNotSet;
+
+        private String mCurMnc;
+        private String mCurMcc;
+
+        private Cursor mCursor;
+        private boolean mNewApn;
+        private boolean mFirstTime;
+        private String mCurrentId;
+
+        private int mSubId;
+
+        /**
+         * Standard projection for the interesting columns of a normal note.
+         */
+        private static final String[] sProjection = new String[] {
+            Telephony.Carriers._ID,         // 0
+            Telephony.Carriers.NAME,        // 1
+            Telephony.Carriers.MMSC,        // 2
+            Telephony.Carriers.MCC,         // 3
+            Telephony.Carriers.MNC,         // 4
+            Telephony.Carriers.NUMERIC,     // 5
+            Telephony.Carriers.MMSPROXY,    // 6
+            Telephony.Carriers.MMSPORT,     // 7
+            Telephony.Carriers.TYPE,        // 8
+        };
+
+        private static final int ID_INDEX = 0;
+        private static final int NAME_INDEX = 1;
+        private static final int MMSC_INDEX = 2;
+        private static final int MCC_INDEX = 3;
+        private static final int MNC_INDEX = 4;
+        private static final int NUMERIC_INDEX = 5;
+        private static final int MMSPROXY_INDEX = 6;
+        private static final int MMSPORT_INDEX = 7;
+        private static final int TYPE_INDEX = 8;
+
+        private SQLiteDatabase mDatabase;
+
+        @Override
+        public void onCreate(Bundle icicle) {
+            super.onCreate(icicle);
+
+        }
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            addPreferencesFromResource(R.xml.apn_editor);
+
+            setHasOptionsMenu(true);
+
+            sNotSet = getResources().getString(R.string.apn_not_set);
+            mName = (EditTextPreference) findPreference("apn_name");
+            mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
+            mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
+            mMmsc = (EditTextPreference) findPreference("apn_mmsc");
+            mMcc = (EditTextPreference) findPreference("apn_mcc");
+            mMnc = (EditTextPreference) findPreference("apn_mnc");
+
+            final Intent intent = getActivity().getIntent();
+
+            mFirstTime = savedInstanceState == null;
+            mCurrentId = intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_APN_ROW_ID);
+            mNewApn = mCurrentId == null;
+
+            mDatabase = ApnDatabase.getApnDatabase().getWritableDatabase();
+
+            if (mNewApn) {
+                fillUi();
+            } else {
+                // Do initial query not on the UI thread
+                new AsyncTask<Void, Void, Void>() {
+                    @Override
+                    protected Void doInBackground(Void... params) {
+                        if (mCurrentId != null) {
+                            String selection = Telephony.Carriers._ID + " =?";
+                            String[] selectionArgs = new String[]{ mCurrentId };
+                            mCursor = mDatabase.query(ApnDatabase.APN_TABLE, sProjection, selection,
+                                    selectionArgs, null, null, null, null);
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    protected void onPostExecute(Void result) {
+                        if (mCursor == null) {
+                            getActivity().finish();
+                            return;
+                        }
+                        mCursor.moveToFirst();
+
+                        fillUi();
+                    }
+                }.execute((Void) null);
+            }
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            if (mCursor != null) {
+                mCursor.close();
+                mCursor = null;
+            }
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+            getPreferenceScreen().getSharedPreferences()
+            .registerOnSharedPreferenceChangeListener(this);
+        }
+
+        @Override
+        public void onPause() {
+            getPreferenceScreen().getSharedPreferences()
+            .unregisterOnSharedPreferenceChangeListener(this);
+            super.onPause();
+        }
+
+        public void setSubId(final int subId) {
+            mSubId = subId;
+        }
+
+        private void fillUi() {
+            if (mNewApn) {
+                mMcc.setText(null);
+                mMnc.setText(null);
+                String numeric = PhoneUtils.get(mSubId).getSimOperatorNumeric();
+                // MCC is first 3 chars and then in 2 - 3 chars of MNC
+                if (numeric != null && numeric.length() > 4) {
+                    // Country code
+                    String mcc = numeric.substring(0, 3);
+                    // Network code
+                    String mnc = numeric.substring(3);
+                    // Auto populate MNC and MCC for new entries, based on what SIM reports
+                    mMcc.setText(mcc);
+                    mMnc.setText(mnc);
+                    mCurMnc = mnc;
+                    mCurMcc = mcc;
+                }
+                mName.setText(null);
+                mMmsProxy.setText(null);
+                mMmsPort.setText(null);
+                mMmsc.setText(null);
+            } else if (mFirstTime) {
+                mFirstTime = false;
+                // Fill in all the values from the db in both text editor and summary
+                mName.setText(mCursor.getString(NAME_INDEX));
+                mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
+                mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
+                mMmsc.setText(mCursor.getString(MMSC_INDEX));
+                mMcc.setText(mCursor.getString(MCC_INDEX));
+                mMnc.setText(mCursor.getString(MNC_INDEX));
+            }
+
+            mName.setSummary(checkNull(mName.getText()));
+            mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
+            mMmsPort.setSummary(checkNull(mMmsPort.getText()));
+            mMmsc.setSummary(checkNull(mMmsc.getText()));
+            mMcc.setSummary(checkNull(mMcc.getText()));
+            mMnc.setSummary(checkNull(mMnc.getText()));
+        }
+
+        @Override
+        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            super.onCreateOptionsMenu(menu, inflater);
+            // If it's a new APN, then cancel will delete the new entry in onPause
+            if (!mNewApn) {
+                menu.add(0, MENU_DELETE, 0, R.string.menu_delete_apn)
+                    .setIcon(R.drawable.ic_delete_small_dark);
+            }
+            menu.add(0, MENU_SAVE, 0, R.string.menu_save_apn)
+                .setIcon(android.R.drawable.ic_menu_save);
+            menu.add(0, MENU_CANCEL, 0, R.string.menu_discard_apn_change)
+                .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+        }
+
+        @Override
+        public boolean onOptionsItemSelected(MenuItem item) {
+            switch (item.getItemId()) {
+                case MENU_DELETE:
+                    deleteApn();
+                    return true;
+
+                case MENU_SAVE:
+                    if (validateAndSave(false)) {
+                        getActivity().finish();
+                    }
+                    return true;
+
+                case MENU_CANCEL:
+                    getActivity().finish();
+                    return true;
+
+                case android.R.id.home:
+                    getActivity().onBackPressed();
+                    return true;
+            }
+            return super.onOptionsItemSelected(item);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle icicle) {
+            super.onSaveInstanceState(icicle);
+            if (validateAndSave(true) && mCursor != null) {
+                icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
+            }
+        }
+
+        /**
+         * Check the key fields' validity and save if valid.
+         * @param force save even if the fields are not valid, if the app is
+         *        being suspended
+         * @return true if the data was saved
+         */
+        private boolean validateAndSave(boolean force) {
+            final String name = checkNotSet(mName.getText());
+            final String mcc = checkNotSet(mMcc.getText());
+            final String mnc = checkNotSet(mMnc.getText());
+
+            if (getErrorMsg() != null && !force) {
+                final Bundle bundle = new Bundle();
+                bundle.putString(ERROR_MESSAGE_KEY, getErrorMsg());
+                getActivity().showDialog(ERROR_DIALOG_ID, bundle);
+                return false;
+            }
+
+            // Make database changes not on the UI thread
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    ContentValues values = new ContentValues();
+
+                    // Add a placeholder name "Untitled", if the user exits the screen without
+                    // adding a name but entered other information worth keeping.
+                    values.put(Telephony.Carriers.NAME, name.length() < 1 ?
+                            getResources().getString(R.string.untitled_apn) : name);
+                    values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
+                    values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
+                    values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
+
+                    values.put(Telephony.Carriers.TYPE, BugleApnSettingsLoader.APN_TYPE_MMS);
+
+                    values.put(Telephony.Carriers.MCC, mcc);
+                    values.put(Telephony.Carriers.MNC, mnc);
+
+                    values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
+
+                    if (mCurMnc != null && mCurMcc != null) {
+                        if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
+                            values.put(Telephony.Carriers.CURRENT, 1);
+                        }
+                    }
+
+                    if (mNewApn) {
+                        mDatabase.insert(ApnDatabase.APN_TABLE, null, values);
+                    } else {
+                        // update the APN
+                        String selection = Telephony.Carriers._ID + " =?";
+                        String[] selectionArgs = new String[]{ mCurrentId };
+                        int updated = mDatabase.update(ApnDatabase.APN_TABLE, values,
+                                selection, selectionArgs);
+                    }
+                    return null;
+                }
+            }.execute((Void) null);
+
+            return true;
+        }
+
+        private void deleteApn() {
+            // Make database changes not on the UI thread
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    // delete the APN
+                    String where = Telephony.Carriers._ID + " =?";
+                    String[] whereArgs = new String[]{ mCurrentId };
+
+                    mDatabase.delete(ApnDatabase.APN_TABLE, where, whereArgs);
+                    return null;
+                }
+            }.execute((Void) null);
+
+            getActivity().finish();
+        }
+
+        private String checkNull(String value) {
+            if (value == null || value.length() == 0) {
+                return sNotSet;
+            } else {
+                return value;
+            }
+        }
+
+        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+            Preference pref = findPreference(key);
+            if (pref != null) {
+                pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
+            }
+        }
+
+        private String getErrorMsg() {
+            String errorMsg = null;
+
+            String name = checkNotSet(mName.getText());
+            String mcc = checkNotSet(mMcc.getText());
+            String mnc = checkNotSet(mMnc.getText());
+
+            if (name.length() < 1) {
+                errorMsg = getString(R.string.error_apn_name_empty);
+            } else if (mcc.length() != 3) {
+                errorMsg = getString(R.string.error_mcc_not3);
+            } else if ((mnc.length() & 0xFFFE) != 2) {
+                errorMsg = getString(R.string.error_mnc_not23);
+            }
+
+            return errorMsg;
+        }
+
+        private String checkNotSet(String value) {
+            if (value == null || value.equals(sNotSet)) {
+                return "";
+            } else {
+                return value;
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/ApnPreference.java b/src/com/android/messaging/ui/appsettings/ApnPreference.java
new file mode 100644
index 0000000..64358eb
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/ApnPreference.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.RadioButton;
+import android.widget.RelativeLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.ui.UIIntents;
+
+/**
+ * ApnPreference implements a pref, typically used as a list item, that has a title/summary on
+ * the left and a radio button on the right.
+ *
+ */
+public class ApnPreference extends Preference implements
+        CompoundButton.OnCheckedChangeListener, OnClickListener {
+    static final String TAG = "ApnPreference";
+
+    public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public ApnPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.apnPreferenceStyle);
+    }
+
+    public ApnPreference(Context context) {
+        this(context, null);
+    }
+
+    private static String mSelectedKey = null;
+    private static CompoundButton mCurrentChecked = null;
+    private boolean mProtectFromCheckedChange = false;
+    private boolean mSelectable = true;
+    private int mSubId = ParticipantData.DEFAULT_SELF_SUB_ID;
+
+    @Override
+    public View getView(View convertView, ViewGroup parent) {
+        View view = super.getView(convertView, parent);
+
+        View widget = view.findViewById(R.id.apn_radiobutton);
+        if ((widget != null) && widget instanceof RadioButton) {
+            RadioButton rb = (RadioButton) widget;
+            if (mSelectable) {
+                rb.setOnCheckedChangeListener(this);
+
+                boolean isChecked = getKey().equals(mSelectedKey);
+                if (isChecked) {
+                    mCurrentChecked = rb;
+                    mSelectedKey = getKey();
+                }
+
+                mProtectFromCheckedChange = true;
+                rb.setChecked(isChecked);
+                mProtectFromCheckedChange = false;
+            } else {
+                rb.setVisibility(View.GONE);
+            }
+            rb.setContentDescription(getTitle());
+        }
+
+        View textLayout = view.findViewById(R.id.text_layout);
+        if ((textLayout != null) && textLayout instanceof RelativeLayout) {
+            textLayout.setOnClickListener(this);
+        }
+
+        return view;
+    }
+
+    public boolean isChecked() {
+        return getKey().equals(mSelectedKey);
+    }
+
+    public void setChecked() {
+        mSelectedKey = getKey();
+    }
+
+    public void setSubId(final int subId) {
+        mSubId = subId;
+    }
+
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        Log.i(TAG, "ID: " + getKey() + " :" + isChecked);
+        if (mProtectFromCheckedChange) {
+            return;
+        }
+
+        if (isChecked) {
+            if (mCurrentChecked != null) {
+                mCurrentChecked.setChecked(false);
+            }
+            mCurrentChecked = buttonView;
+            mSelectedKey = getKey();
+            callChangeListener(mSelectedKey);
+        } else {
+            mCurrentChecked = null;
+            mSelectedKey = null;
+        }
+        buttonView.setContentDescription(getTitle());
+    }
+
+    public void onClick(android.view.View v) {
+        if ((v != null) && (R.id.text_layout == v.getId())) {
+            Context context = getContext();
+            if (context != null) {
+                context.startActivity(
+                        UIIntents.get().getApnEditorIntent(context, getKey(), mSubId));
+            }
+        }
+    }
+
+    public void setSelectable(boolean selectable) {
+        mSelectable = selectable;
+    }
+
+    public boolean getSelectable() {
+        return mSelectable;
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/ApnSettingsActivity.java b/src/com/android/messaging/ui/appsettings/ApnSettingsActivity.java
new file mode 100644
index 0000000..13f775a
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/ApnSettingsActivity.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserManager;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.provider.Telephony;
+import androidx.core.app.NavUtils;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.BugleApnSettingsLoader;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+public class ApnSettingsActivity extends BugleActionBarActivity {
+    private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        // Display the fragment as the main content.
+        final ApnSettingsFragment fragment = new ApnSettingsFragment();
+        fragment.setSubId(getIntent().getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
+                ParticipantData.DEFAULT_SELF_SUB_ID));
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, fragment)
+                .commit();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+        case android.R.id.home:
+            NavUtils.navigateUpFromSameTask(this);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        if (id == DIALOG_RESTORE_DEFAULTAPN) {
+            ProgressDialog dialog = new ProgressDialog(this);
+            dialog.setMessage(getResources().getString(R.string.restore_default_apn));
+            dialog.setCancelable(false);
+            return dialog;
+        }
+        return null;
+    }
+
+    public static class ApnSettingsFragment extends PreferenceFragment implements
+            Preference.OnPreferenceChangeListener {
+        public static final String EXTRA_POSITION = "position";
+
+        public static final String APN_ID = "apn_id";
+
+        private static final String[] APN_PROJECTION = {
+            Telephony.Carriers._ID,         // 0
+            Telephony.Carriers.NAME,        // 1
+            Telephony.Carriers.APN,         // 2
+            Telephony.Carriers.TYPE         // 3
+        };
+        private static final int ID_INDEX    = 0;
+        private static final int NAME_INDEX  = 1;
+        private static final int APN_INDEX   = 2;
+        private static final int TYPES_INDEX = 3;
+
+        private static final int MENU_NEW = Menu.FIRST;
+        private static final int MENU_RESTORE = Menu.FIRST + 1;
+
+        private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
+        private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
+
+        private static boolean mRestoreDefaultApnMode;
+
+        private RestoreApnUiHandler mRestoreApnUiHandler;
+        private RestoreApnProcessHandler mRestoreApnProcessHandler;
+        private HandlerThread mRestoreDefaultApnThread;
+
+        private String mSelectedKey;
+
+        private static final ContentValues sCurrentNullMap;
+        private static final ContentValues sCurrentSetMap;
+
+        private UserManager mUm;
+
+        private boolean mUnavailable;
+        private int mSubId;
+
+        static {
+            sCurrentNullMap = new ContentValues(1);
+            sCurrentNullMap.putNull(Telephony.Carriers.CURRENT);
+
+            sCurrentSetMap = new ContentValues(1);
+            sCurrentSetMap.put(Telephony.Carriers.CURRENT, "2");    // 2 for user-selected APN,
+            // 1 for Bugle-selected APN
+        }
+
+        private SQLiteDatabase mDatabase;
+
+        public void setSubId(final int subId) {
+            mSubId = subId;
+        }
+
+        @Override
+        public void onCreate(Bundle icicle) {
+            super.onCreate(icicle);
+
+            mDatabase = ApnDatabase.getApnDatabase().getWritableDatabase();
+
+            if (OsUtil.isAtLeastL()) {
+                mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
+                if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+                    setHasOptionsMenu(true);
+                }
+            } else {
+                setHasOptionsMenu(true);
+            }
+        }
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            final ListView lv = (ListView) getView().findViewById(android.R.id.list);
+            TextView empty = (TextView) getView().findViewById(android.R.id.empty);
+            if (empty != null) {
+                empty.setText(R.string.apn_settings_not_available);
+                lv.setEmptyView(empty);
+            }
+
+            if (OsUtil.isAtLeastL() &&
+                    mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+                mUnavailable = true;
+                setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
+                return;
+            }
+
+            addPreferencesFromResource(R.xml.apn_settings);
+
+            lv.setItemsCanFocus(true);
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+
+            if (mUnavailable) {
+                return;
+            }
+
+            if (!mRestoreDefaultApnMode) {
+                fillList();
+            }
+        }
+
+        @Override
+        public void onPause() {
+            super.onPause();
+
+            if (mUnavailable) {
+                return;
+            }
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+
+            if (mRestoreDefaultApnThread != null) {
+                mRestoreDefaultApnThread.quit();
+            }
+        }
+
+        private void fillList() {
+            final String mccMnc = PhoneUtils.getMccMncString(PhoneUtils.get(mSubId).getMccMnc());
+
+            new AsyncTask<Void, Void, Cursor>() {
+                @Override
+                protected Cursor doInBackground(Void... params) {
+                    String selection = Telephony.Carriers.NUMERIC + " =?";
+                    String[] selectionArgs = new String[]{ mccMnc };
+                    final Cursor cursor = mDatabase.query(ApnDatabase.APN_TABLE, APN_PROJECTION,
+                            selection, selectionArgs, null, null, null, null);
+                    return cursor;
+                }
+
+                @Override
+                protected void onPostExecute(Cursor cursor) {
+                    if (cursor != null) {
+                        try {
+                            PreferenceGroup apnList = (PreferenceGroup)
+                                    findPreference(getString(R.string.apn_list_pref_key));
+                            apnList.removeAll();
+
+                            mSelectedKey = BugleApnSettingsLoader.getFirstTryApn(mDatabase, mccMnc);
+                            while (cursor.moveToNext()) {
+                                String name = cursor.getString(NAME_INDEX);
+                                String apn = cursor.getString(APN_INDEX);
+                                String key = cursor.getString(ID_INDEX);
+                                String type = cursor.getString(TYPES_INDEX);
+
+                                if (BugleApnSettingsLoader.isValidApnType(type,
+                                        BugleApnSettingsLoader.APN_TYPE_MMS)) {
+                                    ApnPreference pref = new ApnPreference(getActivity());
+                                    pref.setKey(key);
+                                    pref.setTitle(name);
+                                    pref.setSummary(apn);
+                                    pref.setPersistent(false);
+                                    pref.setOnPreferenceChangeListener(ApnSettingsFragment.this);
+                                    pref.setSelectable(true);
+
+                                    // Turn on the radio button for the currently selected APN. If
+                                    // there is no selected APN, don't select an APN.
+                                    if ((mSelectedKey != null && mSelectedKey.equals(key))) {
+                                        pref.setChecked();
+                                    }
+                                    apnList.addPreference(pref);
+                                }
+                            }
+                        } finally {
+                            cursor.close();
+                        }
+                    }
+                }
+            }.execute((Void) null);
+        }
+
+        @Override
+        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            if (!mUnavailable) {
+                menu.add(0, MENU_NEW, 0,
+                        getResources().getString(R.string.menu_new_apn))
+                        .setIcon(R.drawable.ic_add_white)
+                        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                menu.add(0, MENU_RESTORE, 0,
+                        getResources().getString(R.string.menu_restore_default_apn))
+                        .setIcon(android.R.drawable.ic_menu_upload);
+            }
+
+            super.onCreateOptionsMenu(menu, inflater);
+        }
+
+        @Override
+        public boolean onOptionsItemSelected(MenuItem item) {
+            switch (item.getItemId()) {
+                case MENU_NEW:
+                    addNewApn();
+                    return true;
+
+                case MENU_RESTORE:
+                    restoreDefaultApn();
+                    return true;
+            }
+            return super.onOptionsItemSelected(item);
+        }
+
+        private void addNewApn() {
+            startActivity(UIIntents.get().getApnEditorIntent(getActivity(), null, mSubId));
+        }
+
+        @Override
+        public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+                Preference preference) {
+            startActivity(
+                    UIIntents.get().getApnEditorIntent(getActivity(), preference.getKey(), mSubId));
+            return true;
+        }
+
+        @Override
+        public boolean onPreferenceChange(Preference preference, Object newValue) {
+            if (newValue instanceof String) {
+                setSelectedApnKey((String) newValue);
+            }
+
+            return true;
+        }
+
+        // current=2 means user selected APN
+        private static final String UPDATE_SELECTION = Telephony.Carriers.CURRENT + " =?";
+        private static final String[] UPDATE_SELECTION_ARGS = new String[] { "2" };
+        private void setSelectedApnKey(final String key) {
+            mSelectedKey = key;
+
+            // Make database changes not on the UI thread
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    // null out the previous "current=2" APN
+                    mDatabase.update(ApnDatabase.APN_TABLE, sCurrentNullMap,
+                            UPDATE_SELECTION, UPDATE_SELECTION_ARGS);
+
+                    // set the new "current" APN (2)
+                    String selection = Telephony.Carriers._ID + " =?";
+                    String[] selectionArgs = new String[]{ key };
+
+                    mDatabase.update(ApnDatabase.APN_TABLE, sCurrentSetMap,
+                            selection, selectionArgs);
+                    return null;
+                }
+            }.execute((Void) null);
+        }
+
+        private boolean restoreDefaultApn() {
+            getActivity().showDialog(DIALOG_RESTORE_DEFAULTAPN);
+            mRestoreDefaultApnMode = true;
+
+            if (mRestoreApnUiHandler == null) {
+                mRestoreApnUiHandler = new RestoreApnUiHandler();
+            }
+
+            if (mRestoreApnProcessHandler == null ||
+                    mRestoreDefaultApnThread == null) {
+                mRestoreDefaultApnThread = new HandlerThread(
+                        "Restore default APN Handler: Process Thread");
+                mRestoreDefaultApnThread.start();
+                mRestoreApnProcessHandler = new RestoreApnProcessHandler(
+                        mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
+            }
+
+            mRestoreApnProcessHandler.sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
+            return true;
+        }
+
+        private class RestoreApnUiHandler extends Handler {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
+                        fillList();
+                        getPreferenceScreen().setEnabled(true);
+                        mRestoreDefaultApnMode = false;
+                        final Activity activity = getActivity();
+                        activity.dismissDialog(DIALOG_RESTORE_DEFAULTAPN);
+                        Toast.makeText(activity, getResources().getString(
+                                        R.string.restore_default_apn_completed), Toast.LENGTH_LONG)
+                                            .show();
+                        break;
+                }
+            }
+        }
+
+        private class RestoreApnProcessHandler extends Handler {
+            private Handler mCachedRestoreApnUiHandler;
+
+            public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
+                super(looper);
+                this.mCachedRestoreApnUiHandler = restoreApnUiHandler;
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case EVENT_RESTORE_DEFAULTAPN_START:
+                        ApnDatabase.forceBuildAndLoadApnTables();
+                        mCachedRestoreApnUiHandler.sendEmptyMessage(
+                                EVENT_RESTORE_DEFAULTAPN_COMPLETE);
+                        break;
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java b/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java
new file mode 100644
index 0000000..d7abe85
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.preference.RingtonePreference;
+import android.preference.TwoStatePreference;
+import android.provider.Settings;
+import androidx.core.app.NavUtils;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.LicenseActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+public class ApplicationSettingsActivity extends BugleActionBarActivity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        final boolean topLevel = getIntent().getBooleanExtra(
+                UIIntents.UI_INTENT_EXTRA_TOP_LEVEL_SETTINGS, false);
+        if (topLevel) {
+            getSupportActionBar().setTitle(getString(R.string.settings_activity_title));
+        }
+
+        FragmentTransaction ft = getFragmentManager().beginTransaction();
+        ft.replace(android.R.id.content, new ApplicationSettingsFragment());
+        ft.commit();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (super.onCreateOptionsMenu(menu)) {
+            return true;
+        }
+        getMenuInflater().inflate(R.menu.settings_menu, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+        case android.R.id.home:
+            NavUtils.navigateUpFromSameTask(this);
+            return true;
+        case R.id.action_license:
+            final Intent intent = new Intent(this, LicenseActivity.class);
+            startActivity(intent);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    public static class ApplicationSettingsFragment extends PreferenceFragment implements
+            OnSharedPreferenceChangeListener {
+
+        private String mNotificationsEnabledPreferenceKey;
+        private TwoStatePreference mNotificationsEnabledPreference;
+        private String mRingtonePreferenceKey;
+        private RingtonePreference mRingtonePreference;
+        private Preference mVibratePreference;
+        private String mSmsDisabledPrefKey;
+        private Preference mSmsDisabledPreference;
+        private String mSmsEnabledPrefKey;
+        private Preference mSmsEnabledPreference;
+        private boolean mIsSmsPreferenceClicked;
+
+        public ApplicationSettingsFragment() {
+            // Required empty constructor
+        }
+
+        @Override
+        public void onCreate(final Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            getPreferenceManager().setSharedPreferencesName(BuglePrefs.SHARED_PREFERENCES_NAME);
+            addPreferencesFromResource(R.xml.preferences_application);
+
+            mNotificationsEnabledPreferenceKey =
+                    getString(R.string.notifications_enabled_pref_key);
+            mNotificationsEnabledPreference = (TwoStatePreference) findPreference(
+                    mNotificationsEnabledPreferenceKey);
+            mRingtonePreferenceKey = getString(R.string.notification_sound_pref_key);
+            mRingtonePreference = (RingtonePreference) findPreference(mRingtonePreferenceKey);
+            mVibratePreference = findPreference(
+                    getString(R.string.notification_vibration_pref_key));
+            mSmsDisabledPrefKey = getString(R.string.sms_disabled_pref_key);
+            mSmsDisabledPreference = findPreference(mSmsDisabledPrefKey);
+            mSmsEnabledPrefKey = getString(R.string.sms_enabled_pref_key);
+            mSmsEnabledPreference = findPreference(mSmsEnabledPrefKey);
+            mIsSmsPreferenceClicked = false;
+
+            final SharedPreferences prefs = getPreferenceScreen().getSharedPreferences();
+            updateSoundSummary(prefs);
+
+            if (!DebugUtils.isDebugEnabled()) {
+                final Preference debugCategory = findPreference(getString(
+                        R.string.debug_pref_key));
+                getPreferenceScreen().removePreference(debugCategory);
+            }
+
+            final PreferenceScreen advancedScreen = (PreferenceScreen) findPreference(
+                    getString(R.string.advanced_pref_key));
+            final boolean topLevel = getActivity().getIntent().getBooleanExtra(
+                    UIIntents.UI_INTENT_EXTRA_TOP_LEVEL_SETTINGS, false);
+            if (topLevel) {
+                advancedScreen.setIntent(UIIntents.get()
+                        .getAdvancedSettingsIntent(getPreferenceScreen().getContext()));
+            } else {
+                // Hide the Advanced settings screen if this is not top-level; these are shown at
+                // the parent SettingsActivity.
+                getPreferenceScreen().removePreference(advancedScreen);
+            }
+        }
+
+        @Override
+        public boolean onPreferenceTreeClick (PreferenceScreen preferenceScreen,
+                Preference preference) {
+            if (preference.getKey() ==  mSmsDisabledPrefKey ||
+                    preference.getKey() == mSmsEnabledPrefKey) {
+                mIsSmsPreferenceClicked = true;
+            }
+            return super.onPreferenceTreeClick(preferenceScreen, preference);
+        }
+
+        private void updateSoundSummary(final SharedPreferences sharedPreferences) {
+            // The silent ringtone just returns an empty string
+            String ringtoneName = mRingtonePreference.getContext().getString(
+                    R.string.silent_ringtone);
+
+            String ringtoneString = sharedPreferences.getString(mRingtonePreferenceKey, null);
+
+            // Bootstrap the default setting in the preferences so that we have a valid selection
+            // in the dialog the first time that the user opens it.
+            if (ringtoneString == null) {
+                ringtoneString = Settings.System.DEFAULT_NOTIFICATION_URI.toString();
+                final SharedPreferences.Editor editor = sharedPreferences.edit();
+                editor.putString(mRingtonePreferenceKey, ringtoneString);
+                editor.apply();
+            }
+
+            if (!TextUtils.isEmpty(ringtoneString)) {
+                final Uri ringtoneUri = Uri.parse(ringtoneString);
+                final Ringtone tone = RingtoneManager.getRingtone(mRingtonePreference.getContext(),
+                        ringtoneUri);
+
+                if (tone != null) {
+                    ringtoneName = tone.getTitle(mRingtonePreference.getContext());
+                }
+            }
+
+            mRingtonePreference.setSummary(ringtoneName);
+        }
+
+        private void updateSmsEnabledPreferences() {
+            if (!OsUtil.isAtLeastKLP()) {
+                getPreferenceScreen().removePreference(mSmsDisabledPreference);
+                getPreferenceScreen().removePreference(mSmsEnabledPreference);
+            } else {
+                final String defaultSmsAppLabel = getString(R.string.default_sms_app,
+                        PhoneUtils.getDefault().getDefaultSmsAppLabel());
+                boolean isSmsEnabledBeforeState;
+                boolean isSmsEnabledCurrentState;
+                if (PhoneUtils.getDefault().isDefaultSmsApp()) {
+                    if (getPreferenceScreen().findPreference(mSmsEnabledPrefKey) == null) {
+                        getPreferenceScreen().addPreference(mSmsEnabledPreference);
+                        isSmsEnabledBeforeState = false;
+                    } else {
+                        isSmsEnabledBeforeState = true;
+                    }
+                    isSmsEnabledCurrentState = true;
+                    getPreferenceScreen().removePreference(mSmsDisabledPreference);
+                    mSmsEnabledPreference.setSummary(defaultSmsAppLabel);
+                } else {
+                    if (getPreferenceScreen().findPreference(mSmsDisabledPrefKey) == null) {
+                        getPreferenceScreen().addPreference(mSmsDisabledPreference);
+                        isSmsEnabledBeforeState = true;
+                    } else {
+                        isSmsEnabledBeforeState = false;
+                    }
+                    isSmsEnabledCurrentState = false;
+                    getPreferenceScreen().removePreference(mSmsEnabledPreference);
+                    mSmsDisabledPreference.setSummary(defaultSmsAppLabel);
+                }
+                updateNotificationsPreferences();
+            }
+            mIsSmsPreferenceClicked = false;
+        }
+
+        private void updateNotificationsPreferences() {
+            final boolean canNotify = !OsUtil.isAtLeastKLP()
+                    || PhoneUtils.getDefault().isDefaultSmsApp();
+            mNotificationsEnabledPreference.setEnabled(canNotify);
+        }
+
+        @Override
+        public void onStart() {
+            super.onStart();
+            // We do this on start rather than on resume because the sound picker is in a
+            // separate activity.
+            getPreferenceScreen().getSharedPreferences()
+                    .registerOnSharedPreferenceChangeListener(this);
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+            updateSmsEnabledPreferences();
+            updateNotificationsPreferences();
+        }
+
+        @Override
+        public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
+                final String key) {
+            if (key.equals(mNotificationsEnabledPreferenceKey)) {
+                updateNotificationsPreferences();
+            } else if (key.equals(mRingtonePreferenceKey)) {
+                updateSoundSummary(sharedPreferences);
+            }
+        }
+
+        @Override
+        public void onStop() {
+            super.onStop();
+            getPreferenceScreen().getSharedPreferences()
+                    .unregisterOnSharedPreferenceChangeListener(this);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/GroupMmsSettingDialog.java b/src/com/android/messaging/ui/appsettings/GroupMmsSettingDialog.java
new file mode 100644
index 0000000..739d2dc
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/GroupMmsSettingDialog.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.appsettings;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.RadioButton;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BuglePrefs;
+
+/**
+ * Displays an on/off switch for group MMS setting for a given subscription.
+ */
+public class GroupMmsSettingDialog {
+    private final Context mContext;
+    private final int mSubId;
+    private AlertDialog mDialog;
+
+    /**
+     * Shows a new group MMS setting dialog.
+     */
+    public static void showDialog(final Context context, final int subId) {
+        new GroupMmsSettingDialog(context, subId).show();
+    }
+
+    private GroupMmsSettingDialog(final Context context, final int subId) {
+        mContext = context;
+        mSubId = subId;
+    }
+
+    private void show() {
+        Assert.isNull(mDialog);
+        mDialog = new AlertDialog.Builder(mContext)
+                .setView(createView())
+                .setTitle(R.string.group_mms_pref_title)
+                .setNegativeButton(android.R.string.cancel, null)
+                .show();
+    }
+
+    private void changeGroupMmsSettings(final boolean enable) {
+        Assert.notNull(mDialog);
+        BuglePrefs.getSubscriptionPrefs(mSubId).putBoolean(
+                mContext.getString(R.string.group_mms_pref_key), enable);
+        mDialog.dismiss();
+    }
+
+    private View createView() {
+        final LayoutInflater inflater = (LayoutInflater) mContext
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View rootView = inflater.inflate(R.layout.group_mms_setting_dialog, null, false);
+        final RadioButton disableButton = (RadioButton)
+                rootView.findViewById(R.id.disable_group_mms_button);
+        final RadioButton enableButton = (RadioButton)
+                rootView.findViewById(R.id.enable_group_mms_button);
+        disableButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                changeGroupMmsSettings(false);
+            }
+        });
+        enableButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                changeGroupMmsSettings(true);
+            }
+        });
+        final boolean mmsEnabled = BuglePrefs.getSubscriptionPrefs(mSubId).getBoolean(
+                mContext.getString(R.string.group_mms_pref_key),
+                mContext.getResources().getBoolean(R.bool.group_mms_pref_default));
+        enableButton.setChecked(mmsEnabled);
+        disableButton.setChecked(!mmsEnabled);
+        return rootView;
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java b/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java
new file mode 100644
index 0000000..c2fd473
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.app.FragmentTransaction;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.view.MenuItem;
+
+import androidx.appcompat.mms.MmsManager;
+import androidx.core.app.NavUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.ParticipantRefresh;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.PhoneUtils;
+
+public class PerSubscriptionSettingsActivity extends BugleActionBarActivity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        final String title = getIntent().getStringExtra(
+                UIIntents.UI_INTENT_EXTRA_PER_SUBSCRIPTION_SETTING_TITLE);
+        if (!TextUtils.isEmpty(title)) {
+            getSupportActionBar().setTitle(title);
+        } else {
+            // This will fall back to the default title, i.e. "Messaging settings," so No-op.
+        }
+
+        final FragmentTransaction ft = getFragmentManager().beginTransaction();
+        final PerSubscriptionSettingsFragment fragment = new PerSubscriptionSettingsFragment();
+        ft.replace(android.R.id.content, fragment);
+        ft.commit();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+        case android.R.id.home:
+            NavUtils.navigateUpFromSameTask(this);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    public static class PerSubscriptionSettingsFragment extends PreferenceFragment
+            implements OnSharedPreferenceChangeListener {
+        private PhoneNumberPreference mPhoneNumberPreference;
+        private Preference mGroupMmsPreference;
+        private String mGroupMmsPrefKey;
+        private String mPhoneNumberKey;
+        private int mSubId;
+
+        public PerSubscriptionSettingsFragment() {
+            // Required empty constructor
+        }
+
+        @Override
+        public void onCreate(final Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            // Get sub id from launch intent
+            final Intent intent = getActivity().getIntent();
+            Assert.notNull(intent);
+            mSubId = (intent != null) ? intent.getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
+                    ParticipantData.DEFAULT_SELF_SUB_ID) : ParticipantData.DEFAULT_SELF_SUB_ID;
+
+            final BuglePrefs subPrefs = Factory.get().getSubscriptionPrefs(mSubId);
+            getPreferenceManager().setSharedPreferencesName(subPrefs.getSharedPreferencesName());
+            addPreferencesFromResource(R.xml.preferences_per_subscription);
+
+            mPhoneNumberKey = getString(R.string.mms_phone_number_pref_key);
+            mPhoneNumberPreference = (PhoneNumberPreference) findPreference(mPhoneNumberKey);
+            final PreferenceCategory advancedCategory = (PreferenceCategory)
+                    findPreference(getString(R.string.advanced_category_pref_key));
+            final PreferenceCategory mmsCategory = (PreferenceCategory)
+                    findPreference(getString(R.string.mms_messaging_category_pref_key));
+
+            mPhoneNumberPreference.setDefaultPhoneNumber(
+                    PhoneUtils.get(mSubId).getCanonicalForSelf(false/*allowOverride*/), mSubId);
+
+            mGroupMmsPrefKey = getString(R.string.group_mms_pref_key);
+            mGroupMmsPreference = findPreference(mGroupMmsPrefKey);
+            if (!MmsConfig.get(mSubId).getGroupMmsEnabled()) {
+                // Always show group messaging setting even if the SIM has no number
+                // If broadcast sms is selected, the SIM number is not needed
+                // If group mms is selected, the phone number dialog will popup when message
+                // is being sent, making sure we will have a self number for group mms.
+                mmsCategory.removePreference(mGroupMmsPreference);
+            } else {
+                mGroupMmsPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                    @Override
+                    public boolean onPreferenceClick(Preference pref) {
+                        GroupMmsSettingDialog.showDialog(getActivity(), mSubId);
+                        return true;
+                    }
+                });
+                updateGroupMmsPrefSummary();
+            }
+
+            if (!MmsConfig.get(mSubId).getSMSDeliveryReportsEnabled()) {
+                final Preference deliveryReportsPref = findPreference(
+                        getString(R.string.delivery_reports_pref_key));
+                advancedCategory.removePreference(deliveryReportsPref);
+            }
+            final Preference wirelessAlertPref = findPreference(getString(
+                    R.string.wireless_alerts_key));
+            if (!isCellBroadcastAppLinkEnabled()) {
+                advancedCategory.removePreference(wirelessAlertPref);
+            } else {
+                wirelessAlertPref.setOnPreferenceClickListener(
+                        new Preference.OnPreferenceClickListener() {
+                            @Override
+                            public boolean onPreferenceClick(final Preference preference) {
+                                try {
+                                    startActivity(UIIntents.get().getWirelessAlertsIntent());
+                                } catch (final ActivityNotFoundException e) {
+                                    // Handle so we shouldn't crash if the wireless alerts
+                                    // implementation is broken.
+                                    LogUtil.e(LogUtil.BUGLE_TAG,
+                                            "Failed to launch wireless alerts activity", e);
+                                }
+                                return true;
+                            }
+                        });
+            }
+
+            // Access Point Names (APNs)
+            final PreferenceScreen apnsScreen =
+                    (PreferenceScreen) findPreference(getString(R.string.sms_apns_key));
+
+            if (!MmsManager.shouldUseLegacyMms()
+                    || (MmsUtils.useSystemApnTable() && !ApnDatabase.doesDatabaseExist())) {
+                // 1) Remove the ability to edit the local APN prefs if it doesn't use legacy APIs.
+                // 2) Don't remove the ability to edit the local APN prefs if this device lets us
+                // access the system APN, but we can't find the MCC/MNC in the APN table and we
+                // created the local APN table in case the MCC/MNC was in there. In other words,
+                // if the local APN table exists, let the user edit it.
+                advancedCategory.removePreference((Preference) apnsScreen);
+            } else {
+                apnsScreen.setIntent(UIIntents.get()
+                        .getApnSettingsIntent(getPreferenceScreen().getContext(), mSubId));
+            }
+
+            // We want to disable preferences if we are not the default app, but we do all of the
+            // above first so that the user sees the correct information on the screen
+            if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
+                mGroupMmsPreference.setEnabled(false);
+                final Preference autoRetrieveMmsPreference =
+                        findPreference(getString(R.string.auto_retrieve_mms_pref_key));
+                autoRetrieveMmsPreference.setEnabled(false);
+                final Preference deliveryReportsPreference =
+                        findPreference(getString(R.string.delivery_reports_pref_key));
+                if (deliveryReportsPreference != null) {
+                    deliveryReportsPreference.setEnabled(false);
+                }
+            }
+
+            if (advancedCategory.getPreferenceCount() == 0) {
+                getPreferenceScreen().removePreference(advancedCategory);
+            }
+        }
+
+        private boolean isCellBroadcastAppLinkEnabled() {
+            if (!MmsConfig.get(mSubId).getShowCellBroadcast()) {
+                return false;
+            }
+            try {
+                final PackageManager pm = getActivity().getPackageManager();
+                return pm.getApplicationEnabledSetting(UIIntents.CMAS_COMPONENT)
+                        != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+            } catch (final IllegalArgumentException ignored) {
+                // CMAS app not installed.
+            }
+            return false;
+        }
+
+        private void updateGroupMmsPrefSummary() {
+            final boolean groupMmsEnabled = getPreferenceScreen().getSharedPreferences().getBoolean(
+                    mGroupMmsPrefKey, getResources().getBoolean(R.bool.group_mms_pref_default));
+            mGroupMmsPreference.setSummary(groupMmsEnabled ?
+                    R.string.enable_group_mms : R.string.disable_group_mms);
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+            getPreferenceScreen().getSharedPreferences()
+                    .registerOnSharedPreferenceChangeListener(this);
+        }
+
+        @Override
+        public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
+                final String key) {
+            if (key.equals(mGroupMmsPrefKey)) {
+                updateGroupMmsPrefSummary();
+            } else if (key.equals(mPhoneNumberKey)) {
+                // Save the changed phone number in preferences specific to the sub id
+                final String newPhoneNumber = mPhoneNumberPreference.getText();
+                final BuglePrefs subPrefs = BuglePrefs.getSubscriptionPrefs(mSubId);
+                if (TextUtils.isEmpty(newPhoneNumber)) {
+                    subPrefs.remove(mPhoneNumberKey);
+                } else {
+                    subPrefs.putString(getString(R.string.mms_phone_number_pref_key),
+                            newPhoneNumber);
+                }
+                // Update the self participants so the new phone number will be reflected
+                // everywhere in the UI.
+                ParticipantRefresh.refreshSelfParticipants();
+            }
+        }
+
+        @Override
+        public void onPause() {
+            super.onPause();
+            getPreferenceScreen().getSharedPreferences()
+                    .unregisterOnSharedPreferenceChangeListener(this);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/PhoneNumberPreference.java b/src/com/android/messaging/ui/appsettings/PhoneNumberPreference.java
new file mode 100644
index 0000000..42ef606
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/PhoneNumberPreference.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.content.Context;
+import android.preference.EditTextPreference;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Preference that displays a phone number and allows editing via a dialog.
+ * <p>
+ * A default number can be assigned, which is shown in the preference view and
+ * used to populate the dialog editor when the preference value is not set. If
+ * the user sets the preference to a number equivalent to the default, the
+ * underlying preference is cleared.
+ */
+public class PhoneNumberPreference extends EditTextPreference {
+
+    private String mDefaultPhoneNumber;
+    private int mSubId;
+
+    public PhoneNumberPreference(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mDefaultPhoneNumber = "";
+    }
+
+    public void setDefaultPhoneNumber(final String phoneNumber, final int subscriptionId) {
+        mDefaultPhoneNumber = phoneNumber;
+        mSubId = subscriptionId;
+    }
+
+    @Override
+    protected void onBindView(final View view) {
+        // Show the preference value if it's set, or the default number if not.
+        // If we don't have a default, fall back to a static string (e.g. Unknown).
+        String value = getText();
+        if (TextUtils.isEmpty(value)) {
+          value = mDefaultPhoneNumber;
+        }
+        final String displayValue = (!TextUtils.isEmpty(value))
+                ? PhoneUtils.get(mSubId).formatForDisplay(value)
+                : getContext().getString(R.string.unknown_phone_number_pref_display_value);
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+        final String phoneNumber = bidiFormatter.unicodeWrap
+                        (displayValue, TextDirectionHeuristicsCompat.LTR);
+        // Set the value as the summary and let the superclass populate the views
+        setSummary(phoneNumber);
+        super.onBindView(view);
+    }
+
+    @Override
+    protected void onBindDialogView(final View view) {
+        super.onBindDialogView(view);
+
+        final String value = getText();
+
+        // If the preference is empty, populate the EditText with the default number instead.
+        if (TextUtils.isEmpty(value) && !TextUtils.isEmpty(mDefaultPhoneNumber)) {
+            final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+            final String phoneNumber = bidiFormatter.unicodeWrap
+                (PhoneUtils.get(mSubId).getCanonicalBySystemLocale(mDefaultPhoneNumber),
+                            TextDirectionHeuristicsCompat.LTR);
+            getEditText().setText(phoneNumber);
+        }
+        getEditText().setInputType(InputType.TYPE_CLASS_PHONE);
+    }
+
+    @Override
+    protected void onDialogClosed(final boolean positiveResult) {
+        if (positiveResult && mDefaultPhoneNumber != null) {
+            final String value = getEditText().getText().toString();
+            final PhoneUtils phoneUtils = PhoneUtils.get(mSubId);
+            final String phoneNumber = phoneUtils.getCanonicalBySystemLocale(value);
+            final String defaultPhoneNumber = phoneUtils.getCanonicalBySystemLocale(
+                    mDefaultPhoneNumber);
+
+            // If the new value is the default, clear the preference.
+            if (phoneNumber.equals(defaultPhoneNumber)) {
+                setText("");
+                return;
+            }
+        }
+        super.onDialogClosed(positiveResult);
+    }
+
+    @Override
+    public void setText(final String text) {
+        super.setText(text);
+
+        // EditTextPreference doesn't show the value on the preference view, but we do.
+        // We thus need to force a rebind of the view when a new value is set.
+        notifyChanged();
+    }
+}
diff --git a/src/com/android/messaging/ui/appsettings/SettingsActivity.java b/src/com/android/messaging/ui/appsettings/SettingsActivity.java
new file mode 100644
index 0000000..dc16d0a
--- /dev/null
+++ b/src/com/android/messaging/ui/appsettings/SettingsActivity.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.appsettings;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import androidx.core.app.NavUtils;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.SettingsData;
+import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
+import com.android.messaging.datamodel.data.SettingsData.SettingsItem;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Shows the "primary" settings activity that contains two parts, one for application-wide settings
+ * (dubbed "General settings"), and one or more for per-subscription settings (dubbed "Messaging
+ * settings" for single-SIM, and the actual SIM name for multi-SIM). Clicking on either item
+ * (e.g. "General settings") will open the detail settings activity (ApplicationSettingsActivity
+ * in this case).
+ */
+public class SettingsActivity extends BugleActionBarActivity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        // Directly open the detailed settings page as the top-level settings activity if this is
+        // not a multi-SIM device.
+        if (PhoneUtils.getDefault().getActiveSubscriptionCount() <= 1) {
+            UIIntents.get().launchApplicationSettingsActivity(this, true /* topLevel */);
+            finish();
+        } else {
+            getFragmentManager().beginTransaction()
+                    .replace(android.R.id.content, new SettingsFragment())
+                    .commit();
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+        case android.R.id.home:
+            NavUtils.navigateUpFromSameTask(this);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    public static class SettingsFragment extends Fragment implements SettingsDataListener {
+        private ListView mListView;
+        private SettingsListAdapter mAdapter;
+        private final Binding<SettingsData> mBinding = BindingBase.createBinding(this);
+
+        @Override
+        public void onCreate(final Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mBinding.bind(DataModel.get().createSettingsData(getActivity(), this));
+            mBinding.getData().init(getLoaderManager(), mBinding);
+        }
+
+        @Override
+        public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+                final Bundle savedInstanceState) {
+            final View view = inflater.inflate(R.layout.settings_fragment, container, false);
+            mListView = (ListView) view.findViewById(android.R.id.list);
+            mAdapter = new SettingsListAdapter(getActivity());
+            mListView.setAdapter(mAdapter);
+            return view;
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            mBinding.unbind();
+        }
+
+        @Override
+        public void onSelfParticipantDataLoaded(SettingsData data) {
+            mBinding.ensureBound(data);
+            mAdapter.setSettingsItems(data.getSettingsItems());
+        }
+
+        /**
+         * An adapter that displays a list of SettingsItem.
+         */
+        private class SettingsListAdapter extends ArrayAdapter<SettingsItem> {
+            public SettingsListAdapter(final Context context) {
+                super(context, R.layout.settings_item_view, new ArrayList<SettingsItem>());
+            }
+
+            public void setSettingsItems(final List<SettingsItem> newList) {
+                clear();
+                addAll(newList);
+                notifyDataSetChanged();
+            }
+
+            @Override
+            public View getView(final int position, final View convertView,
+                    final ViewGroup parent) {
+                View itemView;
+                if (convertView != null) {
+                    itemView = convertView;
+                } else {
+                    final LayoutInflater inflater = (LayoutInflater) getContext()
+                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                    itemView = inflater.inflate(
+                            R.layout.settings_item_view, parent, false);
+                }
+                final SettingsItem item = getItem(position);
+                final TextView titleTextView = (TextView) itemView.findViewById(R.id.title);
+                final TextView subtitleTextView = (TextView) itemView.findViewById(R.id.subtitle);
+                final String summaryText = item.getDisplayDetail();
+                titleTextView.setText(item.getDisplayName());
+                if (!TextUtils.isEmpty(summaryText)) {
+                    subtitleTextView.setText(summaryText);
+                    subtitleTextView.setVisibility(View.VISIBLE);
+                } else {
+                    subtitleTextView.setVisibility(View.GONE);
+                }
+                itemView.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View view) {
+                        switch (item.getType()) {
+                            case SettingsItem.TYPE_GENERAL_SETTINGS:
+                                UIIntents.get().launchApplicationSettingsActivity(getActivity(),
+                                        false /* topLevel */);
+                                break;
+
+                            case SettingsItem.TYPE_PER_SUBSCRIPTION_SETTINGS:
+                                UIIntents.get().launchPerSubscriptionSettingsActivity(getActivity(),
+                                        item.getSubId(), item.getActivityTitle());
+                                break;
+
+                            default:
+                                Assert.fail("unrecognized setting type!");
+                                break;
+                        }
+                    }
+                });
+                return itemView;
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserActivity.java b/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserActivity.java
new file mode 100644
index 0000000..a540597
--- /dev/null
+++ b/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.attachmentchooser;
+
+import android.app.Fragment;
+import android.os.Bundle;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
+import com.android.messaging.util.Assert;
+
+public class AttachmentChooserActivity extends BugleActionBarActivity implements
+        AttachmentChooserFragmentHost {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.attachment_chooser_activity);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        if (fragment instanceof AttachmentChooserFragment) {
+            final String conversationId =
+                    getIntent().getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+            Assert.notNull(conversationId);
+            final AttachmentChooserFragment chooserFragment =
+                    (AttachmentChooserFragment) fragment;
+            chooserFragment.setConversationId(conversationId);
+            chooserFragment.setHost(this);
+        }
+    }
+
+    @Override
+    public void onConfirmSelection() {
+        setResult(RESULT_OK);
+        finish();
+    }
+}
diff --git a/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragment.java b/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragment.java
new file mode 100644
index 0000000..75ea56d
--- /dev/null
+++ b/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragment.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.attachmentchooser;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageDataListener;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.attachmentchooser.AttachmentGridView.AttachmentGridHost;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AttachmentChooserFragment extends Fragment implements DraftMessageDataListener,
+        AttachmentGridHost {
+    public interface AttachmentChooserFragmentHost {
+        void onConfirmSelection();
+    }
+
+    private AttachmentGridView mAttachmentGridView;
+    private AttachmentGridAdapter mAdapter;
+    private AttachmentChooserFragmentHost mHost;
+
+    @VisibleForTesting
+    Binding<DraftMessageData> mBinding = BindingBase.createBinding(this);
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.attachment_chooser_fragment, container, false);
+        mAttachmentGridView = (AttachmentGridView) view.findViewById(R.id.grid);
+        mAdapter = new AttachmentGridAdapter(getActivity());
+        mAttachmentGridView.setAdapter(mAdapter);
+        mAttachmentGridView.setHost(this);
+        setHasOptionsMenu(true);
+        return view;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mBinding.unbind();
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        inflater.inflate(R.menu.attachment_chooser_menu, menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_confirm_selection:
+                confirmSelection();
+                return true;
+
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    @VisibleForTesting
+    void confirmSelection() {
+        if (mBinding.isBound()) {
+            mBinding.getData().removeExistingAttachments(
+                    mAttachmentGridView.getUnselectedAttachments());
+            mBinding.getData().saveToStorage(mBinding);
+            mHost.onConfirmSelection();
+        }
+    }
+
+    public void setConversationId(final String conversationId) {
+        mBinding.bind(DataModel.get().createDraftMessageData(conversationId));
+        mBinding.getData().addListener(this);
+        mBinding.getData().loadFromStorage(mBinding, null, false);
+    }
+
+    public void setHost(final AttachmentChooserFragmentHost host) {
+        mHost = host;
+    }
+
+    @Override
+    public void onDraftChanged(final DraftMessageData data, final int changeFlags) {
+        mBinding.ensureBound(data);
+        if ((changeFlags & DraftMessageData.ATTACHMENTS_CHANGED) ==
+                DraftMessageData.ATTACHMENTS_CHANGED) {
+            mAdapter.onAttachmentsLoaded(data.getReadOnlyAttachments());
+        }
+    }
+
+    @Override
+    public void onDraftAttachmentLimitReached(final DraftMessageData data) {
+        // Do nothing since the user is in the process of unselecting attachments.
+    }
+
+    @Override
+    public void onDraftAttachmentLoadFailed() {
+        // Do nothing since the user is in the process of unselecting attachments.
+    }
+
+    @Override
+    public void displayPhoto(final Rect viewRect, final Uri photoUri) {
+        final Uri imagesUri = MessagingContentProvider.buildDraftImagesUri(
+                mBinding.getData().getConversationId());
+        UIIntents.get().launchFullScreenPhotoViewer(
+                getActivity(), photoUri, viewRect, imagesUri);
+    }
+
+    @Override
+    public void updateSelectionCount(int count) {
+        if (getActivity() instanceof BugleActionBarActivity) {
+            final ActionBar actionBar = ((BugleActionBarActivity) getActivity())
+                    .getSupportActionBar();
+            if (actionBar != null) {
+                actionBar.setTitle(getResources().getString(
+                        R.string.attachment_chooser_selection, count));
+            }
+        }
+    }
+
+    class AttachmentGridAdapter extends ArrayAdapter<MessagePartData> {
+        public AttachmentGridAdapter(final Context context) {
+            super(context, R.layout.attachment_grid_item_view, new ArrayList<MessagePartData>());
+        }
+
+        public void onAttachmentsLoaded(final List<MessagePartData> attachments) {
+            clear();
+            addAll(attachments);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public View getView(final int position, final View convertView, final ViewGroup parent) {
+            AttachmentGridItemView itemView;
+            final MessagePartData item = getItem(position);
+            if (convertView != null && convertView instanceof AttachmentGridItemView) {
+                itemView = (AttachmentGridItemView) convertView;
+            } else {
+                final LayoutInflater inflater = (LayoutInflater) getContext()
+                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                itemView = (AttachmentGridItemView) inflater.inflate(
+                        R.layout.attachment_grid_item_view, parent, false);
+            }
+            itemView.bind(item, mAttachmentGridView);
+            return itemView;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/attachmentchooser/AttachmentGridItemView.java b/src/com/android/messaging/ui/attachmentchooser/AttachmentGridItemView.java
new file mode 100644
index 0000000..8bb7356
--- /dev/null
+++ b/src/com/android/messaging/ui/attachmentchooser/AttachmentGridItemView.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.attachmentchooser;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.FrameLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.AttachmentPreviewFactory;
+import com.android.messaging.util.Assert;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Shows an item in the attachment picker grid.
+ */
+public class AttachmentGridItemView extends FrameLayout {
+    public interface HostInterface {
+        boolean isItemSelected(MessagePartData attachment);
+        void onItemCheckedChanged(AttachmentGridItemView view, MessagePartData attachment);
+        void onItemClicked(AttachmentGridItemView view, MessagePartData attachment);
+    }
+
+    @VisibleForTesting
+    MessagePartData mAttachmentData;
+    private FrameLayout mAttachmentViewContainer;
+    private CheckBox mCheckBox;
+    private HostInterface mHostInterface;
+
+    public AttachmentGridItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mAttachmentViewContainer = (FrameLayout) findViewById(R.id.attachment_container);
+        mCheckBox = (CheckBox) findViewById(R.id.checkbox);
+        mCheckBox.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                mHostInterface.onItemCheckedChanged(AttachmentGridItemView.this, mAttachmentData);
+            }
+        });
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                mHostInterface.onItemClicked(AttachmentGridItemView.this, mAttachmentData);
+            }
+        });
+        addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                // Enlarge the clickable region for the checkbox.
+                final int touchAreaIncrease = getResources().getDimensionPixelOffset(
+                        R.dimen.attachment_grid_checkbox_area_increase);
+                final Rect region = new Rect();
+                mCheckBox.getHitRect(region);
+                region.inset(-touchAreaIncrease, -touchAreaIncrease);
+                setTouchDelegate(new TouchDelegate(region, mCheckBox));
+            }
+        });
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        // The grid view auto-fits the columns, so we want to let the height match the width
+        // to make the attachment preview square.
+        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
+    }
+
+    public void bind(final MessagePartData attachment, final HostInterface hostInterface) {
+        Assert.isTrue(attachment.isAttachment());
+        mHostInterface = hostInterface;
+        updateSelectedState();
+        if (mAttachmentData == null || !mAttachmentData.equals(attachment)) {
+            mAttachmentData = attachment;
+            updateAttachmentView();
+        }
+    }
+
+    @VisibleForTesting
+    HostInterface testGetHostInterface() {
+        return mHostInterface;
+    }
+
+    public void updateSelectedState() {
+        mCheckBox.setChecked(mHostInterface.isItemSelected(mAttachmentData));
+    }
+
+    private void updateAttachmentView() {
+        mAttachmentViewContainer.removeAllViews();
+        final LayoutInflater inflater = LayoutInflater.from(getContext());
+        final View attachmentView = AttachmentPreviewFactory.createAttachmentPreview(inflater,
+                mAttachmentData, mAttachmentViewContainer,
+                AttachmentPreviewFactory.TYPE_CHOOSER_GRID, true /* startImageRequest */, null);
+        mAttachmentViewContainer.addView(attachmentView);
+    }
+}
diff --git a/src/com/android/messaging/ui/attachmentchooser/AttachmentGridView.java b/src/com/android/messaging/ui/attachmentchooser/AttachmentGridView.java
new file mode 100644
index 0000000..abf61dc
--- /dev/null
+++ b/src/com/android/messaging/ui/attachmentchooser/AttachmentGridView.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.attachmentchooser;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.widget.GridView;
+
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentGridAdapter;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.UiUtils;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Displays a grid of attachment previews for the user to choose which to select/unselect
+ */
+public class AttachmentGridView extends GridView implements
+        AttachmentGridItemView.HostInterface {
+    public interface AttachmentGridHost {
+        void displayPhoto(final Rect viewRect, final Uri photoUri);
+        void updateSelectionCount(final int count);
+    }
+
+    // By default everything is selected so only need to keep track of the unselected set.
+    private final Set<MessagePartData> mUnselectedSet;
+    private AttachmentGridHost mHost;
+
+    public AttachmentGridView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mUnselectedSet = new HashSet<>();
+    }
+
+    public void setHost(final AttachmentGridHost host) {
+        mHost = host;
+    }
+
+    @Override
+    public boolean isItemSelected(final MessagePartData attachment) {
+        return !mUnselectedSet.contains(attachment);
+    }
+
+    @Override
+    public void onItemClicked(final AttachmentGridItemView view, final MessagePartData attachment) {
+        // If the item is an image, show the photo viewer. All the other types (video, audio,
+        // vcard) have internal click handling for showing previews so we don't need to handle them
+        if (attachment.isImage()) {
+            mHost.displayPhoto(UiUtils.getMeasuredBoundsOnScreen(view), attachment.getContentUri());
+        }
+    }
+
+    @Override
+    public void onItemCheckedChanged(AttachmentGridItemView view, MessagePartData attachment) {
+        // Toggle selection.
+        if (isItemSelected(attachment)) {
+            mUnselectedSet.add(attachment);
+        } else {
+            mUnselectedSet.remove(attachment);
+        }
+        view.updateSelectedState();
+        updateSelectionCount();
+    }
+
+    public Set<MessagePartData> getUnselectedAttachments() {
+        return Collections.unmodifiableSet(mUnselectedSet);
+    }
+
+    private void updateSelectionCount() {
+        final int count = getAdapter().getCount() - mUnselectedSet.size();
+        Assert.isTrue(count >= 0);
+        mHost.updateSelectionCount(count);
+    }
+
+    private void refreshViews() {
+        if (getAdapter() instanceof AttachmentGridAdapter) {
+            ((AttachmentGridAdapter) getAdapter()).notifyDataSetChanged();
+        }
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        final SavedState savedState = new SavedState(superState);
+        savedState.unselectedParts = mUnselectedSet
+                .toArray(new MessagePartData[mUnselectedSet.size()]);
+        return savedState;
+    }
+
+    @Override
+    public void onRestoreInstanceState(final Parcelable state) {
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        final SavedState savedState = (SavedState) state;
+        super.onRestoreInstanceState(savedState.getSuperState());
+        mUnselectedSet.clear();
+        for (int i = 0; i < savedState.unselectedParts.length; i++) {
+            final MessagePartData unselectedPart = savedState.unselectedParts[i];
+            mUnselectedSet.add(unselectedPart);
+        }
+        refreshViews();
+    }
+
+    /**
+     * Persists the item selection state to saved instance state so we can restore on activity
+     * recreation
+     */
+    public static class SavedState extends BaseSavedState {
+        MessagePartData[] unselectedParts;
+
+        SavedState(final Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(final Parcel in) {
+            super(in);
+
+            // Read parts
+            final int partCount = in.readInt();
+            unselectedParts = new MessagePartData[partCount];
+            for (int i = 0; i < partCount; i++) {
+                unselectedParts[i] = ((MessagePartData) in.readParcelable(
+                        MessagePartData.class.getClassLoader()));
+            }
+        }
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            super.writeToParcel(out, flags);
+
+            // Write parts
+            out.writeInt(unselectedParts.length);
+            for (final MessagePartData image : unselectedParts) {
+                out.writeParcelable(image, flags);
+            }
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(final Parcel in) {
+                return new SavedState(in);
+            }
+            @Override
+            public SavedState[] newArray(final int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/AddContactsConfirmationDialog.java b/src/com/android/messaging/ui/contact/AddContactsConfirmationDialog.java
new file mode 100644
index 0000000..9c1393d
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/AddContactsConfirmationDialog.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.AccessibilityUtil;
+
+public class AddContactsConfirmationDialog implements DialogInterface.OnClickListener {
+    private final Context mContext;
+    private final Uri mAvatarUri;
+    private final String mNormalizedDestination;
+
+    public AddContactsConfirmationDialog(final Context context, final Uri avatarUri,
+            final String normalizedDestination) {
+        mContext = context;
+        mAvatarUri = avatarUri;
+        mNormalizedDestination = normalizedDestination;
+    }
+
+    public void show() {
+        final int confirmAddContactStringId = R.string.add_contact_confirmation;
+        final int cancelStringId = android.R.string.cancel;
+        final AlertDialog alertDialog = new AlertDialog.Builder(mContext)
+        .setTitle(R.string.add_contact_confirmation_dialog_title)
+        .setView(createBodyView())
+        .setPositiveButton(confirmAddContactStringId, this)
+        .setNegativeButton(cancelStringId, null)
+        .create();
+        alertDialog.show();
+        final Resources resources = mContext.getResources();
+        final Button cancelButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
+        if (cancelButton != null) {
+            cancelButton.setTextColor(resources.getColor(R.color.contact_picker_button_text_color));
+        }
+        final Button addButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        if (addButton != null) {
+            addButton.setTextColor(resources.getColor(R.color.contact_picker_button_text_color));
+        }
+    }
+
+    @Override
+    public void onClick(final DialogInterface dialog, final int which) {
+        UIIntents.get().launchAddContactActivity(mContext, mNormalizedDestination);
+    }
+
+    private View createBodyView() {
+        final View view = LayoutInflater.from(mContext).inflate(
+                R.layout.add_contacts_confirmation_dialog_body, null);
+        final ContactIconView iconView = (ContactIconView) view.findViewById(R.id.contact_icon);
+        iconView.setImageResourceUri(mAvatarUri);
+        final TextView textView = (TextView) view.findViewById(R.id.participant_name);
+        textView.setText(mNormalizedDestination);
+        // Accessibility reason : in case phone numbers are mixed in the display name,
+        // we need to vocalize it for talkback.
+        final String vocalizedDisplayName = AccessibilityUtil.getVocalizedPhoneNumber(
+                mContext.getResources(), mNormalizedDestination);
+        textView.setContentDescription(vocalizedDisplayName);
+        return view;
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/AllContactsListViewHolder.java b/src/com/android/messaging/ui/contact/AllContactsListViewHolder.java
new file mode 100644
index 0000000..7263c54
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/AllContactsListViewHolder.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.CustomHeaderPagerListViewHolder;
+import com.android.messaging.ui.contact.ContactListItemView.HostInterface;
+
+/**
+ * Holds the all contacts view for the contact picker's view pager.
+ */
+public class AllContactsListViewHolder extends CustomHeaderPagerListViewHolder {
+    public AllContactsListViewHolder(final Context context, final HostInterface clivHostInterface) {
+        super(context, new ContactListAdapter(context, null, clivHostInterface,
+                true /* needAlphabetHeader */));
+    }
+
+    @Override
+    protected int getLayoutResId() {
+        return R.layout.all_contacts_list_view;
+    }
+
+    @Override
+    protected int getPageTitleResId() {
+        return R.string.contact_picker_all_contacts_tab_title;
+    }
+
+    @Override
+    protected int getEmptyViewResId() {
+        return R.id.empty_view;
+    }
+
+    @Override
+    protected int getListViewResId() {
+        return R.id.all_contacts_list;
+    }
+
+    @Override
+    protected int getEmptyViewTitleResId() {
+        return R.string.contact_list_empty_text;
+    }
+
+    @Override
+    protected int getEmptyViewImageResId() {
+        return R.drawable.ic_oobe_freq_list;
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactDropdownLayouter.java b/src/com/android/messaging/ui/contact/ContactDropdownLayouter.java
new file mode 100644
index 0000000..0caf6b7
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactDropdownLayouter.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.graphics.drawable.StateListDrawable;
+import android.net.Uri;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.ex.chips.DropdownChipLayouter;
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ContactRecipientEntryUtils;
+import com.android.messaging.util.ContactUtil;
+
+/**
+ * An implementation for {@link DropdownChipLayouter}. Layouts the dropdown
+ * list in the ContactRecipientAutoCompleteView in Material style.
+ */
+public class ContactDropdownLayouter extends DropdownChipLayouter {
+    private final ContactListItemView.HostInterface mClivHostInterface;
+
+    public ContactDropdownLayouter(final LayoutInflater inflater, final Context context,
+            final ContactListItemView.HostInterface clivHostInterface) {
+        super(inflater, context);
+        mClivHostInterface = new ContactListItemView.HostInterface() {
+
+            @Override
+            public void onContactListItemClicked(final ContactListItemData item,
+                    final ContactListItemView view) {
+                // The chips UI will handle auto-complete item click events, so No-op here.
+            }
+
+            @Override
+            public boolean isContactSelected(final ContactListItemData item) {
+                // In chips drop down we don't show any selected checkmark per design.
+                return false;
+            }
+        };
+    }
+
+    /**
+     * Bind a drop down view to a RecipientEntry. We'd like regular dropdown items (BASE_RECIPIENT)
+     * to behave the same as regular ContactListItemViews, while using the chips library's
+     * item styling for alternates dropdown items (happens when you click on a chip).
+     */
+    @Override
+    public View bindView(final View convertView, final ViewGroup parent, final RecipientEntry entry,
+            final int position, AdapterType type, final String substring,
+            final StateListDrawable deleteDrawable) {
+        if (type != AdapterType.BASE_RECIPIENT) {
+            if (type == AdapterType.SINGLE_RECIPIENT) {
+                // Treat single recipients the same way as alternates. The base implementation of
+                // single recipients would try to simplify the destination by tokenizing. We'd
+                // like to always show the full destination address per design request.
+                type = AdapterType.RECIPIENT_ALTERNATES;
+            }
+            return super.bindView(convertView, parent, entry, position, type, substring,
+                    deleteDrawable);
+        }
+
+        // Default to show all the information
+        // RTL : To format contact name and detail if they happen to be phone numbers.
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+        final String displayName = bidiFormatter.unicodeWrap(
+                ContactRecipientEntryUtils.getDisplayNameForContactList(entry),
+                TextDirectionHeuristicsCompat.LTR);
+        final String destination = bidiFormatter.unicodeWrap(
+                ContactRecipientEntryUtils.formatDestination(entry),
+                TextDirectionHeuristicsCompat.LTR);
+        final View itemView = reuseOrInflateView(convertView, parent, type);
+
+        // Bold the string that is matched.
+        final CharSequence[] styledResults =
+                getStyledResults(substring, displayName, destination);
+
+        Assert.isTrue(itemView instanceof ContactListItemView);
+        final ContactListItemView contactListItemView = (ContactListItemView) itemView;
+        contactListItemView.setImageClickHandlerDisabled(true);
+        boolean isWorkContact = ContactUtil.isEnterpriseContactId(entry.getContactId());
+        contactListItemView.bind(entry, styledResults[0], styledResults[1],
+                mClivHostInterface, (type == AdapterType.SINGLE_RECIPIENT), isWorkContact);
+        return itemView;
+    }
+
+    @Override
+    protected void bindIconToView(boolean showImage, RecipientEntry entry, ImageView view,
+            AdapterType type) {
+        if (showImage && view instanceof ContactIconView) {
+            final ContactIconView contactView = (ContactIconView) view;
+            // These show contact cards by default, but that isn't what we want here
+            contactView.setImageClickHandlerDisabled(true);
+            final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                    ParticipantData.getFromRecipientEntry(entry));
+            contactView.setImageResourceUri(avatarUri);
+        } else {
+            super.bindIconToView(showImage, entry, view, type);
+        }
+    }
+
+    @Override
+    protected int getItemLayoutResId(AdapterType type) {
+        switch (type) {
+            case BASE_RECIPIENT:
+                return R.layout.contact_list_item_view;
+            case RECIPIENT_ALTERNATES:
+                return R.layout.chips_alternates_dropdown_item;
+            default:
+                return R.layout.chips_alternates_dropdown_item;
+        }
+    }
+
+    @Override
+    protected int getAlternateItemLayoutResId(AdapterType type) {
+        return getItemLayoutResId(type);
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactListAdapter.java b/src/com/android/messaging/ui/contact/ContactListAdapter.java
new file mode 100644
index 0000000..d466b61
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactListAdapter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.SectionIndexer;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+
+public class ContactListAdapter extends CursorAdapter implements SectionIndexer {
+    private final ContactListItemView.HostInterface mClivHostInterface;
+    private final boolean mNeedAlphabetHeader;
+    private ContactSectionIndexer mSectionIndexer;
+
+    public ContactListAdapter(final Context context, final Cursor cursor,
+            final ContactListItemView.HostInterface clivHostInterface,
+            final boolean needAlphabetHeader) {
+        super(context, cursor, 0);
+        mClivHostInterface = clivHostInterface;
+        mNeedAlphabetHeader = needAlphabetHeader;
+        mSectionIndexer = new ContactSectionIndexer(cursor);
+    }
+
+    @Override
+    public void bindView(final View view, final Context context, final Cursor cursor) {
+        Assert.isTrue(view instanceof ContactListItemView);
+        final ContactListItemView contactListItemView = (ContactListItemView) view;
+        String alphabetHeader = null;
+        if (mNeedAlphabetHeader) {
+            final int position = cursor.getPosition();
+            final int section = mSectionIndexer.getSectionForPosition(position);
+            // Check if the position is the first in the section.
+            if (mSectionIndexer.getPositionForSection(section) == position) {
+                alphabetHeader = (String) mSectionIndexer.getSections()[section];
+            }
+        }
+        contactListItemView.bind(cursor, mClivHostInterface, mNeedAlphabetHeader, alphabetHeader);
+    }
+
+    @Override
+    public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(context);
+        return layoutInflater.inflate(R.layout.contact_list_item_view, parent, false);
+    }
+
+    @Override
+    public Cursor swapCursor(final Cursor newCursor) {
+        mSectionIndexer = new ContactSectionIndexer(newCursor);
+        return super.swapCursor(newCursor);
+    }
+
+    @Override
+    public Object[] getSections() {
+        return mSectionIndexer.getSections();
+    }
+
+    @Override
+    public int getPositionForSection(final int sectionIndex) {
+        return mSectionIndexer.getPositionForSection(sectionIndex);
+    }
+
+    @Override
+    public int getSectionForPosition(final int position) {
+        return mSectionIndexer.getSectionForPosition(position);
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactListItemView.java b/src/com/android/messaging/ui/contact/ContactListItemView.java
new file mode 100644
index 0000000..b0e8957
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactListItemView.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * The view for a single entry in a contact list.
+ */
+public class ContactListItemView extends LinearLayout implements OnClickListener {
+    public interface HostInterface {
+        void onContactListItemClicked(ContactListItemData item, ContactListItemView view);
+        boolean isContactSelected(ContactListItemData item);
+    }
+
+    @VisibleForTesting
+    final ContactListItemData mData;
+    private TextView mContactNameTextView;
+    private TextView mContactDetailsTextView;
+    private TextView mContactDetailTypeTextView;
+    private TextView mAlphabetHeaderTextView;
+    private ContactIconView mContactIconView;
+    private ImageView mContactCheckmarkView;
+    private ImageView mWorkProfileIcon;
+    private HostInterface mHostInterface;
+    private boolean mShouldShowAlphabetHeader;
+
+    public ContactListItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mData = DataModel.get().createContactListItemData();
+    }
+
+    @Override
+    protected void onFinishInflate () {
+        mContactNameTextView = (TextView) findViewById(R.id.contact_name);
+        mContactDetailsTextView = (TextView) findViewById(R.id.contact_details);
+        mContactDetailTypeTextView = (TextView) findViewById(R.id.contact_detail_type);
+        mAlphabetHeaderTextView = (TextView) findViewById(R.id.alphabet_header);
+        mContactIconView = (ContactIconView) findViewById(R.id.contact_icon);
+        mContactCheckmarkView = (ImageView) findViewById(R.id.contact_checkmark);
+        mWorkProfileIcon = (ImageView) findViewById(R.id.work_profile_icon);
+    }
+
+    /**
+     * Fills in the data associated with this view by binding to a contact cursor provided by
+     * ContactUtil.
+     * @param cursor the contact cursor.
+     * @param hostInterface host interface to this view.
+     * @param shouldShowAlphabetHeader whether an alphabetical header should shown on the side
+     *        of this view. If {@code headerLabel} is empty, we will still leave space for it.
+     * @param headerLabel the alphabetical header on the side of this view, if it should be shown.
+     */
+    public void bind(final Cursor cursor, final HostInterface hostInterface,
+            final boolean shouldShowAlphabetHeader, final String headerLabel) {
+        mData.bind(cursor, headerLabel);
+        mHostInterface = hostInterface;
+        mShouldShowAlphabetHeader = shouldShowAlphabetHeader;
+        setOnClickListener(this);
+        updateViewAppearance();
+    }
+
+    /**
+     * Binds a RecipientEntry. This is used by the chips text view's dropdown layout.
+     * @param recipientEntry the source RecipientEntry provided by ContactDropdownLayouter, which
+     *        was in turn directly from one of the existing chips, or from filtered results
+     *        generated by ContactRecipientAdapter.
+     * @param styledName display name where the portion that matches the search text is bold.
+     * @param styledDestination number where the portion that matches the search text is bold.
+     * @param hostInterface host interface to this view.
+     * @param isSingleRecipient whether this item is shown as the only line item in the single
+     *        recipient drop down from the chips view. If this is the case, we always show the
+     *        contact avatar even if it's not a first-level entry.
+     * @param isWorkContact whether the contact is in managed profile.
+     */
+    public void bind(final RecipientEntry recipientEntry, final CharSequence styledName,
+            final CharSequence styledDestination, final HostInterface hostInterface,
+            final boolean isSingleRecipient, final boolean isWorkContact) {
+        mData.bind(recipientEntry, styledName, styledDestination, isSingleRecipient, isWorkContact);
+        mHostInterface = hostInterface;
+        mShouldShowAlphabetHeader = false;
+        updateViewAppearance();
+    }
+
+    private void updateViewAppearance() {
+        mContactNameTextView.setText(mData.getDisplayName());
+        mContactDetailsTextView.setText(mData.getDestination());
+        mContactDetailTypeTextView.setText(Phone.getTypeLabel(getResources(),
+                mData.getDestinationType(), mData.getDestinationLabel()));
+        final RecipientEntry recipientEntry = mData.getRecipientEntry();
+        final String destinationString = String.valueOf(mData.getDestination());
+        if (mData.getIsSimpleContactItem()) {
+            // This is a special number-with-avatar type of contact (for unknown contact chips
+            // and for direct "send to destination" item). In this case, make sure we only show
+            // the display name (phone number) and the avatar and hide everything else.
+            final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                    ParticipantData.getFromRecipientEntry(recipientEntry));
+            mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(),
+                    mData.getLookupKey(), destinationString);
+            mContactIconView.setVisibility(VISIBLE);
+            mContactCheckmarkView.setVisibility(GONE);
+            mContactDetailTypeTextView.setVisibility(GONE);
+            mContactDetailsTextView.setVisibility(GONE);
+            mContactNameTextView.setVisibility(VISIBLE);
+        } else if (mData.getIsFirstLevel()) {
+            final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                    ParticipantData.getFromRecipientEntry(recipientEntry));
+            mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(),
+                    mData.getLookupKey(), destinationString);
+            mContactIconView.setVisibility(VISIBLE);
+            mContactNameTextView.setVisibility(VISIBLE);
+            final boolean isSelected = mHostInterface.isContactSelected(mData);
+            setSelected(isSelected);
+            mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE);
+            mContactDetailsTextView.setVisibility(VISIBLE);
+            mContactDetailTypeTextView.setVisibility(VISIBLE);
+        } else {
+            mContactIconView.setImageResourceUri(null);
+            mContactIconView.setVisibility(INVISIBLE);
+            mContactNameTextView.setVisibility(GONE);
+            final boolean isSelected = mHostInterface.isContactSelected(mData);
+            setSelected(isSelected);
+            mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE);
+            mContactDetailsTextView.setVisibility(VISIBLE);
+            mContactDetailTypeTextView.setVisibility(VISIBLE);
+        }
+        if (mData.getIsWorkContact()) {
+            mWorkProfileIcon.setVisibility(VISIBLE);
+        } else {
+            mWorkProfileIcon.setVisibility(GONE);
+        }
+        if (mShouldShowAlphabetHeader) {
+            mAlphabetHeaderTextView.setVisibility(VISIBLE);
+            mAlphabetHeaderTextView.setText(mData.getAlphabetHeader());
+        } else {
+            mAlphabetHeaderTextView.setVisibility(GONE);
+        }
+    }
+
+    /**
+     * {@inheritDoc} from OnClickListener
+     */
+    @Override
+    public void onClick(final View v) {
+        Assert.isTrue(v == this);
+        Assert.isTrue(mHostInterface != null);
+        mHostInterface.onContactListItemClicked(mData, this);
+    }
+
+    public void setImageClickHandlerDisabled(final boolean isHandlerDisabled) {
+        mContactIconView.setImageClickHandlerDisabled(isHandlerDisabled);
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactPickerFragment.java b/src/com/android/messaging/ui/contact/ContactPickerFragment.java
new file mode 100644
index 0000000..e201074
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactPickerFragment.java
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.contact;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.widget.Toolbar;
+import androidx.appcompat.widget.Toolbar.OnMenuItemClickListener;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.transition.Explode;
+import android.transition.Transition;
+import android.transition.Transition.EpicenterCallback;
+import android.transition.TransitionManager;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.action.ActionMonitor;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ContactPickerData;
+import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.ui.CustomHeaderPagerViewHolder;
+import com.android.messaging.ui.CustomHeaderViewPager;
+import com.android.messaging.ui.animation.ViewGroupItemVerticalExplodeAnimation;
+import com.android.messaging.ui.contact.ContactRecipientAutoCompleteView.ContactChipsChangeListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.RunsOnMainThread;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+
+/**
+ * Shows lists of contacts to start conversations with.
+ */
+public class ContactPickerFragment extends Fragment implements ContactPickerDataListener,
+        ContactListItemView.HostInterface, ContactChipsChangeListener, OnMenuItemClickListener,
+        GetOrCreateConversationActionListener {
+    public static final String FRAGMENT_TAG = "contactpicker";
+
+    // Undefined contact picker mode. We should never be in this state after the host activity has
+    // been created.
+    public static final int MODE_UNDEFINED = 0;
+
+    // The initial contact picker mode for starting a new conversation with one contact.
+    public static final int MODE_PICK_INITIAL_CONTACT = 1;
+
+    // The contact picker mode where one initial contact has been picked and we are showing
+    // only the chips edit box.
+    public static final int MODE_CHIPS_ONLY = 2;
+
+    // The contact picker mode for picking more contacts after starting the initial 1-1.
+    public static final int MODE_PICK_MORE_CONTACTS = 3;
+
+    // The contact picker mode when max number of participants is reached.
+    public static final int MODE_PICK_MAX_PARTICIPANTS = 4;
+
+    public interface ContactPickerFragmentHost {
+        void onGetOrCreateNewConversation(String conversationId);
+        void onBackButtonPressed();
+        void onInitiateAddMoreParticipants();
+        void onParticipantCountChanged(boolean canAddMoreParticipants);
+        void invalidateActionBar();
+    }
+
+    @VisibleForTesting
+    final Binding<ContactPickerData> mBinding = BindingBase.createBinding(this);
+
+    private ContactPickerFragmentHost mHost;
+    private ContactRecipientAutoCompleteView mRecipientTextView;
+    private CustomHeaderViewPager mCustomHeaderViewPager;
+    private AllContactsListViewHolder mAllContactsListViewHolder;
+    private FrequentContactsListViewHolder mFrequentContactsListViewHolder;
+    private View mRootView;
+    private View mPendingExplodeView;
+    private View mComposeDivider;
+    private Toolbar mToolbar;
+    private int mContactPickingMode = MODE_UNDEFINED;
+
+    // Keeps track of the currently selected phone numbers in the chips view to enable fast lookup.
+    private Set<String> mSelectedPhoneNumbers = null;
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAllContactsListViewHolder = new AllContactsListViewHolder(getActivity(), this);
+        mFrequentContactsListViewHolder = new FrequentContactsListViewHolder(getActivity(), this);
+
+        if (ContactUtil.hasReadContactsPermission()) {
+            mBinding.bind(DataModel.get().createContactPickerData(getActivity(), this));
+            mBinding.getData().init(getLoaderManager(), mBinding);
+        }
+    }
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.contact_picker_fragment, container, false);
+        mRecipientTextView = (ContactRecipientAutoCompleteView)
+                view.findViewById(R.id.recipient_text_view);
+        mRecipientTextView.setThreshold(0);
+        mRecipientTextView.setDropDownAnchor(R.id.compose_contact_divider);
+
+        mRecipientTextView.setContactChipsListener(this);
+        mRecipientTextView.setDropdownChipLayouter(new ContactDropdownLayouter(inflater,
+                getActivity(), this));
+        mRecipientTextView.setAdapter(new ContactRecipientAdapter(getActivity(), this));
+        mRecipientTextView.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void onTextChanged(final CharSequence s, final int start, final int before,
+                    final int count) {
+            }
+
+            @Override
+            public void beforeTextChanged(final CharSequence s, final int start, final int count,
+                    final int after) {
+            }
+
+            @Override
+            public void afterTextChanged(final Editable s) {
+                updateTextInputButtonsVisibility();
+            }
+        });
+
+        final CustomHeaderPagerViewHolder[] viewHolders = {
+                mFrequentContactsListViewHolder,
+                mAllContactsListViewHolder };
+
+        mCustomHeaderViewPager = (CustomHeaderViewPager) view.findViewById(R.id.contact_pager);
+        mCustomHeaderViewPager.setViewHolders(viewHolders);
+        mCustomHeaderViewPager.setViewPagerTabHeight(CustomHeaderViewPager.DEFAULT_TAB_STRIP_SIZE);
+        mCustomHeaderViewPager.setBackgroundColor(getResources()
+                .getColor(R.color.contact_picker_background));
+
+        // The view pager defaults to the frequent contacts page.
+        mCustomHeaderViewPager.setCurrentItem(0);
+
+        mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
+        mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_light);
+        mToolbar.setNavigationContentDescription(R.string.back);
+        mToolbar.setNavigationOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                mHost.onBackButtonPressed();
+            }
+        });
+
+        mToolbar.inflateMenu(R.menu.compose_menu);
+        mToolbar.setOnMenuItemClickListener(this);
+
+        mComposeDivider = view.findViewById(R.id.compose_contact_divider);
+        mRootView = view;
+        return view;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Called when the host activity has been created. At this point, the host activity should
+     * have set the contact picking mode for us so that we may update our visuals.
+     */
+    @Override
+    public void onActivityCreated(final Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        Assert.isTrue(mContactPickingMode != MODE_UNDEFINED);
+        updateVisualsForContactPickingMode(false /* animate */);
+        mHost.invalidateActionBar();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        // We could not have bound to the data if the permission was denied.
+        if (mBinding.isBound()) {
+            mBinding.unbind();
+        }
+
+        if (mMonitor != null) {
+            mMonitor.unregister();
+        }
+        mMonitor = null;
+    }
+
+    @Override
+    public boolean onMenuItemClick(final MenuItem menuItem) {
+        switch (menuItem.getItemId()) {
+            case R.id.action_ime_dialpad_toggle:
+                final int baseInputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+                if ((mRecipientTextView.getInputType() & InputType.TYPE_CLASS_PHONE) !=
+                        InputType.TYPE_CLASS_PHONE) {
+                    mRecipientTextView.setInputType(baseInputType | InputType.TYPE_CLASS_PHONE);
+                    menuItem.setIcon(R.drawable.ic_ime_light);
+                } else {
+                    mRecipientTextView.setInputType(baseInputType | InputType.TYPE_CLASS_TEXT);
+                    menuItem.setIcon(R.drawable.ic_numeric_dialpad);
+                }
+                ImeUtil.get().showImeKeyboard(getActivity(), mRecipientTextView);
+                return true;
+
+            case R.id.action_add_more_participants:
+                mHost.onInitiateAddMoreParticipants();
+                return true;
+
+            case R.id.action_confirm_participants:
+                maybeGetOrCreateConversation();
+                return true;
+
+            case R.id.action_delete_text:
+                Assert.equals(MODE_PICK_INITIAL_CONTACT, mContactPickingMode);
+                mRecipientTextView.setText("");
+                return true;
+        }
+        return false;
+    }
+
+    @Override // From ContactPickerDataListener
+    public void onAllContactsCursorUpdated(final Cursor data) {
+        mBinding.ensureBound();
+        mAllContactsListViewHolder.onContactsCursorUpdated(data);
+    }
+
+    @Override // From ContactPickerDataListener
+    public void onFrequentContactsCursorUpdated(final Cursor data) {
+        mBinding.ensureBound();
+        mFrequentContactsListViewHolder.onContactsCursorUpdated(data);
+        if (data != null && data.getCount() == 0) {
+            // Show the all contacts list when there's no frequents.
+            mCustomHeaderViewPager.setCurrentItem(1);
+        }
+    }
+
+    @Override // From ContactListItemView.HostInterface
+    public void onContactListItemClicked(final ContactListItemData item,
+            final ContactListItemView view) {
+        if (!isContactSelected(item)) {
+            if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) {
+                mPendingExplodeView = view;
+            }
+            mRecipientTextView.appendRecipientEntry(item.getRecipientEntry());
+        } else if (mContactPickingMode != MODE_PICK_INITIAL_CONTACT) {
+            mRecipientTextView.removeRecipientEntry(item.getRecipientEntry());
+        }
+    }
+
+    @Override // From ContactListItemView.HostInterface
+    public boolean isContactSelected(final ContactListItemData item) {
+        return mSelectedPhoneNumbers != null &&
+                mSelectedPhoneNumbers.contains(PhoneUtils.getDefault().getCanonicalBySystemLocale(
+                        item.getRecipientEntry().getDestination()));
+    }
+
+    /**
+     * Call this immediately after attaching the fragment, or when there's a ui state change that
+     * changes our host (i.e. restore from saved instance state).
+     */
+    public void setHost(final ContactPickerFragmentHost host) {
+        mHost = host;
+    }
+
+    public void setContactPickingMode(final int mode, final boolean animate) {
+        if (mContactPickingMode != mode) {
+            // Guard against impossible transitions.
+            Assert.isTrue(
+                    // We may start from undefined mode to any mode when we are restoring state.
+                    (mContactPickingMode == MODE_UNDEFINED) ||
+                    (mContactPickingMode == MODE_PICK_INITIAL_CONTACT && mode == MODE_CHIPS_ONLY) ||
+                    (mContactPickingMode == MODE_CHIPS_ONLY && mode == MODE_PICK_MORE_CONTACTS) ||
+                    (mContactPickingMode == MODE_PICK_MORE_CONTACTS
+                            && mode == MODE_PICK_MAX_PARTICIPANTS) ||
+                    (mContactPickingMode == MODE_PICK_MAX_PARTICIPANTS
+                            && mode == MODE_PICK_MORE_CONTACTS));
+
+            mContactPickingMode = mode;
+            updateVisualsForContactPickingMode(animate);
+        }
+    }
+
+    private void showImeKeyboard() {
+        Assert.notNull(mRecipientTextView);
+        mRecipientTextView.requestFocus();
+
+        // showImeKeyboard() won't work until the layout is ready, so wait until layout is complete
+        // before showing the soft keyboard.
+        UiUtils.doOnceAfterLayoutChange(mRootView, new Runnable() {
+            @Override
+            public void run() {
+                final Activity activity = getActivity();
+                if (activity != null) {
+                    ImeUtil.get().showImeKeyboard(activity, mRecipientTextView);
+                }
+            }
+        });
+        mRecipientTextView.invalidate();
+    }
+
+    private void updateVisualsForContactPickingMode(final boolean animate) {
+        // Don't update visuals if the visuals haven't been inflated yet.
+        if (mRootView != null) {
+            final Menu menu = mToolbar.getMenu();
+            final MenuItem addMoreParticipantsItem = menu.findItem(
+                    R.id.action_add_more_participants);
+            final MenuItem confirmParticipantsItem = menu.findItem(
+                    R.id.action_confirm_participants);
+            switch (mContactPickingMode) {
+                case MODE_PICK_INITIAL_CONTACT:
+                    addMoreParticipantsItem.setVisible(false);
+                    confirmParticipantsItem.setVisible(false);
+                    mCustomHeaderViewPager.setVisibility(View.VISIBLE);
+                    mComposeDivider.setVisibility(View.INVISIBLE);
+                    mRecipientTextView.setEnabled(true);
+                    showImeKeyboard();
+                    break;
+
+                case MODE_CHIPS_ONLY:
+                    if (animate) {
+                        if (mPendingExplodeView == null) {
+                            // The user didn't click on any contact item, so use the toolbar as
+                            // the view to "explode."
+                            mPendingExplodeView = mToolbar;
+                        }
+                        startExplodeTransitionForContactLists(false /* show */);
+
+                        ViewGroupItemVerticalExplodeAnimation.startAnimationForView(
+                                mCustomHeaderViewPager, mPendingExplodeView, mRootView,
+                                true /* snapshotView */, UiUtils.COMPOSE_TRANSITION_DURATION);
+                        showHideContactPagerWithAnimation(false /* show */);
+                    } else {
+                        mCustomHeaderViewPager.setVisibility(View.GONE);
+                    }
+
+                    addMoreParticipantsItem.setVisible(true);
+                    confirmParticipantsItem.setVisible(false);
+                    mComposeDivider.setVisibility(View.VISIBLE);
+                    mRecipientTextView.setEnabled(true);
+                    break;
+
+                case MODE_PICK_MORE_CONTACTS:
+                    if (animate) {
+                        // Correctly set the start visibility state for the view pager and
+                        // individual list items (hidden initially), so that the transition
+                        // manager can properly track the visibility change for the explode.
+                        mCustomHeaderViewPager.setVisibility(View.VISIBLE);
+                        toggleContactListItemsVisibilityForPendingTransition(false /* show */);
+                        startExplodeTransitionForContactLists(true /* show */);
+                    }
+                    addMoreParticipantsItem.setVisible(false);
+                    confirmParticipantsItem.setVisible(true);
+                    mCustomHeaderViewPager.setVisibility(View.VISIBLE);
+                    mComposeDivider.setVisibility(View.INVISIBLE);
+                    mRecipientTextView.setEnabled(true);
+                    showImeKeyboard();
+                    break;
+
+                case MODE_PICK_MAX_PARTICIPANTS:
+                    addMoreParticipantsItem.setVisible(false);
+                    confirmParticipantsItem.setVisible(true);
+                    mCustomHeaderViewPager.setVisibility(View.VISIBLE);
+                    mComposeDivider.setVisibility(View.INVISIBLE);
+                    // TODO: Verify that this is okay for accessibility
+                    mRecipientTextView.setEnabled(false);
+                    break;
+
+                default:
+                    Assert.fail("Unsupported contact picker mode!");
+                    break;
+            }
+            updateTextInputButtonsVisibility();
+        }
+    }
+
+    private void updateTextInputButtonsVisibility() {
+        final Menu menu = mToolbar.getMenu();
+        final MenuItem keypadToggleItem = menu.findItem(R.id.action_ime_dialpad_toggle);
+        final MenuItem deleteTextItem = menu.findItem(R.id.action_delete_text);
+        if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) {
+            if (TextUtils.isEmpty(mRecipientTextView.getText())) {
+                deleteTextItem.setVisible(false);
+                keypadToggleItem.setVisible(true);
+            } else {
+                deleteTextItem.setVisible(true);
+                keypadToggleItem.setVisible(false);
+            }
+        } else {
+            deleteTextItem.setVisible(false);
+            keypadToggleItem.setVisible(false);
+        }
+    }
+
+    private void maybeGetOrCreateConversation() {
+        final ArrayList<ParticipantData> participants =
+                mRecipientTextView.getRecipientParticipantDataForConversationCreation();
+        if (ContactPickerData.isTooManyParticipants(participants.size())) {
+            UiUtils.showToast(R.string.too_many_participants);
+        } else if (participants.size() > 0 && mMonitor == null) {
+            mMonitor = GetOrCreateConversationAction.getOrCreateConversation(participants,
+                    null, this);
+        }
+    }
+
+    /**
+     * Watches changes in contact chips to determine possible state transitions (e.g. creating
+     * the initial conversation, adding more participants or finish the current conversation)
+     */
+    @Override
+    public void onContactChipsChanged(final int oldCount, final int newCount) {
+        Assert.isTrue(oldCount != newCount);
+        if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) {
+            // Initial picking mode. Start a conversation once a recipient has been picked.
+            maybeGetOrCreateConversation();
+        } else if (mContactPickingMode == MODE_CHIPS_ONLY) {
+            // oldCount == 0 means we are restoring from savedInstanceState to add the existing
+            // chips, don't switch to "add more participants" mode in this case.
+            if (oldCount > 0 && mRecipientTextView.isFocused()) {
+                // Chips only mode. The user may have picked an additional contact or deleted the
+                // only existing contact. Either way, switch to picking more participants mode.
+                mHost.onInitiateAddMoreParticipants();
+            }
+        }
+        mHost.onParticipantCountChanged(ContactPickerData.getCanAddMoreParticipants(newCount));
+
+        // Refresh our local copy of the selected chips set to keep it up-to-date.
+        mSelectedPhoneNumbers =  mRecipientTextView.getSelectedDestinations();
+        invalidateContactLists();
+    }
+
+    /**
+     * Listens for notification that invalid contacts have been removed during resolving them.
+     * These contacts were not local contacts, valid email, or valid phone numbers
+     */
+    @Override
+    public void onInvalidContactChipsPruned(final int prunedCount) {
+        Assert.isTrue(prunedCount > 0);
+        UiUtils.showToast(R.plurals.add_invalid_contact_error, prunedCount);
+    }
+
+    /**
+     * Listens for notification that the user has pressed enter/done on the keyboard with all
+     * contacts in place and we should create or go to the existing conversation now
+     */
+    @Override
+    public void onEntryComplete() {
+        if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT ||
+                mContactPickingMode == MODE_PICK_MORE_CONTACTS ||
+                mContactPickingMode == MODE_PICK_MAX_PARTICIPANTS) {
+            // Avoid multiple calls to create in race cases (hit done right after selecting contact)
+            maybeGetOrCreateConversation();
+        }
+    }
+
+    private void invalidateContactLists() {
+        mAllContactsListViewHolder.invalidateList();
+        mFrequentContactsListViewHolder.invalidateList();
+    }
+
+    /**
+     * Kicks off a scene transition that animates visibility changes of individual contact list
+     * items via explode animation.
+     * @param show whether the contact lists are to be shown or hidden.
+     */
+    private void startExplodeTransitionForContactLists(final boolean show) {
+        if (!OsUtil.isAtLeastL()) {
+            // Explode animation is not supported pre-L.
+            return;
+        }
+        final Explode transition = new Explode();
+        final Rect epicenter = mPendingExplodeView == null ? null :
+            UiUtils.getMeasuredBoundsOnScreen(mPendingExplodeView);
+        transition.setDuration(UiUtils.COMPOSE_TRANSITION_DURATION);
+        transition.setInterpolator(UiUtils.EASE_IN_INTERPOLATOR);
+        transition.setEpicenterCallback(new EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(final Transition transition) {
+                return epicenter;
+            }
+        });
+
+        // Kick off the delayed scene explode transition. Anything happens after this line in this
+        // method before the next frame will be tracked by the transition manager for visibility
+        // changes and animated accordingly.
+        TransitionManager.beginDelayedTransition(mCustomHeaderViewPager,
+                transition);
+
+        toggleContactListItemsVisibilityForPendingTransition(show);
+    }
+
+    /**
+     * Toggle the visibility of contact list items in the contact lists for them to be tracked by
+     * the transition manager for pending explode transition.
+     */
+    private void toggleContactListItemsVisibilityForPendingTransition(final boolean show) {
+        if (!OsUtil.isAtLeastL()) {
+            // Explode animation is not supported pre-L.
+            return;
+        }
+        mAllContactsListViewHolder.toggleVisibilityForPendingTransition(show, mPendingExplodeView);
+        mFrequentContactsListViewHolder.toggleVisibilityForPendingTransition(show,
+                mPendingExplodeView);
+    }
+
+    private void showHideContactPagerWithAnimation(final boolean show) {
+        final boolean isPagerVisible = (mCustomHeaderViewPager.getVisibility() == View.VISIBLE);
+        if (show == isPagerVisible) {
+            return;
+        }
+
+        mCustomHeaderViewPager.animate().alpha(show ? 1F : 0F)
+            .setStartDelay(!show ? UiUtils.COMPOSE_TRANSITION_DURATION : 0)
+            .withStartAction(new Runnable() {
+                @Override
+                public void run() {
+                    mCustomHeaderViewPager.setVisibility(View.VISIBLE);
+                    mCustomHeaderViewPager.setAlpha(show ? 0F : 1F);
+                }
+            })
+            .withEndAction(new Runnable() {
+                @Override
+                public void run() {
+                    mCustomHeaderViewPager.setVisibility(show ? View.VISIBLE : View.GONE);
+                    mCustomHeaderViewPager.setAlpha(1F);
+                }
+            });
+    }
+
+    @Override
+    public void onContactCustomColorLoaded(final ContactPickerData data) {
+        mBinding.ensureBound(data);
+        invalidateContactLists();
+    }
+
+    public void updateActionBar(final ActionBar actionBar) {
+        // Hide the action bar for contact picker mode. The custom ToolBar containing chips UI
+        // etc. will take the spot of the action bar.
+        actionBar.hide();
+        UiUtils.setStatusBarColor(getActivity(),
+                getResources().getColor(R.color.compose_notification_bar_background));
+    }
+
+    private GetOrCreateConversationActionMonitor mMonitor;
+
+    @Override
+    @RunsOnMainThread
+    public void onGetOrCreateConversationSucceeded(final ActionMonitor monitor,
+            final Object data, final String conversationId) {
+        Assert.isTrue(monitor == mMonitor);
+        Assert.isTrue(conversationId != null);
+
+        mRecipientTextView.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE |
+                InputType.TYPE_CLASS_TEXT);
+        mHost.onGetOrCreateNewConversation(conversationId);
+
+        mMonitor = null;
+    }
+
+    @Override
+    @RunsOnMainThread
+    public void onGetOrCreateConversationFailed(final ActionMonitor monitor,
+            final Object data) {
+        Assert.isTrue(monitor == mMonitor);
+        LogUtil.e(LogUtil.BUGLE_TAG, "onGetOrCreateConversationFailed");
+        mMonitor = null;
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java b/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java
new file mode 100644
index 0000000..e330447
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MergeCursor;
+import androidx.core.util.Pair;
+import android.text.TextUtils;
+import android.text.util.Rfc822Token;
+import android.text.util.Rfc822Tokenizer;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Filter;
+import android.widget.TextView;
+
+import com.android.ex.chips.BaseRecipientAdapter;
+import com.android.ex.chips.RecipientAlternatesAdapter;
+import com.android.ex.chips.RecipientAlternatesAdapter.RecipientMatchCallback;
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.ContactRecipientEntryUtils;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * An extension on the base {@link BaseRecipientAdapter} that uses data layer from Bugle,
+ * such as the ContactRecipientPhotoManager that uses our own MediaResourceManager, and
+ * contact lookup that relies on ContactUtil. It provides data source and filtering ability
+ * for {@link ContactRecipientAutoCompleteView}
+ */
+public final class ContactRecipientAdapter extends BaseRecipientAdapter {
+    private static final int WORD_DIRECTORY_HEADER_POS_NONE = -1;
+    /**
+     * Stores the index of work directory header.
+     */
+    private int mWorkDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
+    private final LayoutInflater mInflater;
+
+    /**
+     * Type of directory entry.
+     */
+    private static final int ENTRY_TYPE_DIRECTORY = RecipientEntry.ENTRY_TYPE_SIZE;
+
+    public ContactRecipientAdapter(final Context context,
+            final ContactListItemView.HostInterface clivHost) {
+        this(context, Integer.MAX_VALUE, QUERY_TYPE_PHONE, clivHost);
+    }
+
+    public ContactRecipientAdapter(final Context context, final int preferredMaxResultCount,
+            final int queryMode, final ContactListItemView.HostInterface clivHost) {
+        super(context, preferredMaxResultCount, queryMode);
+        setPhotoManager(new ContactRecipientPhotoManager(context, clivHost));
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    @Override
+    public boolean forceShowAddress() {
+        // We should always use the SingleRecipientAddressAdapter
+        // And never use the RecipientAlternatesAdapter
+        return true;
+    }
+
+    @Override
+    public Filter getFilter() {
+        return new ContactFilter();
+    }
+
+    /**
+     * A Filter for a RecipientEditTextView that queries Bugle's ContactUtil for auto-complete
+     * results.
+     */
+    public class ContactFilter extends Filter {
+
+        // Used to sort filtered contacts when it has combined results from email and phone.
+        private final RecipientEntryComparator mComparator = new RecipientEntryComparator();
+
+        /**
+         * Returns a cursor containing the filtered results in contacts given the search text,
+         * and a boolean indicating whether the results are sorted.
+         *
+         * The queries are synchronously performed since this is not run on the main thread.
+         *
+         * Some locales (e.g. JPN) expect email addresses to be auto-completed for MMS.
+         * If this is the case, perform two queries on phone number followed by email and
+         * return the merged results.
+         */
+        @DoesNotRunOnMainThread
+        private CursorResult getFilteredResultsCursor(final String searchText) {
+            Assert.isNotMainThread();
+            if (BugleGservices.get().getBoolean(
+                    BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS,
+                    BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT)) {
+
+                final Cursor personalFilterPhonesCursor = ContactUtil
+                        .filterPhones(getContext(), searchText).performSynchronousQuery();
+                final Cursor personalFilterEmailsCursor = ContactUtil
+                        .filterEmails(getContext(), searchText).performSynchronousQuery();
+                final Cursor personalCursor = new MergeCursor(
+                        new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
+                final CursorResult cursorResult =
+                        new CursorResult(personalCursor, false /* sorted */);
+                if (OsUtil.isAtLeastN()) {
+                    // Including enterprise result starting from N.
+                    final Cursor enterpriseFilterPhonesCursor = ContactUtil.filterPhonesEnterprise(
+                            getContext(), searchText).performSynchronousQuery();
+                    final Cursor enterpriseFilterEmailsCursor = ContactUtil.filterEmailsEnterprise(
+                            getContext(), searchText).performSynchronousQuery();
+                    final Cursor enterpriseCursor = new MergeCursor(
+                            new Cursor[]{enterpriseFilterEmailsCursor,
+                                    enterpriseFilterPhonesCursor});
+                    cursorResult.enterpriseCursor = enterpriseCursor;
+                }
+                return cursorResult;
+            } else {
+                final Cursor personalFilterDestinationCursor = ContactUtil
+                        .filterDestination(getContext(), searchText).performSynchronousQuery();
+                final CursorResult cursorResult = new CursorResult(personalFilterDestinationCursor,
+                        true);
+                if (OsUtil.isAtLeastN()) {
+                    // Including enterprise result starting from N.
+                    final Cursor enterpriseFilterDestinationCursor = ContactUtil
+                            .filterDestinationEnterprise(getContext(), searchText)
+                            .performSynchronousQuery();
+                    cursorResult.enterpriseCursor = enterpriseFilterDestinationCursor;
+                }
+                return cursorResult;
+            }
+        }
+
+        @Override
+        protected FilterResults performFiltering(final CharSequence constraint) {
+            Assert.isNotMainThread();
+            final FilterResults results = new FilterResults();
+
+            // No query, return empty results.
+            if (TextUtils.isEmpty(constraint)) {
+                clearTempEntries();
+                return results;
+            }
+
+            final String searchText = constraint.toString();
+
+            // Query for auto-complete results, since performFiltering() is not done on the
+            // main thread, perform the cursor loader queries directly.
+
+            final CursorResult cursorResult = getFilteredResultsCursor(searchText);
+            final List<RecipientEntry> entries = new ArrayList<>();
+
+            // First check if the constraint is a valid SMS destination. If so, add the
+            // destination as a suggestion item to the drop down.
+            if (PhoneUtils.isValidSmsMmsDestination(searchText)) {
+                entries.add(ContactRecipientEntryUtils
+                        .constructSendToDestinationEntry(searchText));
+            }
+
+            // Only show work directory header if more than one result in work directory.
+            int workDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
+            if (cursorResult.enterpriseCursor != null
+                    && cursorResult.enterpriseCursor.getCount() > 0) {
+                if (cursorResult.personalCursor != null) {
+                    workDirectoryHeaderPos = entries.size();
+                    workDirectoryHeaderPos += cursorResult.personalCursor.getCount();
+                }
+            }
+
+            final Cursor[] cursors = new Cursor[]{cursorResult.personalCursor,
+                    cursorResult.enterpriseCursor};
+            for (Cursor cursor : cursors) {
+                if (cursor != null) {
+                    try {
+                        final List<RecipientEntry> tempEntries = new ArrayList<>();
+                        HashSet<Long> existingContactIds = new HashSet<>();
+                        while (cursor.moveToNext()) {
+                            // Make sure there's only one first-level contact (i.e. contact for
+                            // which we show the avatar picture and name) for every contact id.
+                            final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+                            final boolean isFirstLevel = !existingContactIds.contains(contactId);
+                            if (isFirstLevel) {
+                                existingContactIds.add(contactId);
+                            }
+                            tempEntries.add(ContactUtil.createRecipientEntryForPhoneQuery(cursor,
+                                    isFirstLevel));
+                        }
+
+                        if (!cursorResult.isSorted) {
+                            Collections.sort(tempEntries, mComparator);
+                        }
+                        entries.addAll(tempEntries);
+                    } finally {
+                        cursor.close();
+                    }
+                }
+            }
+            results.values = new ContactReceipientFilterResult(entries, workDirectoryHeaderPos);
+            results.count = 1;
+            return results;
+        }
+
+        @Override
+        protected void publishResults(final CharSequence constraint, final FilterResults results) {
+            mCurrentConstraint = constraint;
+            clearTempEntries();
+
+            final ContactReceipientFilterResult contactReceipientFilterResult
+                    = (ContactReceipientFilterResult) results.values;
+            if (contactReceipientFilterResult != null) {
+                mWorkDirectoryHeaderPos = contactReceipientFilterResult.workDirectoryPos;
+                if (contactReceipientFilterResult.recipientEntries != null) {
+                    updateEntries(contactReceipientFilterResult.recipientEntries);
+                } else {
+                    updateEntries(Collections.<RecipientEntry>emptyList());
+                }
+            }
+        }
+
+        private class RecipientEntryComparator implements Comparator<RecipientEntry> {
+
+            private final Collator mCollator;
+
+            public RecipientEntryComparator() {
+                mCollator = Collator.getInstance(Locale.getDefault());
+                mCollator.setStrength(Collator.PRIMARY);
+            }
+
+            /**
+             * Compare two RecipientEntry's, first by locale-aware display name comparison, then by
+             * contact id comparison, finally by first-level-ness comparison.
+             */
+            @Override
+            public int compare(RecipientEntry lhs, RecipientEntry rhs) {
+                // Send-to-destinations always appear before everything else.
+                final boolean sendToLhs = ContactRecipientEntryUtils
+                        .isSendToDestinationContact(lhs);
+                final boolean sendToRhs = ContactRecipientEntryUtils
+                        .isSendToDestinationContact(lhs);
+                if (sendToLhs != sendToRhs) {
+                    if (sendToLhs) {
+                        return -1;
+                    } else if (sendToRhs) {
+                        return 1;
+                    }
+                }
+
+                final int displayNameCompare = mCollator.compare(lhs.getDisplayName(),
+                        rhs.getDisplayName());
+                if (displayNameCompare != 0) {
+                    return displayNameCompare;
+                }
+
+                // Long.compare could accomplish the following three lines, but this is only
+                // available in API 19+
+                final long lhsContactId = lhs.getContactId();
+                final long rhsContactId = rhs.getContactId();
+                final int contactCompare = lhsContactId < rhsContactId ? -1 :
+                        (lhsContactId == rhsContactId ? 0 : 1);
+                if (contactCompare != 0) {
+                    return contactCompare;
+                }
+
+                // These are the same contact. Make sure first-level contacts always
+                // appear at the front.
+                if (lhs.isFirstLevel()) {
+                    return -1;
+                } else if (rhs.isFirstLevel()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+
+        private class CursorResult {
+
+            public final Cursor personalCursor;
+
+            public Cursor enterpriseCursor;
+
+            public final boolean isSorted;
+
+            public CursorResult(Cursor personalCursor, boolean isSorted) {
+                this.personalCursor = personalCursor;
+                this.isSorted = isSorted;
+            }
+        }
+
+        private class ContactReceipientFilterResult {
+            /**
+             * Recipient entries in all directories.
+             */
+            public final List<RecipientEntry> recipientEntries;
+
+            /**
+             * Index of row that showing work directory header.
+             */
+            public final int workDirectoryPos;
+
+            public ContactReceipientFilterResult(List<RecipientEntry> recipientEntries,
+                    int workDirectoryPos) {
+                this.recipientEntries = recipientEntries;
+                this.workDirectoryPos = workDirectoryPos;
+            }
+        }
+    }
+
+    /**
+     * Called when we need to substitute temporary recipient chips with better alternatives.
+     * For example, if a list of comma-delimited phone numbers are pasted into the edit box,
+     * we want to be able to look up in the ContactUtil for exact matches and get contact
+     * details such as name and photo thumbnail for the contact to display a better chip.
+     */
+    @Override
+    public void getMatchingRecipients(final ArrayList<String> inAddresses,
+            final RecipientMatchCallback callback) {
+        final int addressesSize = Math.min(
+                RecipientAlternatesAdapter.MAX_LOOKUPS, inAddresses.size());
+        final HashSet<String> addresses = new HashSet<String>();
+        for (int i = 0; i < addressesSize; i++) {
+            final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase());
+            addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i));
+        }
+
+        final Map<String, RecipientEntry> recipientEntries =
+                new HashMap<String, RecipientEntry>();
+        // query for each address
+        for (final String address : addresses) {
+            final Cursor cursor = ContactUtil.lookupDestination(getContext(), address)
+                    .performSynchronousQuery();
+            if (cursor != null) {
+                try {
+                    if (cursor.moveToNext()) {
+                        // There may be multiple matches to the same number, always take the
+                        // first match.
+                        // TODO: May need to consider if there's an existing conversation
+                        // that matches this particular contact and prioritize that contact.
+                        final RecipientEntry entry =
+                                ContactUtil.createRecipientEntryForPhoneQuery(cursor, true);
+                        recipientEntries.put(address, entry);
+                    }
+
+                } finally {
+                    cursor.close();
+                }
+            }
+        }
+
+        // report matches
+        callback.matchesFound(recipientEntries);
+    }
+
+    /**
+     * We handle directory header here and then delegate the work of creating recipient views to
+     * the {@link BaseRecipientAdapter}. Please notice that we need to fix the position
+     * before passing to {@link BaseRecipientAdapter} because it is not aware of the existence of
+     * directory headers.
+     */
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        TextView textView;
+        if (isDirectoryEntry(position)) {
+            if (convertView == null) {
+                textView = (TextView) mInflater.inflate(R.layout.work_directory_header, parent,
+                        false);
+            } else {
+                textView = (TextView) convertView;
+            }
+            return textView;
+        }
+        return super.getView(fixPosition(position), convertView, parent);
+    }
+
+    @Override
+    public RecipientEntry getItem(int position) {
+        if (isDirectoryEntry(position)) {
+            return null;
+        }
+        return super.getItem(fixPosition(position));
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return RecipientEntry.ENTRY_TYPE_SIZE + 1;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (isDirectoryEntry(position)) {
+            return ENTRY_TYPE_DIRECTORY;
+        }
+        return super.getItemViewType(fixPosition(position));
+    }
+
+    @Override
+    public boolean isEnabled(int position) {
+        if (isDirectoryEntry(position)) {
+            return false;
+        }
+        return super.isEnabled(fixPosition(position));
+    }
+
+    @Override
+    public int getCount() {
+        return super.getCount() + ((hasWorkDirectoryHeader()) ? 1 : 0);
+    }
+
+    private boolean isDirectoryEntry(int position) {
+        return position == mWorkDirectoryHeaderPos;
+    }
+
+    /**
+     * @return the position of items without counting directory headers.
+     */
+    private int fixPosition(int position) {
+        if (hasWorkDirectoryHeader()) {
+            Assert.isTrue(position != mWorkDirectoryHeaderPos);
+            if (position > mWorkDirectoryHeaderPos) {
+                return position - 1;
+            }
+        }
+        return position;
+    }
+
+    private boolean hasWorkDirectoryHeader() {
+        return mWorkDirectoryHeaderPos != WORD_DIRECTORY_HEADER_POS_NONE;
+    }
+
+}
diff --git a/src/com/android/messaging/ui/contact/ContactRecipientAutoCompleteView.java b/src/com/android/messaging/ui/contact/ContactRecipientAutoCompleteView.java
new file mode 100644
index 0000000..17128c1
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactRecipientAutoCompleteView.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+import android.text.Editable;
+import android.text.TextPaint;
+import android.text.TextWatcher;
+import android.text.util.Rfc822Tokenizer;
+import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.widget.TextView;
+
+import com.android.ex.chips.RecipientEditTextView;
+import com.android.ex.chips.RecipientEntry;
+import com.android.ex.chips.recipientchip.DrawableRecipientChip;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.ContactRecipientEntryUtils;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * An extension for {@link RecipientEditTextView} which shows a list of Materialized contact chips.
+ * It uses Bugle's ContactUtil to perform contact lookup, and is able to return the list of
+ * recipients in the form of a ParticipantData list.
+ */
+public class ContactRecipientAutoCompleteView extends RecipientEditTextView {
+    public interface ContactChipsChangeListener {
+        void onContactChipsChanged(int oldCount, int newCount);
+        void onInvalidContactChipsPruned(int prunedCount);
+        void onEntryComplete();
+    }
+
+    private final int mTextHeight;
+    private ContactChipsChangeListener mChipsChangeListener;
+
+    /**
+     * Watches changes in contact chips to determine possible state transitions.
+     */
+    private class ContactChipsWatcher implements TextWatcher {
+        /**
+         * Tracks the old chips count before text changes. Note that we currently don't compare
+         * the entire chip sets but just the cheaper-to-do before and after counts, because
+         * the chips view don't allow for replacing chips.
+         */
+        private int mLastChipsCount = 0;
+
+        @Override
+        public void onTextChanged(final CharSequence s, final int start, final int before,
+                final int count) {
+        }
+
+        @Override
+        public void beforeTextChanged(final CharSequence s, final int start, final int count,
+                final int after) {
+            // We don't take mLastChipsCount from here but from the last afterTextChanged() run.
+            // The reason is because at this point, any chip spans to be removed is already removed
+            // from s in the chips text view.
+        }
+
+        @Override
+        public void afterTextChanged(final Editable s) {
+            final int currentChipsCount = s.getSpans(0, s.length(),
+                    DrawableRecipientChip.class).length;
+            if (currentChipsCount != mLastChipsCount) {
+                // When a sanitizing task is running, we don't want to notify any chips count
+                // change, but we do want to track the last chip count.
+                if (mChipsChangeListener != null && mCurrentSanitizeTask == null) {
+                    mChipsChangeListener.onContactChipsChanged(mLastChipsCount, currentChipsCount);
+                }
+                mLastChipsCount = currentChipsCount;
+            }
+        }
+    }
+
+    private static final String TEXT_HEIGHT_SAMPLE = "a";
+
+    public ContactRecipientAutoCompleteView(final Context context, final AttributeSet attrs) {
+        super(new ContextThemeWrapper(context, R.style.ColorAccentGrayOverrideStyle), attrs);
+
+        // Get the height of the text, given the currently set font face and size.
+        final Rect textBounds = new Rect(0, 0, 0, 0);
+        final TextPaint paint = getPaint();
+        paint.getTextBounds(TEXT_HEIGHT_SAMPLE, 0, TEXT_HEIGHT_SAMPLE.length(), textBounds);
+        mTextHeight = textBounds.height();
+
+        setTokenizer(new Rfc822Tokenizer());
+        addTextChangedListener(new ContactChipsWatcher());
+        setOnFocusListShrinkRecipients(false);
+
+        setBackground(context.getResources().getDrawable(
+                androidx.appcompat.R.drawable.abc_textfield_search_default_mtrl_alpha));
+    }
+
+    public void setContactChipsListener(final ContactChipsChangeListener listener) {
+        mChipsChangeListener = listener;
+    }
+
+    /**
+     * A tuple of chips which AsyncContactChipSanitizeTask reports as progress to have the
+     * chip actually replaced/removed on the UI thread.
+     */
+    private class ChipReplacementTuple {
+        public final DrawableRecipientChip removedChip;
+        public final RecipientEntry replacedChipEntry;
+
+        public ChipReplacementTuple(final DrawableRecipientChip removedChip,
+                final RecipientEntry replacedChipEntry) {
+            this.removedChip = removedChip;
+            this.replacedChipEntry = replacedChipEntry;
+        }
+    }
+
+    /**
+     * An AsyncTask that cleans up contact chips on every chips commit (i.e. get or create a new
+     * conversation with the given chips).
+     */
+    private class AsyncContactChipSanitizeTask extends
+            AsyncTask<Void, ChipReplacementTuple, Integer> {
+
+        @Override
+        protected Integer doInBackground(final Void... params) {
+            final DrawableRecipientChip[] recips = getText()
+                    .getSpans(0, getText().length(), DrawableRecipientChip.class);
+            int invalidChipsRemoved = 0;
+            for (final DrawableRecipientChip recipient : recips) {
+                final RecipientEntry entry = recipient.getEntry();
+                if (entry != null) {
+                    if (entry.isValid()) {
+                        if (RecipientEntry.isCreatedRecipient(entry.getContactId()) ||
+                                ContactRecipientEntryUtils.isSendToDestinationContact(entry)) {
+                            // This is a generated/send-to contact chip, try to look it up and
+                            // display a chip for the corresponding local contact.
+                            try (final Cursor lookupResult =
+                                    ContactUtil.lookupDestination(
+                                                    getContext(), entry.getDestination())
+                                            .performSynchronousQuery()) {
+                                if (lookupResult != null && lookupResult.moveToNext()) {
+                                    // Found a match, remove the generated entry and replace with a
+                                    // better local entry.
+                                    publishProgress(
+                                            new ChipReplacementTuple(
+                                                    recipient,
+                                                    ContactUtil.createRecipientEntryForPhoneQuery(
+                                                            lookupResult, true)));
+                                } else if (PhoneUtils.isValidSmsMmsDestination(
+                                        entry.getDestination())) {
+                                    // No match was found, but we have a valid destination so let's
+                                    // at least create an entry that shows an avatar.
+                                    publishProgress(
+                                            new ChipReplacementTuple(
+                                                    recipient,
+                                                    ContactRecipientEntryUtils
+                                                            .constructNumberWithAvatarEntry(
+                                                                    entry.getDestination())));
+                                } else {
+                                    // Not a valid contact. Remove and show an error.
+                                    publishProgress(new ChipReplacementTuple(recipient, null));
+                                    invalidChipsRemoved++;
+                                }
+                            }
+                        }
+                    } else {
+                        publishProgress(new ChipReplacementTuple(recipient, null));
+                        invalidChipsRemoved++;
+                    }
+                }
+            }
+            return invalidChipsRemoved;
+        }
+
+        @Override
+        protected void onProgressUpdate(final ChipReplacementTuple... values) {
+            for (final ChipReplacementTuple tuple : values) {
+                if (tuple.removedChip != null) {
+                    final Editable text = getText();
+                    final int chipStart = text.getSpanStart(tuple.removedChip);
+                    final int chipEnd = text.getSpanEnd(tuple.removedChip);
+                    if (chipStart >= 0 && chipEnd >= 0) {
+                        text.delete(chipStart, chipEnd);
+                    }
+
+                    if (tuple.replacedChipEntry != null) {
+                        appendRecipientEntry(tuple.replacedChipEntry);
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected void onPostExecute(final Integer invalidChipsRemoved) {
+            mCurrentSanitizeTask = null;
+            if (invalidChipsRemoved > 0) {
+                mChipsChangeListener.onInvalidContactChipsPruned(invalidChipsRemoved);
+            }
+        }
+    }
+
+    /**
+     * We don't use SafeAsyncTask but instead use a single threaded executor to ensure that
+     * all sanitization tasks are serially executed so as not to interfere with each other.
+     */
+    private static final Executor SANITIZE_EXECUTOR = Executors.newSingleThreadExecutor();
+
+    private AsyncContactChipSanitizeTask mCurrentSanitizeTask;
+
+    /**
+     * Whenever the caller wants to start a new conversation with the list of chips we have,
+     * make sure we asynchronously:
+     * 1. Remove invalid chips.
+     * 2. Attempt to resolve unknown contacts to known local contacts.
+     * 3. Convert still unknown chips to chips with generated avatar.
+     *
+     * Note that we don't need to perform this synchronously since we can
+     * resolve any unknown contacts to local contacts when needed.
+     */
+    private void sanitizeContactChips() {
+        if (mCurrentSanitizeTask != null && !mCurrentSanitizeTask.isCancelled()) {
+            mCurrentSanitizeTask.cancel(false);
+            mCurrentSanitizeTask = null;
+        }
+        mCurrentSanitizeTask = new AsyncContactChipSanitizeTask();
+        mCurrentSanitizeTask.executeOnExecutor(SANITIZE_EXECUTOR);
+    }
+
+    /**
+     * Returns a list of ParticipantData from the entered chips in order to create
+     * new conversation.
+     */
+    public ArrayList<ParticipantData> getRecipientParticipantDataForConversationCreation() {
+        final DrawableRecipientChip[] recips = getText()
+                .getSpans(0, getText().length(), DrawableRecipientChip.class);
+        final ArrayList<ParticipantData> contacts =
+                new ArrayList<ParticipantData>(recips.length);
+        for (final DrawableRecipientChip recipient : recips) {
+            final RecipientEntry entry = recipient.getEntry();
+            if (entry != null && entry.isValid() && entry.getDestination() != null &&
+                    PhoneUtils.isValidSmsMmsDestination(entry.getDestination())) {
+                contacts.add(ParticipantData.getFromRecipientEntry(recipient.getEntry()));
+            }
+        }
+        sanitizeContactChips();
+        return contacts;
+    }
+
+    /**c
+     * Gets a set of currently selected chips' emails/phone numbers. This will facilitate the
+     * consumer with determining quickly whether a contact is currently selected.
+     */
+    public Set<String> getSelectedDestinations() {
+        Set<String> set = new HashSet<String>();
+        final DrawableRecipientChip[] recips = getText()
+                .getSpans(0, getText().length(), DrawableRecipientChip.class);
+
+        for (final DrawableRecipientChip recipient : recips) {
+            final RecipientEntry entry = recipient.getEntry();
+            if (entry != null && entry.isValid() && entry.getDestination() != null) {
+                set.add(PhoneUtils.getDefault().getCanonicalBySystemLocale(
+                        entry.getDestination()));
+            }
+        }
+        return set;
+    }
+
+    @Override
+    public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) {
+        if (actionId == EditorInfo.IME_ACTION_DONE) {
+            mChipsChangeListener.onEntryComplete();
+        }
+        return super.onEditorAction(view, actionId, event);
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactRecipientPhotoManager.java b/src/com/android/messaging/ui/contact/ContactRecipientPhotoManager.java
new file mode 100644
index 0000000..d69ba64
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactRecipientPhotoManager.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.ex.chips.PhotoManager;
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.media.AvatarRequestDescriptor;
+import com.android.messaging.datamodel.media.BindableMediaRequest;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.ThreadUtil;
+
+/**
+ * An implementation of {@link PhotoManager} that hooks up the chips UI's photos with our own
+ * {@link MediaResourceManager} for retrieving and caching contact avatars.
+ */
+public class ContactRecipientPhotoManager implements PhotoManager {
+    private static final String IMAGE_BYTES_REQUEST_STATIC_BINDING_ID = "imagebytes";
+    private final Context mContext;
+    private final int mIconSize;
+    private final ContactListItemView.HostInterface mClivHostInterface;
+
+    public ContactRecipientPhotoManager(final Context context,
+            final ContactListItemView.HostInterface clivHostInterface) {
+        mContext = context;
+        mIconSize = context.getResources().getDimensionPixelSize(
+                R.dimen.compose_message_chip_height) - context.getResources().getDimensionPixelSize(
+                        R.dimen.compose_message_chip_padding) * 2;
+        mClivHostInterface = clivHostInterface;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void populatePhotoBytesAsync(final RecipientEntry entry,
+            final PhotoManagerCallback callback) {
+        // Post all media resource request to the main thread.
+        ThreadUtil.getMainThreadHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                        ParticipantData.getFromRecipientEntry(entry));
+                final AvatarRequestDescriptor descriptor =
+                        new AvatarRequestDescriptor(avatarUri, mIconSize, mIconSize);
+                final BindableMediaRequest<ImageResource> req = descriptor.buildAsyncMediaRequest(
+                        mContext,
+                        new MediaResourceLoadListener<ImageResource>() {
+                    @Override
+                    public void onMediaResourceLoaded(final MediaRequest<ImageResource> request,
+                            final ImageResource resource, final boolean isCached) {
+                        entry.setPhotoBytes(resource.getBytes());
+                        callback.onPhotoBytesAsynchronouslyPopulated();
+                    }
+
+                    @Override
+                    public void onMediaResourceLoadError(final MediaRequest<ImageResource> request,
+                            final Exception exception) {
+                        LogUtil.e(LogUtil.BUGLE_TAG, "Photo bytes loading failed due to " +
+                                exception + " request key=" + request.getKey());
+
+                        // Fall back to the default avatar image.
+                        callback.onPhotoBytesAsyncLoadFailed();
+                    }});
+
+                // Statically bind the request since it's not bound to any specific piece of UI.
+                req.bind(IMAGE_BYTES_REQUEST_STATIC_BINDING_ID);
+
+                Factory.get().getMediaResourceManager().requestMediaResourceAsync(req);
+            }
+        });
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/ContactSectionIndexer.java b/src/com/android/messaging/ui/contact/ContactSectionIndexer.java
new file mode 100644
index 0000000..1d5abf3
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/ContactSectionIndexer.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+import android.widget.SectionIndexer;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+
+/**
+ * Indexes contact alphabetical sections so we can report to the fast scrolling list view
+ * where we are in the list when the user scrolls through the contact list, allowing us to show
+ * alphabetical indicators for the fast scroller as well as list section headers.
+ */
+public class ContactSectionIndexer implements SectionIndexer {
+    private String[] mSections;
+    private ArrayList<Integer> mSectionStartingPositions;
+    private static final String BLANK_HEADER_STRING = " ";
+
+    public ContactSectionIndexer(final Cursor contactsCursor) {
+        buildIndexer(contactsCursor);
+    }
+
+    @Override
+    public Object[] getSections() {
+        return mSections;
+    }
+
+    @Override
+    public int getPositionForSection(final int sectionIndex) {
+        if (mSectionStartingPositions.isEmpty()) {
+            return 0;
+        }
+        // Clamp to the bounds of the section position array per Android API doc.
+        return mSectionStartingPositions.get(
+                Math.max(Math.min(sectionIndex, mSectionStartingPositions.size() - 1), 0));
+    }
+
+    @Override
+    public int getSectionForPosition(final int position) {
+        if (mSectionStartingPositions.isEmpty()) {
+            return 0;
+        }
+
+        // Perform a binary search on the starting positions of the sections to the find the
+        // section for the position.
+        int left = 0;
+        int right = mSectionStartingPositions.size() - 1;
+
+        // According to getSectionForPosition()'s doc, we should always clamp the value when the
+        // position is out of bound.
+        if (position <= mSectionStartingPositions.get(left)) {
+            return left;
+        } else if (position >= mSectionStartingPositions.get(right)) {
+            return right;
+        }
+
+        while (left <= right) {
+            final int mid = (left + right) / 2;
+            final int startingPos = mSectionStartingPositions.get(mid);
+            final int nextStartingPos = mSectionStartingPositions.get(mid + 1);
+            if (position >= startingPos && position < nextStartingPos) {
+                return mid;
+            } else if (position < startingPos) {
+                right = mid - 1;
+            } else if (position >= nextStartingPos) {
+                left = mid + 1;
+            }
+        }
+        Assert.fail("Invalid section indexer state: couldn't find section for pos " + position);
+        return -1;
+    }
+
+    private boolean buildIndexerFromCursorExtras(final Cursor cursor) {
+        if (cursor == null) {
+            return false;
+        }
+        final Bundle cursorExtras = cursor.getExtras();
+        if (cursorExtras == null) {
+            return false;
+        }
+        final String[] sections = cursorExtras.getStringArray(
+                Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
+        final int[] counts = cursorExtras.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
+        if (sections == null || counts == null) {
+            return false;
+        }
+
+        if (sections.length != counts.length) {
+            return false;
+        }
+
+        this.mSections = sections;
+        mSectionStartingPositions = new ArrayList<Integer>(counts.length);
+        int position = 0;
+        for (int i = 0; i < counts.length; i++) {
+            if (TextUtils.isEmpty(mSections[i])) {
+                mSections[i] = BLANK_HEADER_STRING;
+            } else if (!mSections[i].equals(BLANK_HEADER_STRING)) {
+                mSections[i] = mSections[i].trim();
+            }
+
+            mSectionStartingPositions.add(position);
+            position += counts[i];
+        }
+        return true;
+    }
+
+    private void buildIndexerFromDisplayNames(final Cursor cursor) {
+        // Loop through the contact cursor and get the starting position for each first character.
+        // The result is stored into two arrays, one for the section header (i.e. the first
+        // character), and one for the starting position, which is guaranteed to be sorted in
+        // ascending order.
+        final ArrayList<String> sections = new ArrayList<String>();
+        mSectionStartingPositions = new ArrayList<Integer>();
+        if (cursor != null) {
+            cursor.moveToPosition(-1);
+            int currentPosition = 0;
+            while (cursor.moveToNext()) {
+                // The sort key is typically the contact's display name, so for example, a contact
+                // named "Bob" will go into section "B". The Contacts provider generally uses a
+                // a slightly more sophisticated heuristic, but as a fallback this is good enough.
+                final String sortKey = cursor.getString(ContactUtil.INDEX_SORT_KEY);
+                final String section = TextUtils.isEmpty(sortKey) ? BLANK_HEADER_STRING :
+                    sortKey.substring(0, 1).toUpperCase();
+
+                final int lastIndex = sections.size() - 1;
+                final String currentSection = lastIndex >= 0 ? sections.get(lastIndex) : null;
+                if (!TextUtils.equals(currentSection, section)) {
+                    sections.add(section);
+                    mSectionStartingPositions.add(currentPosition);
+                }
+                currentPosition++;
+            }
+        }
+        mSections = new String[sections.size()];
+        sections.toArray(mSections);
+    }
+
+    private void buildIndexer(final Cursor cursor) {
+        // First check if we get indexer label extras from the contact provider; if not, fall back
+        // to building from display names.
+        if (!buildIndexerFromCursorExtras(cursor)) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "contact provider didn't provide contact label " +
+                    "information, fall back to using display name!");
+            buildIndexerFromDisplayNames(cursor);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/contact/FrequentContactsListViewHolder.java b/src/com/android/messaging/ui/contact/FrequentContactsListViewHolder.java
new file mode 100644
index 0000000..1f3c795
--- /dev/null
+++ b/src/com/android/messaging/ui/contact/FrequentContactsListViewHolder.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.CustomHeaderPagerListViewHolder;
+import com.android.messaging.ui.contact.ContactListItemView.HostInterface;
+
+/**
+ * Holds the frequent contacts view for the contact picker's view pager.
+ */
+public class FrequentContactsListViewHolder extends CustomHeaderPagerListViewHolder {
+    public FrequentContactsListViewHolder(final Context context,
+            final HostInterface clivHostInterface) {
+        super(context, new ContactListAdapter(context, null, clivHostInterface,
+                false /* needAlphabetHeader */));
+    }
+
+    @Override
+    protected int getLayoutResId() {
+        return R.layout.frequent_contacts_list_view;
+    }
+
+    @Override
+    protected int getPageTitleResId() {
+        return R.string.contact_picker_frequents_tab_title;
+    }
+
+    @Override
+    protected int getEmptyViewResId() {
+        return R.id.empty_view;
+    }
+
+    @Override
+    protected int getListViewResId() {
+        return R.id.frequent_contacts_list;
+    }
+
+    @Override
+    protected int getEmptyViewTitleResId() {
+        return R.string.contact_list_empty_text;
+    }
+
+    @Override
+    protected int getEmptyViewImageResId() {
+        return R.drawable.ic_oobe_freq_list;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ComposeMessageView.java b/src/com/android/messaging/ui/conversation/ComposeMessageView.java
new file mode 100644
index 0000000..c35927e
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ComposeMessageView.java
@@ -0,0 +1,1019 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.text.Editable;
+import android.text.Html;
+import android.text.InputFilter;
+import android.text.InputFilter.LengthFilter;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.format.Formatter;
+import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationData.SimpleConversationDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftForSendTask;
+import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftTaskCallback;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageDataListener;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.ui.AttachmentPreview;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.PlainTextEditText;
+import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputSink;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This view contains the UI required to generate and send messages.
+ */
+public class ComposeMessageView extends LinearLayout
+        implements TextView.OnEditorActionListener, DraftMessageDataListener, TextWatcher,
+        ConversationInputSink {
+
+    public interface IComposeMessageViewHost extends
+            DraftMessageData.DraftMessageSubscriptionDataProvider {
+        void sendMessage(MessageData message);
+        void onComposeEditTextFocused();
+        void onAttachmentsCleared();
+        void onAttachmentsChanged(final boolean haveAttachments);
+        void displayPhoto(Uri photoUri, Rect imageBounds, boolean isDraft);
+        void promptForSelfPhoneNumber();
+        boolean isReadyForAction();
+        void warnOfMissingActionConditions(final boolean sending,
+                final Runnable commandToRunAfterActionConditionResolved);
+        void warnOfExceedingMessageLimit(final boolean showAttachmentChooser,
+                boolean tooManyVideos);
+        void notifyOfAttachmentLoadFailed();
+        void showAttachmentChooser();
+        boolean shouldShowSubjectEditor();
+        boolean shouldHideAttachmentsWhenSimSelectorShown();
+        Uri getSelfSendButtonIconUri();
+        int overrideCounterColor();
+        int getAttachmentsClearedFlags();
+    }
+
+    public static final int CODEPOINTS_REMAINING_BEFORE_COUNTER_SHOWN = 10;
+
+    // There is no draft and there is no need for the SIM selector
+    private static final int SEND_WIDGET_MODE_SELF_AVATAR = 1;
+    // There is no draft but we need to show the SIM selector
+    private static final int SEND_WIDGET_MODE_SIM_SELECTOR = 2;
+    // There is a draft
+    private static final int SEND_WIDGET_MODE_SEND_BUTTON = 3;
+
+    private PlainTextEditText mComposeEditText;
+    private PlainTextEditText mComposeSubjectText;
+    private TextView mMessageBodySize;
+    private TextView mMmsIndicator;
+    private SimIconView mSelfSendIcon;
+    private ImageButton mSendButton;
+    private View mSubjectView;
+    private ImageButton mDeleteSubjectButton;
+    private AttachmentPreview mAttachmentPreview;
+    private ImageButton mAttachMediaButton;
+
+    private final Binding<DraftMessageData> mBinding;
+    private IComposeMessageViewHost mHost;
+    private final Context mOriginalContext;
+    private int mSendWidgetMode = SEND_WIDGET_MODE_SELF_AVATAR;
+
+    // Shared data model object binding from the conversation.
+    private ImmutableBindingRef<ConversationData> mConversationDataModel;
+
+    // Centrally manages all the mutual exclusive UI components accepting user input, i.e.
+    // media picker, IME keyboard and SIM selector.
+    private ConversationInputManager mInputManager;
+
+    private final ConversationDataListener mDataListener = new SimpleConversationDataListener() {
+        @Override
+        public void onConversationMetadataUpdated(ConversationData data) {
+            mConversationDataModel.ensureBound(data);
+            updateVisualsOnDraftChanged();
+        }
+
+        @Override
+        public void onConversationParticipantDataLoaded(ConversationData data) {
+            mConversationDataModel.ensureBound(data);
+            updateVisualsOnDraftChanged();
+        }
+
+        @Override
+        public void onSubscriptionListDataLoaded(ConversationData data) {
+            mConversationDataModel.ensureBound(data);
+            updateOnSelfSubscriptionChange();
+            updateVisualsOnDraftChanged();
+        }
+    };
+
+    public ComposeMessageView(final Context context, final AttributeSet attrs) {
+        super(new ContextThemeWrapper(context, R.style.ColorAccentBlueOverrideStyle), attrs);
+        mOriginalContext = context;
+        mBinding = BindingBase.createBinding(this);
+    }
+
+    /**
+     * Host calls this to bind view to DraftMessageData object
+     */
+    public void bind(final DraftMessageData data, final IComposeMessageViewHost host) {
+        mHost = host;
+        mBinding.bind(data);
+        data.addListener(this);
+        data.setSubscriptionDataProvider(host);
+
+        final int counterColor = mHost.overrideCounterColor();
+        if (counterColor != -1) {
+            mMessageBodySize.setTextColor(counterColor);
+        }
+    }
+
+    /**
+     * Host calls this to unbind view
+     */
+    public void unbind() {
+        mBinding.unbind();
+        mHost = null;
+        mInputManager.onDetach();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mComposeEditText = (PlainTextEditText) findViewById(
+                R.id.compose_message_text);
+        mComposeEditText.setOnEditorActionListener(this);
+        mComposeEditText.addTextChangedListener(this);
+        mComposeEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(final View v, final boolean hasFocus) {
+                if (v == mComposeEditText && hasFocus) {
+                    mHost.onComposeEditTextFocused();
+                }
+            }
+        });
+        mComposeEditText.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View arg0) {
+                if (mHost.shouldHideAttachmentsWhenSimSelectorShown()) {
+                    hideSimSelector();
+                }
+            }
+        });
+
+        // onFinishInflate() is called before self is loaded from db. We set the default text
+        // limit here, and apply the real limit later in updateOnSelfSubscriptionChange().
+        mComposeEditText.setFilters(new InputFilter[] {
+                new LengthFilter(MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
+                        .getMaxTextLimit()) });
+
+        mSelfSendIcon = (SimIconView) findViewById(R.id.self_send_icon);
+        mSelfSendIcon.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                boolean shown = mInputManager.toggleSimSelector(true /* animate */,
+                        getSelfSubscriptionListEntry());
+                hideAttachmentsWhenShowingSims(shown);
+            }
+        });
+        mSelfSendIcon.setOnLongClickListener(new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(final View v) {
+                if (mHost.shouldShowSubjectEditor()) {
+                    showSubjectEditor();
+                } else {
+                    boolean shown = mInputManager.toggleSimSelector(true /* animate */,
+                            getSelfSubscriptionListEntry());
+                    hideAttachmentsWhenShowingSims(shown);
+                }
+                return true;
+            }
+        });
+
+        mComposeSubjectText = (PlainTextEditText) findViewById(
+                R.id.compose_subject_text);
+        // We need the listener to change the avatar to the send button when the user starts
+        // typing a subject without a message.
+        mComposeSubjectText.addTextChangedListener(this);
+        // onFinishInflate() is called before self is loaded from db. We set the default text
+        // limit here, and apply the real limit later in updateOnSelfSubscriptionChange().
+        mComposeSubjectText.setFilters(new InputFilter[] {
+                new LengthFilter(MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
+                        .getMaxSubjectLength())});
+
+        mDeleteSubjectButton = (ImageButton) findViewById(R.id.delete_subject_button);
+        mDeleteSubjectButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View clickView) {
+                hideSubjectEditor();
+                mComposeSubjectText.setText(null);
+                mBinding.getData().setMessageSubject(null);
+            }
+        });
+
+        mSubjectView = findViewById(R.id.subject_view);
+
+        mSendButton = (ImageButton) findViewById(R.id.send_message_button);
+        mSendButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View clickView) {
+                sendMessageInternal(true /* checkMessageSize */);
+            }
+        });
+        mSendButton.setOnLongClickListener(new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(final View arg0) {
+                boolean shown = mInputManager.toggleSimSelector(true /* animate */,
+                        getSelfSubscriptionListEntry());
+                hideAttachmentsWhenShowingSims(shown);
+                if (mHost.shouldShowSubjectEditor()) {
+                    showSubjectEditor();
+                }
+                return true;
+            }
+        });
+        mSendButton.setAccessibilityDelegate(new AccessibilityDelegate() {
+            @Override
+            public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+                super.onPopulateAccessibilityEvent(host, event);
+                // When the send button is long clicked, we want TalkBack to announce the real
+                // action (select SIM or edit subject), as opposed to "long press send button."
+                if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {
+                    event.getText().clear();
+                    event.getText().add(getResources()
+                            .getText(shouldShowSimSelector(mConversationDataModel.getData()) ?
+                            R.string.send_button_long_click_description_with_sim_selector :
+                                R.string.send_button_long_click_description_no_sim_selector));
+                    // Make this an announcement so TalkBack will read our custom message.
+                    event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
+                }
+            }
+        });
+
+        mAttachMediaButton =
+                (ImageButton) findViewById(R.id.attach_media_button);
+        mAttachMediaButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View clickView) {
+                // Showing the media picker is treated as starting to compose the message.
+                mInputManager.showHideMediaPicker(true /* show */, true /* animate */);
+            }
+        });
+
+        mAttachmentPreview = (AttachmentPreview) findViewById(R.id.attachment_draft_view);
+        mAttachmentPreview.setComposeMessageView(this);
+
+        mMessageBodySize = (TextView) findViewById(R.id.message_body_size);
+        mMmsIndicator = (TextView) findViewById(R.id.mms_indicator);
+    }
+
+    private void hideAttachmentsWhenShowingSims(final boolean simPickerVisible) {
+        if (!mHost.shouldHideAttachmentsWhenSimSelectorShown()) {
+            return;
+        }
+        final boolean haveAttachments = mBinding.getData().hasAttachments();
+        if (simPickerVisible && haveAttachments) {
+            mHost.onAttachmentsChanged(false);
+            mAttachmentPreview.hideAttachmentPreview();
+        } else {
+            mHost.onAttachmentsChanged(haveAttachments);
+            mAttachmentPreview.onAttachmentsChanged(mBinding.getData());
+        }
+    }
+
+    public void setInputManager(final ConversationInputManager inputManager) {
+        mInputManager = inputManager;
+    }
+
+    public void setConversationDataModel(final ImmutableBindingRef<ConversationData> refDataModel) {
+        mConversationDataModel = refDataModel;
+        mConversationDataModel.getData().addConversationDataListener(mDataListener);
+    }
+
+    ImmutableBindingRef<DraftMessageData> getDraftDataModel() {
+        return BindingBase.createBindingReference(mBinding);
+    }
+
+    // returns true if it actually shows the subject editor and false if already showing
+    private boolean showSubjectEditor() {
+        // show the subject editor
+        if (mSubjectView.getVisibility() == View.GONE) {
+            mSubjectView.setVisibility(View.VISIBLE);
+            mSubjectView.requestFocus();
+            return true;
+        }
+        return false;
+    }
+
+    private void hideSubjectEditor() {
+        mSubjectView.setVisibility(View.GONE);
+        mComposeEditText.requestFocus();
+    }
+
+    /**
+     * {@inheritDoc} from TextView.OnEditorActionListener
+     */
+    @Override // TextView.OnEditorActionListener.onEditorAction
+    public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) {
+        if (actionId == EditorInfo.IME_ACTION_SEND) {
+            sendMessageInternal(true /* checkMessageSize */);
+            return true;
+        }
+        return false;
+    }
+
+    private void sendMessageInternal(final boolean checkMessageSize) {
+        LogUtil.i(LogUtil.BUGLE_TAG, "UI initiated message sending in conversation " +
+                mBinding.getData().getConversationId());
+        if (mBinding.getData().isCheckingDraft()) {
+            // Don't send message if we are currently checking draft for sending.
+            LogUtil.w(LogUtil.BUGLE_TAG, "Message can't be sent: still checking draft");
+            return;
+        }
+        // Check the host for pre-conditions about any action.
+        if (mHost.isReadyForAction()) {
+            mInputManager.showHideSimSelector(false /* show */, true /* animate */);
+            final String messageToSend = mComposeEditText.getText().toString();
+            mBinding.getData().setMessageText(messageToSend);
+            final String subject = mComposeSubjectText.getText().toString();
+            mBinding.getData().setMessageSubject(subject);
+            // Asynchronously check the draft against various requirements before sending.
+            mBinding.getData().checkDraftForAction(checkMessageSize,
+                    mHost.getConversationSelfSubId(), new CheckDraftTaskCallback() {
+                @Override
+                public void onDraftChecked(DraftMessageData data, int result) {
+                    mBinding.ensureBound(data);
+                    switch (result) {
+                        case CheckDraftForSendTask.RESULT_PASSED:
+                            // Continue sending after check succeeded.
+                            final MessageData message = mBinding.getData()
+                                    .prepareMessageForSending(mBinding);
+                            if (message != null && message.hasContent()) {
+                                playSentSound();
+                                mHost.sendMessage(message);
+                                hideSubjectEditor();
+                                if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
+                                    AccessibilityUtil.announceForAccessibilityCompat(
+                                            ComposeMessageView.this, null,
+                                            R.string.sending_message);
+                                }
+                            }
+                            break;
+
+                        case CheckDraftForSendTask.RESULT_HAS_PENDING_ATTACHMENTS:
+                            // Cannot send while there's still attachment(s) being loaded.
+                            UiUtils.showToastAtBottom(
+                                    R.string.cant_send_message_while_loading_attachments);
+                            break;
+
+                        case CheckDraftForSendTask.RESULT_NO_SELF_PHONE_NUMBER_IN_GROUP_MMS:
+                            mHost.promptForSelfPhoneNumber();
+                            break;
+
+                        case CheckDraftForSendTask.RESULT_MESSAGE_OVER_LIMIT:
+                            Assert.isTrue(checkMessageSize);
+                            mHost.warnOfExceedingMessageLimit(
+                                    true /*sending*/, false /* tooManyVideos */);
+                            break;
+
+                        case CheckDraftForSendTask.RESULT_VIDEO_ATTACHMENT_LIMIT_EXCEEDED:
+                            Assert.isTrue(checkMessageSize);
+                            mHost.warnOfExceedingMessageLimit(
+                                    true /*sending*/, true /* tooManyVideos */);
+                            break;
+
+                        case CheckDraftForSendTask.RESULT_SIM_NOT_READY:
+                            // Cannot send if there is no active subscription
+                            UiUtils.showToastAtBottom(
+                                    R.string.cant_send_message_without_active_subscription);
+                            break;
+
+                        default:
+                            break;
+                    }
+                }
+            }, mBinding);
+        } else {
+            mHost.warnOfMissingActionConditions(true /*sending*/,
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            sendMessageInternal(checkMessageSize);
+                        }
+
+            });
+        }
+    }
+
+    public static void playSentSound() {
+        // Check if this setting is enabled before playing
+        final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+        final Context context = Factory.get().getApplicationContext();
+        final String prefKey = context.getString(R.string.send_sound_pref_key);
+        final boolean defaultValue = context.getResources().getBoolean(
+                R.bool.send_sound_pref_default);
+        if (!prefs.getBoolean(prefKey, defaultValue)) {
+            return;
+        }
+        MediaUtil.get().playSound(context, R.raw.message_sent, null /* completionListener */);
+    }
+
+    /**
+     * {@inheritDoc} from DraftMessageDataListener
+     */
+    @Override // From DraftMessageDataListener
+    public void onDraftChanged(final DraftMessageData data, final int changeFlags) {
+        // As this is called asynchronously when message read check bound before updating text
+        mBinding.ensureBound(data);
+
+        // We have to cache the values of the DraftMessageData because when we set
+        // mComposeEditText, its onTextChanged calls updateVisualsOnDraftChanged,
+        // which immediately reloads the text from the subject and message fields and replaces
+        // what's in the DraftMessageData.
+
+        final String subject = data.getMessageSubject();
+        final String message = data.getMessageText();
+
+        boolean hasAttachmentsChanged = false;
+
+        if ((changeFlags & DraftMessageData.MESSAGE_SUBJECT_CHANGED) ==
+                DraftMessageData.MESSAGE_SUBJECT_CHANGED) {
+            mComposeSubjectText.setText(subject);
+
+            // Set the cursor selection to the end since setText resets it to the start
+            mComposeSubjectText.setSelection(mComposeSubjectText.getText().length());
+        }
+
+        if ((changeFlags & DraftMessageData.MESSAGE_TEXT_CHANGED) ==
+                DraftMessageData.MESSAGE_TEXT_CHANGED) {
+            mComposeEditText.setText(message);
+
+            // Set the cursor selection to the end since setText resets it to the start
+            mComposeEditText.setSelection(mComposeEditText.getText().length());
+        }
+
+        if ((changeFlags & DraftMessageData.ATTACHMENTS_CHANGED) ==
+                DraftMessageData.ATTACHMENTS_CHANGED) {
+            final boolean haveAttachments = mAttachmentPreview.onAttachmentsChanged(data);
+            mHost.onAttachmentsChanged(haveAttachments);
+            hasAttachmentsChanged = true;
+        }
+
+        if ((changeFlags & DraftMessageData.SELF_CHANGED) == DraftMessageData.SELF_CHANGED) {
+            updateOnSelfSubscriptionChange();
+        }
+        updateVisualsOnDraftChanged(hasAttachmentsChanged);
+    }
+
+    @Override   // From DraftMessageDataListener
+    public void onDraftAttachmentLimitReached(final DraftMessageData data) {
+        mBinding.ensureBound(data);
+        mHost.warnOfExceedingMessageLimit(false /* sending */, false /* tooManyVideos */);
+    }
+
+    private void updateOnSelfSubscriptionChange() {
+        // Refresh the length filters according to the selected self's MmsConfig.
+        mComposeEditText.setFilters(new InputFilter[] {
+                new LengthFilter(MmsConfig.get(mBinding.getData().getSelfSubId())
+                        .getMaxTextLimit()) });
+        mComposeSubjectText.setFilters(new InputFilter[] {
+                new LengthFilter(MmsConfig.get(mBinding.getData().getSelfSubId())
+                        .getMaxSubjectLength())});
+    }
+
+    @Override
+    public void onMediaItemsSelected(final Collection<MessagePartData> items) {
+        mBinding.getData().addAttachments(items);
+        announceMediaItemState(true /*isSelected*/);
+    }
+
+    @Override
+    public void onMediaItemsUnselected(final MessagePartData item) {
+        mBinding.getData().removeAttachment(item);
+        announceMediaItemState(false /*isSelected*/);
+    }
+
+    @Override
+    public void onPendingAttachmentAdded(final PendingAttachmentData pendingItem) {
+        mBinding.getData().addPendingAttachment(pendingItem, mBinding);
+        resumeComposeMessage();
+    }
+
+    private void announceMediaItemState(final boolean isSelected) {
+        final Resources res = getContext().getResources();
+        final String announcement = isSelected ? res.getString(
+                R.string.mediapicker_gallery_item_selected_content_description) :
+                    res.getString(R.string.mediapicker_gallery_item_unselected_content_description);
+        AccessibilityUtil.announceForAccessibilityCompat(
+                this, null, announcement);
+    }
+
+    private void announceAttachmentState() {
+        if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
+            int attachmentCount = mBinding.getData().getReadOnlyAttachments().size()
+                    + mBinding.getData().getReadOnlyPendingAttachments().size();
+            final String announcement = getContext().getResources().getQuantityString(
+                    R.plurals.attachment_changed_accessibility_announcement,
+                    attachmentCount, attachmentCount);
+            AccessibilityUtil.announceForAccessibilityCompat(
+                    this, null, announcement);
+        }
+    }
+
+    @Override
+    public void resumeComposeMessage() {
+        mComposeEditText.requestFocus();
+        mInputManager.showHideImeKeyboard(true, true);
+        announceAttachmentState();
+    }
+
+    public void clearAttachments() {
+        mBinding.getData().clearAttachments(mHost.getAttachmentsClearedFlags());
+        mHost.onAttachmentsCleared();
+    }
+
+    public void requestDraftMessage(boolean clearLocalDraft) {
+        mBinding.getData().loadFromStorage(mBinding, null, clearLocalDraft);
+    }
+
+    public void setDraftMessage(final MessageData message) {
+        mBinding.getData().loadFromStorage(mBinding, message, false);
+    }
+
+    public void writeDraftMessage() {
+        final String messageText = mComposeEditText.getText().toString();
+        mBinding.getData().setMessageText(messageText);
+
+        final String subject = mComposeSubjectText.getText().toString();
+        mBinding.getData().setMessageSubject(subject);
+
+        mBinding.getData().saveToStorage(mBinding);
+    }
+
+    private void updateConversationSelfId(final String selfId, final boolean notify) {
+        mBinding.getData().setSelfId(selfId, notify);
+    }
+
+    private Uri getSelfSendButtonIconUri() {
+        final Uri overridenSelfUri = mHost.getSelfSendButtonIconUri();
+        if (overridenSelfUri != null) {
+            return overridenSelfUri;
+        }
+        final SubscriptionListEntry subscriptionListEntry = getSelfSubscriptionListEntry();
+
+        if (subscriptionListEntry != null) {
+            return subscriptionListEntry.selectedIconUri;
+        }
+
+        // Fall back to default self-avatar in the base case.
+        final ParticipantData self = mConversationDataModel.getData().getDefaultSelfParticipant();
+        return self == null ? null : AvatarUriUtil.createAvatarUri(self);
+    }
+
+    private SubscriptionListEntry getSelfSubscriptionListEntry() {
+        return mConversationDataModel.getData().getSubscriptionEntryForSelfParticipant(
+                mBinding.getData().getSelfId(), false /* excludeDefault */);
+    }
+
+    private boolean isDataLoadedForMessageSend() {
+        // Check data loading prerequisites for sending a message.
+        return mConversationDataModel != null && mConversationDataModel.isBound() &&
+                mConversationDataModel.getData().getParticipantsLoaded();
+    }
+
+    private static class AsyncUpdateMessageBodySizeTask
+            extends SafeAsyncTask<List<MessagePartData>, Void, Long> {
+
+        private final Context mContext;
+        private final TextView mSizeTextView;
+
+        public AsyncUpdateMessageBodySizeTask(final Context context, final TextView tv) {
+            mContext = context;
+            mSizeTextView = tv;
+        }
+
+        @Override
+        protected Long doInBackgroundTimed(final List<MessagePartData>... params) {
+            final List<MessagePartData> attachments = params[0];
+            long totalSize = 0;
+            for (final MessagePartData attachment : attachments) {
+                final Uri contentUri = attachment.getContentUri();
+                if (contentUri != null) {
+                    totalSize += UriUtil.getContentSize(attachment.getContentUri());
+                }
+            }
+            return totalSize;
+        }
+
+        @Override
+        protected void onPostExecute(Long size) {
+            if (mSizeTextView != null) {
+                mSizeTextView.setText(Formatter.formatFileSize(mContext, size));
+                mSizeTextView.setVisibility(View.VISIBLE);
+            }
+        }
+    }
+
+    private void updateVisualsOnDraftChanged() {
+        updateVisualsOnDraftChanged(false);
+    }
+
+    private void updateVisualsOnDraftChanged(boolean hasAttachmentsChanged) {
+        final String messageText = mComposeEditText.getText().toString();
+        final DraftMessageData draftMessageData = mBinding.getData();
+        draftMessageData.setMessageText(messageText);
+
+        final String subject = mComposeSubjectText.getText().toString();
+        draftMessageData.setMessageSubject(subject);
+        if (!TextUtils.isEmpty(subject)) {
+             mSubjectView.setVisibility(View.VISIBLE);
+        }
+
+        final boolean hasMessageText = (TextUtils.getTrimmedLength(messageText) > 0);
+        final boolean hasSubject = (TextUtils.getTrimmedLength(subject) > 0);
+        final boolean hasWorkingDraft = hasMessageText || hasSubject ||
+                mBinding.getData().hasAttachments();
+
+        final List<MessagePartData> attachments =
+                new ArrayList<MessagePartData>(draftMessageData.getReadOnlyAttachments());
+        if (draftMessageData.getIsMms()) { // MMS case
+            if (draftMessageData.hasAttachments()) {
+                if (hasAttachmentsChanged) {
+                    // Calculate message attachments size and show it.
+                    new AsyncUpdateMessageBodySizeTask(getContext(), mMessageBodySize)
+                            .executeOnThreadPool(attachments, null, null);
+                } else {
+                    // No update. Just show previous size.
+                    mMessageBodySize.setVisibility(View.VISIBLE);
+                }
+            } else {
+                mMessageBodySize.setVisibility(View.INVISIBLE);
+            }
+        } else { // SMS case
+            // Update the SMS text counter.
+            final int messageCount = draftMessageData.getNumMessagesToBeSent();
+            final int codePointsRemaining =
+                    draftMessageData.getCodePointsRemainingInCurrentMessage();
+            // Show the counter only if we are going to send more than one message OR we are getting
+            // close.
+            if (messageCount > 1
+                    || codePointsRemaining <= CODEPOINTS_REMAINING_BEFORE_COUNTER_SHOWN) {
+                // Update the remaining characters and number of messages required.
+                final String counterText =
+                        messageCount > 1
+                                ? codePointsRemaining + " / " + messageCount
+                                : String.valueOf(codePointsRemaining);
+                mMessageBodySize.setText(counterText);
+                mMessageBodySize.setVisibility(View.VISIBLE);
+            } else {
+                mMessageBodySize.setVisibility(View.INVISIBLE);
+            }
+        }
+
+        // Update the send message button. Self icon uri might be null if self participant data
+        // and/or conversation metadata hasn't been loaded by the host.
+        final Uri selfSendButtonUri = getSelfSendButtonIconUri();
+        int sendWidgetMode = SEND_WIDGET_MODE_SELF_AVATAR;
+        if (selfSendButtonUri != null) {
+            if (hasWorkingDraft && isDataLoadedForMessageSend()) {
+                UiUtils.revealOrHideViewWithAnimation(mSendButton, VISIBLE, null);
+                if (isOverriddenAvatarAGroup()) {
+                    // If the host has overriden the avatar to show a group avatar where the
+                    // send button sits, we have to hide the group avatar because it can be larger
+                    // than the send button and pieces of the avatar will stick out from behind
+                    // the send button.
+                    UiUtils.revealOrHideViewWithAnimation(mSelfSendIcon, GONE, null);
+                }
+                mMmsIndicator.setVisibility(draftMessageData.getIsMms() ? VISIBLE : INVISIBLE);
+                sendWidgetMode = SEND_WIDGET_MODE_SEND_BUTTON;
+            } else {
+                mSelfSendIcon.setImageResourceUri(selfSendButtonUri);
+                if (isOverriddenAvatarAGroup()) {
+                    UiUtils.revealOrHideViewWithAnimation(mSelfSendIcon, VISIBLE, null);
+                }
+                UiUtils.revealOrHideViewWithAnimation(mSendButton, GONE, null);
+                mMmsIndicator.setVisibility(INVISIBLE);
+                if (shouldShowSimSelector(mConversationDataModel.getData())) {
+                    sendWidgetMode = SEND_WIDGET_MODE_SIM_SELECTOR;
+                }
+            }
+        } else {
+            mSelfSendIcon.setImageResourceUri(null);
+        }
+
+        if (mSendWidgetMode != sendWidgetMode || sendWidgetMode == SEND_WIDGET_MODE_SIM_SELECTOR) {
+            setSendButtonAccessibility(sendWidgetMode);
+            mSendWidgetMode = sendWidgetMode;
+        }
+
+        // Update the text hint on the message box depending on the attachment type.
+        final int attachmentCount = attachments.size();
+        if (attachmentCount == 0) {
+            final SubscriptionListEntry subscriptionListEntry =
+                    mConversationDataModel.getData().getSubscriptionEntryForSelfParticipant(
+                            mBinding.getData().getSelfId(), false /* excludeDefault */);
+            if (subscriptionListEntry == null) {
+                mComposeEditText.setHint(R.string.compose_message_view_hint_text);
+            } else {
+                mComposeEditText.setHint(Html.fromHtml(getResources().getString(
+                        R.string.compose_message_view_hint_text_multi_sim,
+                        subscriptionListEntry.displayName)));
+            }
+        } else {
+            int type = -1;
+            for (final MessagePartData attachment : attachments) {
+                int newType;
+                if (attachment.isImage()) {
+                    newType = ContentType.TYPE_IMAGE;
+                } else if (attachment.isAudio()) {
+                    newType = ContentType.TYPE_AUDIO;
+                } else if (attachment.isVideo()) {
+                    newType = ContentType.TYPE_VIDEO;
+                } else if (attachment.isVCard()) {
+                    newType = ContentType.TYPE_VCARD;
+                } else {
+                    newType = ContentType.TYPE_OTHER;
+                }
+
+                if (type == -1) {
+                    type = newType;
+                } else if (type != newType || type == ContentType.TYPE_OTHER) {
+                    type = ContentType.TYPE_OTHER;
+                    break;
+                }
+            }
+
+            switch (type) {
+                case ContentType.TYPE_IMAGE:
+                    mComposeEditText.setHint(getResources().getQuantityString(
+                            R.plurals.compose_message_view_hint_text_photo, attachmentCount));
+                    break;
+
+                case ContentType.TYPE_AUDIO:
+                    mComposeEditText.setHint(getResources().getQuantityString(
+                            R.plurals.compose_message_view_hint_text_audio, attachmentCount));
+                    break;
+
+                case ContentType.TYPE_VIDEO:
+                    mComposeEditText.setHint(getResources().getQuantityString(
+                            R.plurals.compose_message_view_hint_text_video, attachmentCount));
+                    break;
+
+                case ContentType.TYPE_VCARD:
+                    mComposeEditText.setHint(getResources().getQuantityString(
+                            R.plurals.compose_message_view_hint_text_vcard, attachmentCount));
+                    break;
+
+                case ContentType.TYPE_OTHER:
+                    mComposeEditText.setHint(getResources().getQuantityString(
+                            R.plurals.compose_message_view_hint_text_attachments, attachmentCount));
+                    break;
+
+                default:
+                    Assert.fail("Unsupported attachment type!");
+                    break;
+            }
+        }
+    }
+
+    private void setSendButtonAccessibility(final int sendWidgetMode) {
+        switch (sendWidgetMode) {
+            case SEND_WIDGET_MODE_SELF_AVATAR:
+                // No send button and no SIM selector; the self send button is no longer
+                // important for accessibility.
+                mSelfSendIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+                mSelfSendIcon.setContentDescription(null);
+                mSendButton.setVisibility(View.GONE);
+                setSendWidgetAccessibilityTraversalOrder(SEND_WIDGET_MODE_SELF_AVATAR);
+                break;
+
+            case SEND_WIDGET_MODE_SIM_SELECTOR:
+                mSelfSendIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+                mSelfSendIcon.setContentDescription(getSimContentDescription());
+                setSendWidgetAccessibilityTraversalOrder(SEND_WIDGET_MODE_SIM_SELECTOR);
+                break;
+
+            case SEND_WIDGET_MODE_SEND_BUTTON:
+                mMmsIndicator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+                mMmsIndicator.setContentDescription(null);
+                setSendWidgetAccessibilityTraversalOrder(SEND_WIDGET_MODE_SEND_BUTTON);
+                break;
+        }
+    }
+
+    private String getSimContentDescription() {
+        final SubscriptionListEntry sub = getSelfSubscriptionListEntry();
+        if (sub != null) {
+            return getResources().getString(
+                    R.string.sim_selector_button_content_description_with_selection,
+                    sub.displayName);
+        } else {
+            return getResources().getString(
+                    R.string.sim_selector_button_content_description);
+        }
+    }
+
+    // Set accessibility traversal order of the components in the send widget.
+    private void setSendWidgetAccessibilityTraversalOrder(final int mode) {
+        if (OsUtil.isAtLeastL_MR1()) {
+            mAttachMediaButton.setAccessibilityTraversalBefore(R.id.compose_message_text);
+            switch (mode) {
+                case SEND_WIDGET_MODE_SIM_SELECTOR:
+                    mComposeEditText.setAccessibilityTraversalBefore(R.id.self_send_icon);
+                    break;
+                case SEND_WIDGET_MODE_SEND_BUTTON:
+                    mComposeEditText.setAccessibilityTraversalBefore(R.id.send_message_button);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public void afterTextChanged(final Editable editable) {
+    }
+
+    @Override
+    public void beforeTextChanged(final CharSequence s, final int start, final int count,
+            final int after) {
+        if (mHost.shouldHideAttachmentsWhenSimSelectorShown()) {
+            hideSimSelector();
+        }
+    }
+
+    private void hideSimSelector() {
+        if (mInputManager.showHideSimSelector(false /* show */, true /* animate */)) {
+            // Now that the sim selector has been hidden, reshow the attachments if they
+            // have been hidden.
+            hideAttachmentsWhenShowingSims(false /*simPickerVisible*/);
+        }
+    }
+
+    @Override
+    public void onTextChanged(final CharSequence s, final int start, final int before,
+            final int count) {
+        final BugleActionBarActivity activity = (mOriginalContext instanceof BugleActionBarActivity)
+                ? (BugleActionBarActivity) mOriginalContext : null;
+        if (activity != null && activity.getIsDestroyed()) {
+            LogUtil.v(LogUtil.BUGLE_TAG, "got onTextChanged after onDestroy");
+
+            // if we get onTextChanged after the activity is destroyed then, ah, wtf
+            // b/18176615
+            // This appears to have occurred as the result of orientation change.
+            return;
+        }
+
+        mBinding.ensureBound();
+        updateVisualsOnDraftChanged();
+    }
+
+    @Override
+    public PlainTextEditText getComposeEditText() {
+        return mComposeEditText;
+    }
+
+    public void displayPhoto(final Uri photoUri, final Rect imageBounds) {
+        mHost.displayPhoto(photoUri, imageBounds, true /* isDraft */);
+    }
+
+    public void updateConversationSelfIdOnExternalChange(final String selfId) {
+        updateConversationSelfId(selfId, true /* notify */);
+    }
+
+    /**
+     * The selfId of the conversation. As soon as the DraftMessageData successfully loads (i.e.
+     * getSelfId() is non-null), the selfId in DraftMessageData is treated as the sole source
+     * of truth for conversation self id since it reflects any pending self id change the user
+     * makes in the UI.
+     */
+    public String getConversationSelfId() {
+        return mBinding.getData().getSelfId();
+    }
+
+    public void selectSim(SubscriptionListEntry subscriptionData) {
+        final String oldSelfId = getConversationSelfId();
+        final String newSelfId = subscriptionData.selfParticipantId;
+        Assert.notNull(newSelfId);
+        // Don't attempt to change self if self hasn't been loaded, or if self hasn't changed.
+        if (oldSelfId == null || TextUtils.equals(oldSelfId, newSelfId)) {
+            return;
+        }
+        updateConversationSelfId(newSelfId, true /* notify */);
+    }
+
+    public void hideAllComposeInputs(final boolean animate) {
+        mInputManager.hideAllInputs(animate);
+    }
+
+    public void saveInputState(final Bundle outState) {
+        mInputManager.onSaveInputState(outState);
+    }
+
+    public void resetMediaPickerState() {
+        mInputManager.resetMediaPickerState();
+    }
+
+    public boolean onBackPressed() {
+        return mInputManager.onBackPressed();
+    }
+
+    public boolean onNavigationUpPressed() {
+        return mInputManager.onNavigationUpPressed();
+    }
+
+    public boolean updateActionBar(final ActionBar actionBar) {
+        return mInputManager != null ? mInputManager.updateActionBar(actionBar) : false;
+    }
+
+    public static boolean shouldShowSimSelector(final ConversationData convData) {
+        return OsUtil.isAtLeastL_MR1() &&
+                convData.getSelfParticipantsCountExcludingDefault(true /* activeOnly */) > 1;
+    }
+
+    public void sendMessageIgnoreMessageSizeLimit() {
+        sendMessageInternal(false /* checkMessageSize */);
+    }
+
+    public void onAttachmentPreviewLongClicked() {
+        mHost.showAttachmentChooser();
+    }
+
+    @Override
+    public void onDraftAttachmentLoadFailed() {
+        mHost.notifyOfAttachmentLoadFailed();
+    }
+
+    private boolean isOverriddenAvatarAGroup() {
+        final Uri overridenSelfUri = mHost.getSelfSendButtonIconUri();
+        if (overridenSelfUri == null) {
+            return false;
+        }
+        return AvatarUriUtil.TYPE_GROUP_URI.equals(AvatarUriUtil.getAvatarType(overridenSelfUri));
+    }
+
+    @Override
+    public void setAccessibility(boolean enabled) {
+        if (enabled) {
+            mAttachMediaButton.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+            mComposeEditText.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+            mSendButton.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+            setSendButtonAccessibility(mSendWidgetMode);
+        } else {
+            mSelfSendIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mComposeEditText.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mSendButton.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mAttachMediaButton.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationActivity.java b/src/com/android/messaging/ui/conversation/ConversationActivity.java
new file mode 100644
index 0000000..d8d3157
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationActivity.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.text.TextUtils;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.contact.ContactPickerFragment;
+import com.android.messaging.ui.contact.ContactPickerFragment.ContactPickerFragmentHost;
+import com.android.messaging.ui.conversation.ConversationActivityUiState.ConversationActivityUiStateHost;
+import com.android.messaging.ui.conversation.ConversationFragment.ConversationFragmentHost;
+import com.android.messaging.ui.conversationlist.ConversationListActivity;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+public class ConversationActivity extends BugleActionBarActivity
+        implements ContactPickerFragmentHost, ConversationFragmentHost,
+        ConversationActivityUiStateHost {
+    public static final int FINISH_RESULT_CODE = 1;
+    private static final String SAVED_INSTANCE_STATE_UI_STATE_KEY = "uistate";
+
+    private ConversationActivityUiState mUiState;
+
+    // Fragment transactions cannot be performed after onSaveInstanceState() has been called since
+    // it will cause state loss. We don't want to call commitAllowingStateLoss() since it's
+    // dangerous. Therefore, we note when instance state is saved and avoid performing UI state
+    // updates concerning fragments past that point.
+    private boolean mInstanceStateSaved;
+
+    // Tracks whether onPause is called.
+    private boolean mIsPaused;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.conversation_activity);
+
+        final Intent intent = getIntent();
+
+        // Do our best to restore UI state from saved instance state.
+        if (savedInstanceState != null) {
+            mUiState = savedInstanceState.getParcelable(SAVED_INSTANCE_STATE_UI_STATE_KEY);
+        } else {
+            if (intent.
+                    getBooleanExtra(UIIntents.UI_INTENT_EXTRA_GOTO_CONVERSATION_LIST, false)) {
+                // See the comment in BugleWidgetService.getViewMoreConversationsView() why this
+                // is unfortunately necessary. The Bugle desktop widget can display a list of
+                // conversations. When there are more conversations that can be displayed in
+                // the widget, the last item is a "More conversations" item. The way widgets
+                // are built, the list items can only go to a single fill-in intent which points
+                // to this ConversationActivity. When the user taps on "More conversations", we
+                // really want to go to the ConversationList. This code makes that possible.
+                finish();
+                final Intent convListIntent = new Intent(this, ConversationListActivity.class);
+                convListIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(convListIntent);
+                return;
+            }
+        }
+
+        // If saved instance state doesn't offer a clue, get the info from the intent.
+        if (mUiState == null) {
+            final String conversationId = intent.getStringExtra(
+                    UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+            mUiState = new ConversationActivityUiState(conversationId);
+        }
+        mUiState.setHost(this);
+        mInstanceStateSaved = false;
+
+        // Don't animate UI state change for initial setup.
+        updateUiState(false /* animate */);
+
+        // See if we're getting called from a widget to directly display an image or video
+        final String extraToDisplay =
+                intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_ATTACHMENT_URI);
+        if (!TextUtils.isEmpty(extraToDisplay)) {
+            final String contentType =
+                    intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_ATTACHMENT_TYPE);
+            final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(
+                    findViewById(R.id.conversation_and_compose_container));
+            if (ContentType.isImageType(contentType)) {
+                final Uri imagesUri = MessagingContentProvider.buildConversationImagesUri(
+                        mUiState.getConversationId());
+                UIIntents.get().launchFullScreenPhotoViewer(
+                        this, Uri.parse(extraToDisplay), bounds, imagesUri);
+            } else if (ContentType.isVideoType(contentType)) {
+                UIIntents.get().launchFullScreenVideoViewer(this, Uri.parse(extraToDisplay));
+            }
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(final Bundle outState) {
+        super.onSaveInstanceState(outState);
+        // After onSaveInstanceState() is called, future changes to mUiState won't update the UI
+        // anymore, because fragment transactions are not allowed past this point.
+        // For an activity recreation due to orientation change, the saved instance state keeps
+        // using the in-memory copy of the UI state instead of writing it to parcel as an
+        // optimization, so the UI state values may still change in response to, for example,
+        // focus change from the framework, making mUiState and actual UI inconsistent.
+        // Therefore, save an exact "snapshot" (clone) of the UI state object to make sure the
+        // restored UI state ALWAYS matches the actual restored UI components.
+        outState.putParcelable(SAVED_INSTANCE_STATE_UI_STATE_KEY, mUiState.clone());
+        mInstanceStateSaved = true;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // we need to reset the mInstanceStateSaved flag since we may have just been restored from
+        // a previous onStop() instead of an onDestroy().
+        mInstanceStateSaved = false;
+        mIsPaused = false;
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mIsPaused = true;
+    }
+
+    @Override
+    public void onWindowFocusChanged(final boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        final ConversationFragment conversationFragment = getConversationFragment();
+        // When the screen is turned on, the last used activity gets resumed, but it gets
+        // window focus only after the lock screen is unlocked.
+        if (hasFocus && conversationFragment != null) {
+            conversationFragment.setConversationFocus();
+        }
+    }
+
+    @Override
+    public void onDisplayHeightChanged(final int heightSpecification) {
+        super.onDisplayHeightChanged(heightSpecification);
+        invalidateActionBar();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mUiState != null) {
+            mUiState.setHost(null);
+        }
+    }
+
+    @Override
+    public void updateActionBar(final ActionBar actionBar) {
+        super.updateActionBar(actionBar);
+        final ConversationFragment conversation = getConversationFragment();
+        final ContactPickerFragment contactPicker = getContactPicker();
+        if (contactPicker != null && mUiState.shouldShowContactPickerFragment()) {
+            contactPicker.updateActionBar(actionBar);
+        } else if (conversation != null && mUiState.shouldShowConversationFragment()) {
+            conversation.updateActionBar(actionBar);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem menuItem) {
+        if (super.onOptionsItemSelected(menuItem)) {
+            return true;
+        }
+        if (menuItem.getItemId() == android.R.id.home) {
+            onNavigationUpPressed();
+            return true;
+        }
+        return false;
+    }
+
+    public void onNavigationUpPressed() {
+        // Let the conversation fragment handle the navigation up press.
+        final ConversationFragment conversationFragment = getConversationFragment();
+        if (conversationFragment != null && conversationFragment.onNavigationUpPressed()) {
+            return;
+        }
+        onFinishCurrentConversation();
+    }
+
+    @Override
+    public void onBackPressed() {
+        // If action mode is active dismiss it
+        if (getActionMode() != null) {
+            dismissActionMode();
+            return;
+        }
+
+        // Let the conversation fragment handle the back press.
+        final ConversationFragment conversationFragment = getConversationFragment();
+        if (conversationFragment != null && conversationFragment.onBackPressed()) {
+            return;
+        }
+        super.onBackPressed();
+    }
+
+    private ContactPickerFragment getContactPicker() {
+        return (ContactPickerFragment) getFragmentManager().findFragmentByTag(
+                ContactPickerFragment.FRAGMENT_TAG);
+    }
+
+    private ConversationFragment getConversationFragment() {
+        return (ConversationFragment) getFragmentManager().findFragmentByTag(
+                ConversationFragment.FRAGMENT_TAG);
+    }
+
+    @Override // From ContactPickerFragmentHost
+    public void onGetOrCreateNewConversation(final String conversationId) {
+        Assert.isTrue(conversationId != null);
+        mUiState.onGetOrCreateConversation(conversationId);
+    }
+
+    @Override // From ContactPickerFragmentHost
+    public void onBackButtonPressed() {
+        onBackPressed();
+    }
+
+    @Override // From ContactPickerFragmentHost
+    public void onInitiateAddMoreParticipants() {
+        mUiState.onAddMoreParticipants();
+    }
+
+
+    @Override
+    public void onParticipantCountChanged(final boolean canAddMoreParticipants) {
+        mUiState.onParticipantCountUpdated(canAddMoreParticipants);
+    }
+
+    @Override // From ConversationFragmentHost
+    public void onStartComposeMessage() {
+        mUiState.onStartMessageCompose();
+    }
+
+    @Override // From ConversationFragmentHost
+    public void onConversationMetadataUpdated() {
+        invalidateActionBar();
+    }
+
+    @Override // From ConversationFragmentHost
+    public void onConversationMessagesUpdated(final int numberOfMessages) {
+    }
+
+    @Override // From ConversationFragmentHost
+    public void onConversationParticipantDataLoaded(final int numberOfParticipants) {
+    }
+
+    @Override // From ConversationFragmentHost
+    public boolean isActiveAndFocused() {
+        return !mIsPaused && hasWindowFocus();
+    }
+
+    @Override // From ConversationActivityUiStateListener
+    public void onConversationContactPickerUiStateChanged(final int oldState, final int newState,
+            final boolean animate) {
+        Assert.isTrue(oldState != newState);
+        updateUiState(animate);
+    }
+
+    private void updateUiState(final boolean animate) {
+        if (mInstanceStateSaved || mIsPaused) {
+            return;
+        }
+        Assert.notNull(mUiState);
+        final Intent intent = getIntent();
+        final String conversationId = mUiState.getConversationId();
+
+        final FragmentManager fragmentManager = getFragmentManager();
+        final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+        final boolean needConversationFragment = mUiState.shouldShowConversationFragment();
+        final boolean needContactPickerFragment = mUiState.shouldShowContactPickerFragment();
+        ConversationFragment conversationFragment = getConversationFragment();
+
+        // Set up the conversation fragment.
+        if (needConversationFragment) {
+            Assert.notNull(conversationId);
+            if (conversationFragment == null) {
+                conversationFragment = new ConversationFragment();
+                fragmentTransaction.add(R.id.conversation_fragment_container,
+                        conversationFragment, ConversationFragment.FRAGMENT_TAG);
+            }
+            final MessageData draftData = intent.getParcelableExtra(
+                    UIIntents.UI_INTENT_EXTRA_DRAFT_DATA);
+            if (!needContactPickerFragment) {
+                // Once the user has committed the audience,remove the draft data from the
+                // intent to prevent reuse
+                intent.removeExtra(UIIntents.UI_INTENT_EXTRA_DRAFT_DATA);
+            }
+            conversationFragment.setHost(this);
+            conversationFragment.setConversationInfo(this, conversationId, draftData);
+        } else if (conversationFragment != null) {
+            // Don't save draft to DB when removing conversation fragment and switching to
+            // contact picking mode.  The draft is intended for the new group.
+            conversationFragment.suppressWriteDraft();
+            fragmentTransaction.remove(conversationFragment);
+        }
+
+        // Set up the contact picker fragment.
+        ContactPickerFragment contactPickerFragment = getContactPicker();
+        if (needContactPickerFragment) {
+            if (contactPickerFragment == null) {
+                contactPickerFragment = new ContactPickerFragment();
+                fragmentTransaction.add(R.id.contact_picker_fragment_container,
+                        contactPickerFragment, ContactPickerFragment.FRAGMENT_TAG);
+            }
+            contactPickerFragment.setHost(this);
+            contactPickerFragment.setContactPickingMode(mUiState.getDesiredContactPickingMode(),
+                    animate);
+        } else if (contactPickerFragment != null) {
+            fragmentTransaction.remove(contactPickerFragment);
+        }
+
+        fragmentTransaction.commit();
+        invalidateActionBar();
+    }
+
+    @Override
+    public void onFinishCurrentConversation() {
+        // Simply finish the current activity. The current design is to leave any empty
+        // conversations as is.
+        if (OsUtil.isAtLeastL()) {
+            finishAfterTransition();
+        } else {
+            finish();
+        }
+    }
+
+    @Override
+    public boolean shouldResumeComposeMessage() {
+        return mUiState.shouldResumeComposeMessage();
+    }
+
+    @SuppressWarnings("MissingSuperCall") // TODO: fix me
+    @Override
+    protected void onActivityResult(final int requestCode, final int resultCode,
+            final Intent data) {
+        if (requestCode == ConversationFragment.REQUEST_CHOOSE_ATTACHMENTS &&
+                resultCode == RESULT_OK) {
+            final ConversationFragment conversationFragment = getConversationFragment();
+            if (conversationFragment != null) {
+                conversationFragment.onAttachmentChoosen();
+            } else {
+                LogUtil.e(LogUtil.BUGLE_TAG, "ConversationFragment is missing after launching " +
+                        "AttachmentChooserActivity!");
+            }
+        } else if (resultCode == FINISH_RESULT_CODE) {
+            finish();
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationActivityUiState.java b/src/com/android/messaging/ui/conversation/ConversationActivityUiState.java
new file mode 100644
index 0000000..1469c93
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationActivityUiState.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.messaging.ui.contact.ContactPickerFragment;
+import com.android.messaging.util.Assert;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Keeps track of the different UI states that the ConversationActivity may be in. This acts as
+ * a state machine which, based on different actions (e.g. onAddMoreParticipants), notifies the
+ * ConversationActivity about any state UI change so it can update the visuals. This class
+ * implements Parcelable and it's persisted across activity tear down and relaunch.
+ */
+public class ConversationActivityUiState implements Parcelable, Cloneable {
+    interface ConversationActivityUiStateHost {
+        void onConversationContactPickerUiStateChanged(int oldState, int newState, boolean animate);
+    }
+
+    /*------ Overall UI states (conversation & contact picker) ------*/
+
+    /** Only a full screen conversation is showing. */
+    public static final int STATE_CONVERSATION_ONLY = 1;
+    /** Only a full screen contact picker is showing asking user to pick the initial contact. */
+    public static final int STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT = 2;
+    /**
+     * Only a full screen contact picker is showing asking user to pick more participants. This
+     * happens after the user picked the initial contact, and then decide to go back and add more.
+     */
+    public static final int STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS = 3;
+    /**
+     * Only a full screen contact picker is showing asking user to pick more participants. However
+     * user has reached max number of conversation participants and can add no more.
+     */
+    public static final int STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS = 4;
+    /**
+     * A hybrid mode where the conversation view + contact chips view are showing. This happens
+     * right after the user picked the initial contact for which a 1-1 conversation is fetched or
+     * created.
+     */
+    public static final int STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW = 5;
+
+    // The overall UI state of the ConversationActivity.
+    private int mConversationContactUiState;
+
+    // The currently displayed conversation (if any).
+    private String mConversationId;
+
+    // Indicates whether we should put focus in the compose message view when the
+    // ConversationFragment is attached. This is a transient state that's not persisted as
+    // part of the parcelable.
+    private boolean mPendingResumeComposeMessage = false;
+
+    // The owner ConversationActivity. This is not parceled since the instance always change upon
+    // object reuse.
+    private ConversationActivityUiStateHost mHost;
+
+    // Indicates the owning ConverastionActivity is in the process of updating its UI presentation
+    // to be in sync with the UI states. Outside of the UI updates, the UI states here should
+    // ALWAYS be consistent with the actual states of the activity.
+    private int mUiUpdateCount;
+
+    /**
+     * Create a new instance with an initial conversation id.
+     */
+    ConversationActivityUiState(final String conversationId) {
+        // The conversation activity may be initialized with only one of two states:
+        // Conversation-only (when there's a conversation id) or picking initial contact
+        // (when no conversation id is given).
+        mConversationId = conversationId;
+        mConversationContactUiState = conversationId == null ?
+                STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT : STATE_CONVERSATION_ONLY;
+    }
+
+    public void setHost(final ConversationActivityUiStateHost host) {
+        mHost = host;
+    }
+
+    public boolean shouldShowConversationFragment() {
+        return mConversationContactUiState == STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW ||
+                mConversationContactUiState == STATE_CONVERSATION_ONLY;
+    }
+
+    public boolean shouldShowContactPickerFragment() {
+        return mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS ||
+                mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS ||
+                mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT ||
+                mConversationContactUiState == STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW;
+    }
+
+    /**
+     * Returns whether there's a pending request to resume message compose (i.e. set focus to
+     * the compose message view and show the soft keyboard). If so, this request will be served
+     * when the conversation fragment get created and resumed. This happens when the user commits
+     * participant selection for a group conversation and goes back to the conversation fragment.
+     * Since conversation fragment creation happens asynchronously, we issue and track this
+     * pending request for it to be eventually fulfilled.
+     */
+    public boolean shouldResumeComposeMessage() {
+        if (mPendingResumeComposeMessage) {
+            // This is a one-shot operation that just keeps track of the pending resume compose
+            // state. This is also a non-critical operation so we don't care about failure case.
+            mPendingResumeComposeMessage = false;
+            return true;
+        }
+        return false;
+    }
+
+    public int getDesiredContactPickingMode() {
+        switch (mConversationContactUiState) {
+            case STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS:
+                return ContactPickerFragment.MODE_PICK_MORE_CONTACTS;
+            case STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS:
+                return ContactPickerFragment.MODE_PICK_MAX_PARTICIPANTS;
+            case STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT:
+                return ContactPickerFragment.MODE_PICK_INITIAL_CONTACT;
+            case STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW:
+                return ContactPickerFragment.MODE_CHIPS_ONLY;
+            default:
+                Assert.fail("Invalid contact picking mode for ConversationActivity!");
+                return ContactPickerFragment.MODE_UNDEFINED;
+        }
+    }
+
+    public String getConversationId() {
+        return mConversationId;
+    }
+
+    /**
+     * Called whenever the contact picker fragment successfully fetched or created a conversation.
+     */
+    public void onGetOrCreateConversation(final String conversationId) {
+        int newState = STATE_CONVERSATION_ONLY;
+        if (mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT) {
+            newState = STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW;
+        } else if (mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS ||
+                mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS) {
+            newState = STATE_CONVERSATION_ONLY;
+        } else {
+            // New conversation should only be created when we are in one of the contact picking
+            // modes.
+            Assert.fail("Invalid conversation activity state: can't create conversation!");
+        }
+        mConversationId = conversationId;
+        performUiStateUpdate(newState, true);
+    }
+
+    /**
+     * Called when the user started composing message. If we are in the hybrid chips state, we
+     * should commit to enter the conversation only state.
+     */
+    public void onStartMessageCompose() {
+        // This cannot happen when we are in one of the full-screen contact picking states.
+        Assert.isTrue(mConversationContactUiState != STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT &&
+                mConversationContactUiState != STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS &&
+                mConversationContactUiState != STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS);
+        if (mConversationContactUiState == STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW) {
+            performUiStateUpdate(STATE_CONVERSATION_ONLY, true);
+        }
+    }
+
+    /**
+     * Called when the user initiated an action to add more participants in the hybrid state,
+     * namely clicking on the "add more participants" button or entered a new contact chip via
+     * auto-complete.
+     */
+    public void onAddMoreParticipants() {
+        if (mConversationContactUiState == STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW) {
+            mPendingResumeComposeMessage = true;
+            performUiStateUpdate(STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS, true);
+        } else {
+            // This is only possible in the hybrid state.
+            Assert.fail("Invalid conversation activity state: can't add more participants!");
+        }
+    }
+
+    /**
+     * Called each time the number of participants is updated to check against the limit and
+     * update the ui state accordingly.
+     */
+    public void onParticipantCountUpdated(final boolean canAddMoreParticipants) {
+        if (mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS
+                && !canAddMoreParticipants) {
+            performUiStateUpdate(STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS, false);
+        } else if (mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_MAX_PARTICIPANTS
+                && canAddMoreParticipants) {
+            performUiStateUpdate(STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS, false);
+        }
+    }
+
+    private void performUiStateUpdate(final int conversationContactState, final boolean animate) {
+        // This starts one UI update cycle, during which we allow the conversation activity's
+        // UI presentation to be temporarily out of sync with the states here.
+        beginUiUpdate();
+
+        if (conversationContactState != mConversationContactUiState) {
+            final int oldState = mConversationContactUiState;
+            mConversationContactUiState = conversationContactState;
+            notifyOnOverallUiStateChanged(oldState, mConversationContactUiState, animate);
+        }
+        endUiUpdate();
+    }
+
+    private void notifyOnOverallUiStateChanged(
+            final int oldState, final int newState, final boolean animate) {
+        // Always verify state validity whenever we have a state change.
+        assertValidState();
+        Assert.isTrue(isUiUpdateInProgress());
+
+        // Only do this if we are still attached to the host. mHost can be null if the host
+        // activity is already destroyed, but due to timing the contained UI components may still
+        // receive events such as focus change and trigger a callback to the Ui state. We'd like
+        // to guard against those cases.
+        if (mHost != null) {
+            mHost.onConversationContactPickerUiStateChanged(oldState, newState, animate);
+        }
+    }
+
+    private void assertValidState() {
+        // Conversation id may be null IF AND ONLY IF the user is picking the initial contact to
+        // start a conversation.
+        Assert.isTrue((mConversationContactUiState == STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT) ==
+                (mConversationId == null));
+    }
+
+    private void beginUiUpdate() {
+        mUiUpdateCount++;
+    }
+
+    private void endUiUpdate() {
+        if (--mUiUpdateCount < 0) {
+            Assert.fail("Unbalanced Ui updates!");
+        }
+    }
+
+    private boolean isUiUpdateInProgress() {
+        return mUiUpdateCount > 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(final Parcel dest, final int flags) {
+        dest.writeInt(mConversationContactUiState);
+        dest.writeString(mConversationId);
+    }
+
+    private ConversationActivityUiState(final Parcel in) {
+        mConversationContactUiState = in.readInt();
+        mConversationId = in.readString();
+
+        // Always verify state validity whenever we initialize states.
+        assertValidState();
+    }
+
+    public static final Parcelable.Creator<ConversationActivityUiState> CREATOR
+        = new Parcelable.Creator<ConversationActivityUiState>() {
+        @Override
+        public ConversationActivityUiState createFromParcel(final Parcel in) {
+            return new ConversationActivityUiState(in);
+        }
+
+        @Override
+        public ConversationActivityUiState[] newArray(final int size) {
+            return new ConversationActivityUiState[size];
+        }
+    };
+
+    @Override
+    protected ConversationActivityUiState clone() {
+        try {
+            return (ConversationActivityUiState) super.clone();
+        } catch (CloneNotSupportedException e) {
+            Assert.fail("ConversationActivityUiState: failed to clone(). Is there a mutable " +
+                    "reference?");
+        }
+        return null;
+    }
+
+    /**
+     * allows for overridding the internal UI state. Should never be called except by test code.
+     */
+    @VisibleForTesting
+    void testSetUiState(final int uiState) {
+        mConversationContactUiState = uiState;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationFastScroller.java b/src/com/android/messaging/ui/conversation/ConversationFastScroller.java
new file mode 100644
index 0000000..f17f11e
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationFastScroller.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.drawable.StateListDrawable;
+import android.os.Handler;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+import android.util.StateSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroupOverlay;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Adds a "fast-scroll" bar to the conversation RecyclerView that shows the current position within
+ * the conversation and allows quickly moving to another position by dragging the scrollbar thumb
+ * up or down. As the thumb is dragged, we show a floating bubble alongside it that shows the
+ * date/time of the first visible message at the current position.
+ */
+public class ConversationFastScroller extends RecyclerView.OnScrollListener implements
+        OnLayoutChangeListener, RecyclerView.OnItemTouchListener {
+
+    /**
+     * Creates a {@link ConversationFastScroller} instance, attached to the provided
+     * {@link RecyclerView}.
+     *
+     * @param rv the conversation RecyclerView
+     * @param position where the scrollbar should appear (either {@code POSITION_RIGHT_SIDE} or
+     *            {@code POSITION_LEFT_SIDE})
+     * @return a new ConversationFastScroller, or {@code null} if fast-scrolling is not supported
+     *         (the feature requires Jellybean MR2 or newer)
+     */
+    public static ConversationFastScroller addTo(RecyclerView rv, int position) {
+        if (OsUtil.isAtLeastJB_MR2()) {
+            return new ConversationFastScroller(rv, position);
+        }
+        return null;
+    }
+
+    public static final int POSITION_RIGHT_SIDE = 0;
+    public static final int POSITION_LEFT_SIDE = 1;
+
+    private static final int MIN_PAGES_TO_ENABLE = 7;
+    private static final int SHOW_ANIMATION_DURATION_MS = 150;
+    private static final int HIDE_ANIMATION_DURATION_MS = 300;
+    private static final int HIDE_DELAY_MS = 1500;
+
+    private final Context mContext;
+    private final RecyclerView mRv;
+    private final ViewGroupOverlay mOverlay;
+    private final ImageView mTrackImageView;
+    private final ImageView mThumbImageView;
+    private final TextView mPreviewTextView;
+
+    private final int mTrackWidth;
+    private final int mThumbHeight;
+    private final int mPreviewHeight;
+    private final int mPreviewMinWidth;
+    private final int mPreviewMarginTop;
+    private final int mPreviewMarginLeftRight;
+    private final int mTouchSlop;
+
+    private final Rect mContainer = new Rect();
+    private final Handler mHandler = new Handler();
+
+    // Whether to render the scrollbar on the right side (otherwise it'll be on the left).
+    private final boolean mPosRight;
+
+    // Whether the scrollbar is currently visible (it may still be animating).
+    private boolean mVisible = false;
+
+    // Whether we are waiting to hide the scrollbar (i.e. scrolling has stopped).
+    private boolean mPendingHide = false;
+
+    // Whether the user is currently dragging the thumb up or down.
+    private boolean mDragging = false;
+
+    // Animations responsible for hiding the scrollbar & preview. May be null.
+    private AnimatorSet mHideAnimation;
+    private ObjectAnimator mHidePreviewAnimation;
+
+    private final Runnable mHideTrackRunnable = new Runnable() {
+        @Override
+        public void run() {
+            hide(true /* animate */);
+            mPendingHide = false;
+        }
+    };
+
+    private ConversationFastScroller(RecyclerView rv, int position) {
+        mContext = rv.getContext();
+        mRv = rv;
+        mRv.addOnLayoutChangeListener(this);
+        mRv.addOnScrollListener(this);
+        mRv.addOnItemTouchListener(this);
+        mRv.getAdapter().registerAdapterDataObserver(new AdapterDataObserver() {
+            @Override
+            public void onChanged() {
+                updateScrollPos();
+            }
+        });
+        mPosRight = (position == POSITION_RIGHT_SIDE);
+
+        // Cache the dimensions we'll need during layout
+        final Resources res = mContext.getResources();
+        mTrackWidth = res.getDimensionPixelSize(R.dimen.fastscroll_track_width);
+        mThumbHeight = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_height);
+        mPreviewHeight = res.getDimensionPixelSize(R.dimen.fastscroll_preview_height);
+        mPreviewMinWidth = res.getDimensionPixelSize(R.dimen.fastscroll_preview_min_width);
+        mPreviewMarginTop = res.getDimensionPixelOffset(R.dimen.fastscroll_preview_margin_top);
+        mPreviewMarginLeftRight = res.getDimensionPixelOffset(
+                R.dimen.fastscroll_preview_margin_left_right);
+        mTouchSlop = res.getDimensionPixelOffset(R.dimen.fastscroll_touch_slop);
+
+        final LayoutInflater inflator = LayoutInflater.from(mContext);
+        mTrackImageView = (ImageView) inflator.inflate(R.layout.fastscroll_track, null);
+        mThumbImageView = (ImageView) inflator.inflate(R.layout.fastscroll_thumb, null);
+        mPreviewTextView = (TextView) inflator.inflate(R.layout.fastscroll_preview, null);
+
+        refreshConversationThemeColor();
+
+        // Add the fast scroll views to the overlay, so they are rendered above the list
+        mOverlay = rv.getOverlay();
+        mOverlay.add(mTrackImageView);
+        mOverlay.add(mThumbImageView);
+        mOverlay.add(mPreviewTextView);
+
+        hide(false /* animate */);
+        mPreviewTextView.setAlpha(0f);
+    }
+
+    public void refreshConversationThemeColor() {
+        mPreviewTextView.setBackground(
+                ConversationDrawables.get().getFastScrollPreviewDrawable(mPosRight));
+        if (OsUtil.isAtLeastL()) {
+            final StateListDrawable drawable = new StateListDrawable();
+            drawable.addState(new int[]{ android.R.attr.state_pressed },
+                    ConversationDrawables.get().getFastScrollThumbDrawable(true /* pressed */));
+            drawable.addState(StateSet.WILD_CARD,
+                    ConversationDrawables.get().getFastScrollThumbDrawable(false /* pressed */));
+            mThumbImageView.setImageDrawable(drawable);
+        } else {
+            // Android pre-L doesn't seem to handle a StateListDrawable containing a tinted
+            // drawable (it's rendered in the filter base color, which is red), so fall back to
+            // just the regular (non-pressed) drawable.
+            mThumbImageView.setImageDrawable(
+                    ConversationDrawables.get().getFastScrollThumbDrawable(false /* pressed */));
+        }
+    }
+
+    @Override
+    public void onScrollStateChanged(final RecyclerView view, final int newState) {
+        if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
+            // Only show the scrollbar once the user starts scrolling
+            if (!mVisible && isEnabled()) {
+                show();
+            }
+            cancelAnyPendingHide();
+        } else if (newState == RecyclerView.SCROLL_STATE_IDLE && !mDragging) {
+            // Hide the scrollbar again after scrolling stops
+            hideAfterDelay();
+        }
+    }
+
+    private boolean isEnabled() {
+        final int range = mRv.computeVerticalScrollRange();
+        final int extent = mRv.computeVerticalScrollExtent();
+
+        if (range == 0 || extent == 0) {
+            return false; // Conversation isn't long enough to scroll
+        }
+        // Only enable scrollbars for conversations long enough that they would require several
+        // flings to scroll through.
+        final float pages = (float) range / extent;
+        return (pages > MIN_PAGES_TO_ENABLE);
+    }
+
+    private void show() {
+        if (mHideAnimation != null && mHideAnimation.isRunning()) {
+            mHideAnimation.cancel();
+        }
+        // Slide the scrollbar in from the side
+        ObjectAnimator trackSlide = ObjectAnimator.ofFloat(mTrackImageView, View.TRANSLATION_X, 0);
+        ObjectAnimator thumbSlide = ObjectAnimator.ofFloat(mThumbImageView, View.TRANSLATION_X, 0);
+        AnimatorSet animation = new AnimatorSet();
+        animation.playTogether(trackSlide, thumbSlide);
+        animation.setDuration(SHOW_ANIMATION_DURATION_MS);
+        animation.start();
+
+        mVisible = true;
+        updateScrollPos();
+    }
+
+    private void hideAfterDelay() {
+        cancelAnyPendingHide();
+        mHandler.postDelayed(mHideTrackRunnable, HIDE_DELAY_MS);
+        mPendingHide = true;
+    }
+
+    private void cancelAnyPendingHide() {
+        if (mPendingHide) {
+            mHandler.removeCallbacks(mHideTrackRunnable);
+        }
+    }
+
+    private void hide(boolean animate) {
+        final int hiddenTranslationX = mPosRight ? mTrackWidth : -mTrackWidth;
+        if (animate) {
+            // Slide the scrollbar off to the side
+            ObjectAnimator trackSlide = ObjectAnimator.ofFloat(mTrackImageView, View.TRANSLATION_X,
+                    hiddenTranslationX);
+            ObjectAnimator thumbSlide = ObjectAnimator.ofFloat(mThumbImageView, View.TRANSLATION_X,
+                    hiddenTranslationX);
+            mHideAnimation = new AnimatorSet();
+            mHideAnimation.playTogether(trackSlide, thumbSlide);
+            mHideAnimation.setDuration(HIDE_ANIMATION_DURATION_MS);
+            mHideAnimation.start();
+        } else {
+            mTrackImageView.setTranslationX(hiddenTranslationX);
+            mThumbImageView.setTranslationX(hiddenTranslationX);
+        }
+
+        mVisible = false;
+    }
+
+    private void showPreview() {
+        if (mHidePreviewAnimation != null && mHidePreviewAnimation.isRunning()) {
+            mHidePreviewAnimation.cancel();
+        }
+        mPreviewTextView.setAlpha(1f);
+    }
+
+    private void hidePreview() {
+        mHidePreviewAnimation = ObjectAnimator.ofFloat(mPreviewTextView, View.ALPHA, 0f);
+        mHidePreviewAnimation.setDuration(HIDE_ANIMATION_DURATION_MS);
+        mHidePreviewAnimation.start();
+    }
+
+    @Override
+    public void onScrolled(final RecyclerView view, final int dx, final int dy) {
+        updateScrollPos();
+    }
+
+    private void updateScrollPos() {
+        if (!mVisible) {
+            return;
+        }
+        final int verticalScrollLength = mContainer.height() - mThumbHeight;
+        final int verticalScrollStart = mContainer.top + mThumbHeight / 2;
+
+        final float scrollRatio = computeScrollRatio();
+        final int thumbCenterY = verticalScrollStart + (int)(verticalScrollLength * scrollRatio);
+        layoutThumb(thumbCenterY);
+
+        if (mDragging) {
+            updatePreviewText();
+            layoutPreview(thumbCenterY);
+        }
+    }
+
+    /**
+     * Returns the current position in the conversation, as a value between 0 and 1, inclusive.
+     * The top of the conversation is 0, the bottom is 1, the exact middle is 0.5, and so on.
+     */
+    private float computeScrollRatio() {
+        final int range = mRv.computeVerticalScrollRange();
+        final int extent = mRv.computeVerticalScrollExtent();
+        int offset = mRv.computeVerticalScrollOffset();
+
+        if (range == 0 || extent == 0) {
+            // If the conversation doesn't scroll, we're at the bottom.
+            return 1.0f;
+        }
+        final int scrollRange = range - extent;
+        offset = Math.min(offset, scrollRange);
+        return offset / (float) scrollRange;
+    }
+
+    private void updatePreviewText() {
+        final LinearLayoutManager lm = (LinearLayoutManager) mRv.getLayoutManager();
+        final int pos = lm.findFirstVisibleItemPosition();
+        if (pos == RecyclerView.NO_POSITION) {
+            return;
+        }
+        final ViewHolder vh = mRv.findViewHolderForAdapterPosition(pos);
+        if (vh == null) {
+            // This can happen if the messages update while we're dragging the thumb.
+            return;
+        }
+        final ConversationMessageView messageView = (ConversationMessageView) vh.itemView;
+        final ConversationMessageData messageData = messageView.getData();
+        final long timestamp = messageData.getReceivedTimeStamp();
+        final CharSequence timestampText = Dates.getFastScrollPreviewTimeString(timestamp);
+        mPreviewTextView.setText(timestampText);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+        if (!mVisible) {
+            return false;
+        }
+        // If the user presses down on the scroll thumb, we'll start intercepting events from the
+        // RecyclerView so we can handle the move events while they're dragging it up/down.
+        final int action = e.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                if (isInsideThumb(e.getX(), e.getY())) {
+                    startDrag();
+                    return true;
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mDragging) {
+                    return true;
+                }
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                if (mDragging) {
+                    cancelDrag();
+                }
+                return false;
+        }
+        return false;
+    }
+
+    private boolean isInsideThumb(float x, float y) {
+        final int hitTargetLeft = mThumbImageView.getLeft() - mTouchSlop;
+        final int hitTargetRight = mThumbImageView.getRight() + mTouchSlop;
+
+        if (x < hitTargetLeft || x > hitTargetRight) {
+            return false;
+        }
+        if (y < mThumbImageView.getTop() || y > mThumbImageView.getBottom()) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+        if (!mDragging) {
+            return;
+        }
+        final int action = e.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_MOVE:
+                handleDragMove(e.getY());
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                cancelDrag();
+                break;
+        }
+    }
+
+    @Override
+    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+    }
+
+    private void startDrag() {
+        mDragging = true;
+        mThumbImageView.setPressed(true);
+        updateScrollPos();
+        showPreview();
+        cancelAnyPendingHide();
+    }
+
+    private void handleDragMove(float y) {
+        final int verticalScrollLength = mContainer.height() - mThumbHeight;
+        final int verticalScrollStart = mContainer.top + (mThumbHeight / 2);
+
+        // Convert the desired position from px to a scroll position in the conversation.
+        float dragScrollRatio = (y - verticalScrollStart) / verticalScrollLength;
+        dragScrollRatio = Math.max(dragScrollRatio, 0.0f);
+        dragScrollRatio = Math.min(dragScrollRatio, 1.0f);
+
+        // Scroll the RecyclerView to a new position.
+        final int itemCount = mRv.getAdapter().getItemCount();
+        final int itemPos = (int)((itemCount - 1) * dragScrollRatio);
+        mRv.scrollToPosition(itemPos);
+    }
+
+    private void cancelDrag() {
+        mDragging = false;
+        mThumbImageView.setPressed(false);
+        hidePreview();
+        hideAfterDelay();
+    }
+
+    @Override
+    public void onLayoutChange(View v, int left, int top, int right, int bottom,
+            int oldLeft, int oldTop, int oldRight, int oldBottom) {
+        if (!mVisible) {
+            hide(false /* animate */);
+        }
+        // The container is the size of the RecyclerView that's visible on screen. We have to
+        // exclude the top padding, because it's usually hidden behind the conversation action bar.
+        mContainer.set(left, top + mRv.getPaddingTop(), right, bottom);
+        layoutTrack();
+        updateScrollPos();
+    }
+
+    private void layoutTrack() {
+        int trackHeight = Math.max(0, mContainer.height());
+        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(mTrackWidth, MeasureSpec.EXACTLY);
+        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(trackHeight, MeasureSpec.EXACTLY);
+        mTrackImageView.measure(widthMeasureSpec, heightMeasureSpec);
+
+        int left = mPosRight ? (mContainer.right - mTrackWidth) : mContainer.left;
+        int top = mContainer.top;
+        int right = mPosRight ? mContainer.right : (mContainer.left + mTrackWidth);
+        int bottom = mContainer.bottom;
+        mTrackImageView.layout(left, top, right, bottom);
+    }
+
+    private void layoutThumb(int centerY) {
+        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(mTrackWidth, MeasureSpec.EXACTLY);
+        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(mThumbHeight, MeasureSpec.EXACTLY);
+        mThumbImageView.measure(widthMeasureSpec, heightMeasureSpec);
+
+        int left = mPosRight ? (mContainer.right - mTrackWidth) : mContainer.left;
+        int top = centerY - (mThumbImageView.getHeight() / 2);
+        int right = mPosRight ? mContainer.right : (mContainer.left + mTrackWidth);
+        int bottom = top + mThumbHeight;
+        mThumbImageView.layout(left, top, right, bottom);
+    }
+
+    private void layoutPreview(int centerY) {
+        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(mContainer.width(), MeasureSpec.AT_MOST);
+        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(mPreviewHeight, MeasureSpec.EXACTLY);
+        mPreviewTextView.measure(widthMeasureSpec, heightMeasureSpec);
+
+        // Ensure that the preview bubble is at least as wide as it is tall
+        if (mPreviewTextView.getMeasuredWidth() < mPreviewMinWidth) {
+            widthMeasureSpec = MeasureSpec.makeMeasureSpec(mPreviewMinWidth, MeasureSpec.EXACTLY);
+            mPreviewTextView.measure(widthMeasureSpec, heightMeasureSpec);
+        }
+        final int previewMinY = mContainer.top + mPreviewMarginTop;
+
+        final int left, right;
+        if (mPosRight) {
+            right = mContainer.right - mTrackWidth - mPreviewMarginLeftRight;
+            left = right - mPreviewTextView.getMeasuredWidth();
+        } else {
+            left = mContainer.left + mTrackWidth + mPreviewMarginLeftRight;
+            right = left + mPreviewTextView.getMeasuredWidth();
+        }
+
+        int bottom = centerY;
+        int top = bottom - mPreviewTextView.getMeasuredHeight();
+        if (top < previewMinY) {
+            top = previewMinY;
+            bottom = top + mPreviewTextView.getMeasuredHeight();
+        }
+        mPreviewTextView.layout(left, top, right, bottom);
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationFragment.java b/src/com/android/messaging/ui/conversation/ConversationFragment.java
new file mode 100644
index 0000000..6eb7089
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationFragment.java
@@ -0,0 +1,1672 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DownloadManager;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.BroadcastReceiver;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.database.Cursor;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Parcelable;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import androidx.appcompat.app.ActionBar;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+import android.view.ActionMode;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.InsertNewMessageAction;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.ConversationParticipantsData;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageDataListener;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.ui.AttachmentPreview;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.ui.SnackBar;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.animation.PopupTransitionAnimation;
+import com.android.messaging.ui.contact.AddContactsConfirmationDialog;
+import com.android.messaging.ui.conversation.ComposeMessageView.IComposeMessageViewHost;
+import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputHost;
+import com.android.messaging.ui.conversation.ConversationMessageView.ConversationMessageViewHost;
+import com.android.messaging.ui.mediapicker.MediaPicker;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ChangeDefaultSmsAppHelper;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.TextUtil;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Shows a list of messages/parts comprising a conversation.
+ */
+public class ConversationFragment extends Fragment implements ConversationDataListener,
+        IComposeMessageViewHost, ConversationMessageViewHost, ConversationInputHost,
+        DraftMessageDataListener {
+
+    public interface ConversationFragmentHost extends ImeUtil.ImeStateHost {
+        void onStartComposeMessage();
+        void onConversationMetadataUpdated();
+        boolean shouldResumeComposeMessage();
+        void onFinishCurrentConversation();
+        void invalidateActionBar();
+        ActionMode startActionMode(ActionMode.Callback callback);
+        void dismissActionMode();
+        ActionMode getActionMode();
+        void onConversationMessagesUpdated(int numberOfMessages);
+        void onConversationParticipantDataLoaded(int numberOfParticipants);
+        boolean isActiveAndFocused();
+    }
+
+    public static final String FRAGMENT_TAG = "conversation";
+
+    static final int REQUEST_CHOOSE_ATTACHMENTS = 2;
+    private static final int JUMP_SCROLL_THRESHOLD = 15;
+    // We animate the message from draft to message list, if we the message doesn't show up in the
+    // list within this time limit, then we just do a fade in animation instead
+    public static final int MESSAGE_ANIMATION_MAX_WAIT = 500;
+
+    private ComposeMessageView mComposeMessageView;
+    private RecyclerView mRecyclerView;
+    private ConversationMessageAdapter mAdapter;
+    private ConversationFastScroller mFastScroller;
+
+    private View mConversationComposeDivider;
+    private ChangeDefaultSmsAppHelper mChangeDefaultSmsAppHelper;
+
+    private String mConversationId;
+    // If the fragment receives a draft as part of the invocation this is set
+    private MessageData mIncomingDraft;
+
+    // This binding keeps track of our associated ConversationData instance
+    // A binding should have the lifetime of the owning component,
+    //  don't recreate, unbind and bind if you need new data
+    @VisibleForTesting
+    final Binding<ConversationData> mBinding = BindingBase.createBinding(this);
+
+    // Saved Instance State Data - only for temporal data which is nice to maintain but not
+    // critical for correctness.
+    private static final String SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY = "conversationViewState";
+    private Parcelable mListState;
+
+    private ConversationFragmentHost mHost;
+
+    protected List<Integer> mFilterResults;
+
+    // The minimum scrolling distance between RecyclerView's scroll change event beyong which
+    // a fling motion is considered fast, in which case we'll delay load image attachments for
+    // perf optimization.
+    private int mFastFlingThreshold;
+
+    // ConversationMessageView that is currently selected
+    private ConversationMessageView mSelectedMessage;
+
+    // Attachment data for the attachment within the selected message that was long pressed
+    private MessagePartData mSelectedAttachment;
+
+    // Normally, as soon as draft message is loaded, we trust the UI state held in
+    // ComposeMessageView to be the only source of truth (incl. the conversation self id). However,
+    // there can be external events that forces the UI state to change, such as SIM state changes
+    // or SIM auto-switching on receiving a message. This receiver is used to receive such
+    // local broadcast messages and reflect the change in the UI.
+    private final BroadcastReceiver mConversationSelfIdChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(final Context context, final Intent intent) {
+            final String conversationId =
+                    intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+            final String selfId =
+                    intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_SELF_ID);
+            Assert.notNull(conversationId);
+            Assert.notNull(selfId);
+            if (isBound() && TextUtils
+                    .equals(mBinding.getData().getConversationId(), conversationId)) {
+                mComposeMessageView.updateConversationSelfIdOnExternalChange(selfId);
+            }
+        }
+    };
+
+    // Flag to prevent writing draft to DB on pause
+    private boolean mSuppressWriteDraft;
+
+    // Indicates whether local draft should be cleared due to external draft changes that must
+    // be reloaded from db
+    private boolean mClearLocalDraft;
+    private ImmutableBindingRef<DraftMessageData> mDraftMessageDataModel;
+
+    private boolean isScrolledToBottom() {
+        if (mRecyclerView.getChildCount() == 0) {
+            return true;
+        }
+        final View lastView = mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1);
+        int lastVisibleItem = ((LinearLayoutManager) mRecyclerView
+                .getLayoutManager()).findLastVisibleItemPosition();
+        if (lastVisibleItem < 0) {
+            // If the recyclerView height is 0, then the last visible item position is -1
+            // Try to compute the position of the last item, even though it's not visible
+            final long id = mRecyclerView.getChildItemId(lastView);
+            final RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForItemId(id);
+            if (holder != null) {
+                lastVisibleItem = holder.getAdapterPosition();
+            }
+        }
+        final int totalItemCount = mRecyclerView.getAdapter().getItemCount();
+        final boolean isAtBottom = (lastVisibleItem + 1 == totalItemCount);
+        return isAtBottom && lastView.getBottom() <= mRecyclerView.getHeight();
+    }
+
+    private void scrollToBottom(final boolean smoothScroll) {
+        if (mAdapter.getItemCount() > 0) {
+            scrollToPosition(mAdapter.getItemCount() - 1, smoothScroll);
+        }
+    }
+
+    private int mScrollToDismissThreshold;
+    private final RecyclerView.OnScrollListener mListScrollListener =
+        new RecyclerView.OnScrollListener() {
+            // Keeps track of cumulative scroll delta during a scroll event, which we may use to
+            // hide the media picker & co.
+            private int mCumulativeScrollDelta;
+            private boolean mScrollToDismissHandled;
+            private boolean mWasScrolledToBottom = true;
+            private int mScrollState = RecyclerView.SCROLL_STATE_IDLE;
+
+            @Override
+            public void onScrollStateChanged(final RecyclerView view, final int newState) {
+                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                    // Reset scroll states.
+                    mCumulativeScrollDelta = 0;
+                    mScrollToDismissHandled = false;
+                } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
+                    mRecyclerView.getItemAnimator().endAnimations();
+                }
+                mScrollState = newState;
+            }
+
+            @Override
+            public void onScrolled(final RecyclerView view, final int dx, final int dy) {
+                if (mScrollState == RecyclerView.SCROLL_STATE_DRAGGING &&
+                        !mScrollToDismissHandled) {
+                    mCumulativeScrollDelta += dy;
+                    // Dismiss the keyboard only when the user scroll up (into the past).
+                    if (mCumulativeScrollDelta < -mScrollToDismissThreshold) {
+                        mComposeMessageView.hideAllComposeInputs(false /* animate */);
+                        mScrollToDismissHandled = true;
+                    }
+                }
+                if (mWasScrolledToBottom != isScrolledToBottom()) {
+                    mConversationComposeDivider.animate().alpha(isScrolledToBottom() ? 0 : 1);
+                    mWasScrolledToBottom = isScrolledToBottom();
+                }
+            }
+    };
+
+    private final ActionMode.Callback mMessageActionModeCallback = new ActionMode.Callback() {
+        @Override
+        public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+            if (mSelectedMessage == null) {
+                return false;
+            }
+            final ConversationMessageData data = mSelectedMessage.getData();
+            final MenuInflater menuInflater = getActivity().getMenuInflater();
+            menuInflater.inflate(R.menu.conversation_fragment_select_menu, menu);
+            menu.findItem(R.id.action_download).setVisible(data.getShowDownloadMessage());
+            menu.findItem(R.id.action_send).setVisible(data.getShowResendMessage());
+
+            // ShareActionProvider does not work with ActionMode. So we use a normal menu item.
+            menu.findItem(R.id.share_message_menu).setVisible(data.getCanForwardMessage());
+            menu.findItem(R.id.save_attachment).setVisible(mSelectedAttachment != null);
+            menu.findItem(R.id.forward_message_menu).setVisible(data.getCanForwardMessage());
+
+            // TODO: We may want to support copying attachments in the future, but it's
+            // unclear which attachment to pick when we make this context menu at the message level
+            // instead of the part level
+            menu.findItem(R.id.copy_text).setVisible(data.getCanCopyMessageToClipboard());
+
+            return true;
+        }
+
+        @Override
+        public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+            return true;
+        }
+
+        @Override
+        public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+            final ConversationMessageData data = mSelectedMessage.getData();
+            final String messageId = data.getMessageId();
+            switch (menuItem.getItemId()) {
+                case R.id.save_attachment:
+                    if (OsUtil.hasStoragePermission()) {
+                        final SaveAttachmentTask saveAttachmentTask = new SaveAttachmentTask(
+                                getActivity());
+                        for (final MessagePartData part : data.getAttachments()) {
+                            saveAttachmentTask.addAttachmentToSave(part.getContentUri(),
+                                    part.getContentType());
+                        }
+                        if (saveAttachmentTask.getAttachmentCount() > 0) {
+                            saveAttachmentTask.executeOnThreadPool();
+                            mHost.dismissActionMode();
+                        }
+                    } else {
+                        getActivity().requestPermissions(
+                                new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
+                    }
+                    return true;
+                case R.id.action_delete_message:
+                    if (mSelectedMessage != null) {
+                        deleteMessage(messageId);
+                    }
+                    return true;
+                case R.id.action_download:
+                    if (mSelectedMessage != null) {
+                        retryDownload(messageId);
+                        mHost.dismissActionMode();
+                    }
+                    return true;
+                case R.id.action_send:
+                    if (mSelectedMessage != null) {
+                        retrySend(messageId);
+                        mHost.dismissActionMode();
+                    }
+                    return true;
+                case R.id.copy_text:
+                    Assert.isTrue(data.hasText());
+                    final ClipboardManager clipboard = (ClipboardManager) getActivity()
+                            .getSystemService(Context.CLIPBOARD_SERVICE);
+                    clipboard.setPrimaryClip(
+                            ClipData.newPlainText(null /* label */, data.getText()));
+                    mHost.dismissActionMode();
+                    return true;
+                case R.id.details_menu:
+                    MessageDetailsDialog.show(
+                            getActivity(), data, mBinding.getData().getParticipants(),
+                            mBinding.getData().getSelfParticipantById(data.getSelfParticipantId()));
+                    mHost.dismissActionMode();
+                    return true;
+                case R.id.share_message_menu:
+                    shareMessage(data);
+                    mHost.dismissActionMode();
+                    return true;
+                case R.id.forward_message_menu:
+                    // TODO: Currently we are forwarding one part at a time, instead of
+                    // the entire message. Change this to forwarding the entire message when we
+                    // use message-based cursor in conversation.
+                    final MessageData message = mBinding.getData().createForwardedMessage(data);
+                    UIIntents.get().launchForwardMessageActivity(getActivity(), message);
+                    mHost.dismissActionMode();
+                    return true;
+            }
+            return false;
+        }
+
+        private void shareMessage(final ConversationMessageData data) {
+            // Figure out what to share.
+            MessagePartData attachmentToShare = mSelectedAttachment;
+            // If the user long-pressed on the background, we will share the text (if any)
+            // or the first attachment.
+            if (mSelectedAttachment == null
+                    && TextUtil.isAllWhitespace(data.getText())) {
+                final List<MessagePartData> attachments = data.getAttachments();
+                if (attachments.size() > 0) {
+                    attachmentToShare = attachments.get(0);
+                }
+            }
+
+            final Intent shareIntent = new Intent();
+            shareIntent.setAction(Intent.ACTION_SEND);
+            if (attachmentToShare == null) {
+                shareIntent.putExtra(Intent.EXTRA_TEXT, data.getText());
+                shareIntent.setType("text/plain");
+            } else {
+                shareIntent.putExtra(
+                        Intent.EXTRA_STREAM, attachmentToShare.getContentUri());
+                shareIntent.setType(attachmentToShare.getContentType());
+            }
+            final CharSequence title = getResources().getText(R.string.action_share);
+            startActivity(Intent.createChooser(shareIntent, title));
+        }
+
+        @Override
+        public void onDestroyActionMode(final ActionMode actionMode) {
+            selectMessage(null);
+        }
+    };
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mFastFlingThreshold = getResources().getDimensionPixelOffset(
+                R.dimen.conversation_fast_fling_threshold);
+        mAdapter = new ConversationMessageAdapter(getActivity(), null, this,
+                null,
+                // Sets the item click listener on the Recycler item views.
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(final View v) {
+                        final ConversationMessageView messageView = (ConversationMessageView) v;
+                        handleMessageClick(messageView);
+                    }
+                },
+                new View.OnLongClickListener() {
+                    @Override
+                    public boolean onLongClick(final View view) {
+                        selectMessage((ConversationMessageView) view);
+                        return true;
+                    }
+                }
+        );
+    }
+
+    /**
+     * setConversationInfo() may be called before or after onCreate(). When a user initiate a
+     * conversation from compose, the ConversationActivity creates this fragment and calls
+     * setConversationInfo(), so it happens before onCreate(). However, when the activity is
+     * restored from saved instance state, the ConversationFragment is created automatically by
+     * the fragment, before ConversationActivity has a chance to call setConversationInfo(). Since
+     * the ability to start loading data depends on both methods being called, we need to start
+     * loading when onActivityCreated() is called, which is guaranteed to happen after both.
+     */
+    @Override
+    public void onActivityCreated(final Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        // Delay showing the message list until the participant list is loaded.
+        mRecyclerView.setVisibility(View.INVISIBLE);
+        mBinding.ensureBound();
+        mBinding.getData().init(getLoaderManager(), mBinding);
+
+        // Build the input manager with all its required dependencies and pass it along to the
+        // compose message view.
+        final ConversationInputManager inputManager = new ConversationInputManager(
+                getActivity(), this, mComposeMessageView, mHost, getFragmentManagerToUse(),
+                mBinding, mComposeMessageView.getDraftDataModel(), savedInstanceState);
+        mComposeMessageView.setInputManager(inputManager);
+        mComposeMessageView.setConversationDataModel(BindingBase.createBindingReference(mBinding));
+        mHost.invalidateActionBar();
+
+        mDraftMessageDataModel =
+                BindingBase.createBindingReference(mComposeMessageView.getDraftDataModel());
+        mDraftMessageDataModel.getData().addListener(this);
+    }
+
+    public void onAttachmentChoosen() {
+        // Attachment has been choosen in the AttachmentChooserActivity, so clear local draft
+        // and reload draft on resume.
+        mClearLocalDraft = true;
+    }
+
+    private int getScrollToMessagePosition() {
+        final Activity activity = getActivity();
+        if (activity == null) {
+            return -1;
+        }
+
+        final Intent intent = activity.getIntent();
+        if (intent == null) {
+            return -1;
+        }
+
+        return intent.getIntExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_POSITION, -1);
+    }
+
+    private void clearScrollToMessagePosition() {
+        final Activity activity = getActivity();
+        if (activity == null) {
+            return;
+        }
+
+        final Intent intent = activity.getIntent();
+        if (intent == null) {
+            return;
+        }
+        intent.putExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_POSITION, -1);
+    }
+
+    private final Handler mHandler = new Handler();
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.conversation_fragment, container, false);
+        mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
+        final LinearLayoutManager manager = new LinearLayoutManager(getActivity());
+        manager.setStackFromEnd(true);
+        manager.setReverseLayout(false);
+        mRecyclerView.setHasFixedSize(true);
+        mRecyclerView.setLayoutManager(manager);
+        mRecyclerView.setItemAnimator(new DefaultItemAnimator() {
+            private final List<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>();
+            private PopupTransitionAnimation mPopupTransitionAnimation;
+
+            @Override
+            public boolean animateAdd(final ViewHolder holder) {
+                final ConversationMessageView view =
+                        (ConversationMessageView) holder.itemView;
+                final ConversationMessageData data = view.getData();
+                endAnimation(holder);
+                final long timeSinceSend = System.currentTimeMillis() - data.getReceivedTimeStamp();
+                if (data.getReceivedTimeStamp() ==
+                                InsertNewMessageAction.getLastSentMessageTimestamp() &&
+                        !data.getIsIncoming() &&
+                        timeSinceSend < MESSAGE_ANIMATION_MAX_WAIT) {
+                    final ConversationMessageBubbleView messageBubble =
+                            (ConversationMessageBubbleView) view
+                                    .findViewById(R.id.message_content);
+                    final Rect startRect = UiUtils.getMeasuredBoundsOnScreen(mComposeMessageView);
+                    final View composeBubbleView = mComposeMessageView.findViewById(
+                            R.id.compose_message_text);
+                    final Rect composeBubbleRect =
+                            UiUtils.getMeasuredBoundsOnScreen(composeBubbleView);
+                    final AttachmentPreview attachmentView =
+                            (AttachmentPreview) mComposeMessageView.findViewById(
+                                    R.id.attachment_draft_view);
+                    final Rect attachmentRect = UiUtils.getMeasuredBoundsOnScreen(attachmentView);
+                    if (attachmentView.getVisibility() == View.VISIBLE) {
+                        startRect.top = attachmentRect.top;
+                    } else {
+                        startRect.top = composeBubbleRect.top;
+                    }
+                    startRect.top -= view.getPaddingTop();
+                    startRect.bottom =
+                            composeBubbleRect.bottom;
+                    startRect.left += view.getPaddingRight();
+
+                    view.setAlpha(0);
+                    mPopupTransitionAnimation = new PopupTransitionAnimation(startRect, view);
+                    mPopupTransitionAnimation.setOnStartCallback(new Runnable() {
+                            @Override
+                            public void run() {
+                                final int startWidth = composeBubbleRect.width();
+                                attachmentView.onMessageAnimationStart();
+                                messageBubble.kickOffMorphAnimation(startWidth,
+                                        messageBubble.findViewById(R.id.message_text_and_info)
+                                        .getMeasuredWidth());
+                            }
+                        });
+                    mPopupTransitionAnimation.setOnStopCallback(new Runnable() {
+                            @Override
+                            public void run() {
+                                view.setAlpha(1);
+                                dispatchAddFinished(holder);
+                            }
+                        });
+                    mPopupTransitionAnimation.startAfterLayoutComplete();
+                    mAddAnimations.add(holder);
+                    return true;
+                } else {
+                    return super.animateAdd(holder);
+                }
+            }
+
+            @Override
+            public void endAnimation(final ViewHolder holder) {
+                if (mAddAnimations.remove(holder)) {
+                    holder.itemView.clearAnimation();
+                }
+                super.endAnimation(holder);
+            }
+
+            @Override
+            public void endAnimations() {
+                for (final ViewHolder holder : mAddAnimations) {
+                    holder.itemView.clearAnimation();
+                }
+                mAddAnimations.clear();
+                if (mPopupTransitionAnimation != null) {
+                    mPopupTransitionAnimation.cancel();
+                }
+                super.endAnimations();
+            }
+        });
+        mRecyclerView.setAdapter(mAdapter);
+
+        if (savedInstanceState != null) {
+            mListState = savedInstanceState.getParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY);
+        }
+
+        mConversationComposeDivider = view.findViewById(R.id.conversation_compose_divider);
+        mScrollToDismissThreshold = ViewConfiguration.get(getActivity()).getScaledTouchSlop();
+        mRecyclerView.addOnScrollListener(mListScrollListener);
+        mFastScroller = ConversationFastScroller.addTo(mRecyclerView,
+                UiUtils.isRtlMode() ? ConversationFastScroller.POSITION_LEFT_SIDE :
+                    ConversationFastScroller.POSITION_RIGHT_SIDE);
+
+        mComposeMessageView = (ComposeMessageView)
+                view.findViewById(R.id.message_compose_view_container);
+        // Bind the compose message view to the DraftMessageData
+        mComposeMessageView.bind(DataModel.get().createDraftMessageData(
+                mBinding.getData().getConversationId()), this);
+
+        return view;
+    }
+
+    private void scrollToPosition(final int targetPosition, final boolean smoothScroll) {
+        if (smoothScroll) {
+            final int maxScrollDelta = JUMP_SCROLL_THRESHOLD;
+
+            final LinearLayoutManager layoutManager =
+                    (LinearLayoutManager) mRecyclerView.getLayoutManager();
+            final int firstVisibleItemPosition =
+                    layoutManager.findFirstVisibleItemPosition();
+            final int delta = targetPosition - firstVisibleItemPosition;
+            final int intermediatePosition;
+
+            if (delta > maxScrollDelta) {
+                intermediatePosition = Math.max(0, targetPosition - maxScrollDelta);
+            } else if (delta < -maxScrollDelta) {
+                final int count = layoutManager.getItemCount();
+                intermediatePosition = Math.min(count - 1, targetPosition + maxScrollDelta);
+            } else {
+                intermediatePosition = -1;
+            }
+            if (intermediatePosition != -1) {
+                mRecyclerView.scrollToPosition(intermediatePosition);
+            }
+            mRecyclerView.smoothScrollToPosition(targetPosition);
+        } else {
+            mRecyclerView.scrollToPosition(targetPosition);
+        }
+    }
+
+    private int getScrollPositionFromBottom() {
+        final LinearLayoutManager layoutManager =
+                (LinearLayoutManager) mRecyclerView.getLayoutManager();
+        final int lastVisibleItem =
+                layoutManager.findLastVisibleItemPosition();
+        return Math.max(mAdapter.getItemCount() - 1 - lastVisibleItem, 0);
+    }
+
+    /**
+     * Display a photo using the Photoviewer component.
+     */
+    @Override
+    public void displayPhoto(final Uri photoUri, final Rect imageBounds, final boolean isDraft) {
+        displayPhoto(photoUri, imageBounds, isDraft, mConversationId, getActivity());
+    }
+
+    public static void displayPhoto(final Uri photoUri, final Rect imageBounds,
+            final boolean isDraft, final String conversationId, final Activity activity) {
+        final Uri imagesUri =
+                isDraft ? MessagingContentProvider.buildDraftImagesUri(conversationId)
+                        : MessagingContentProvider.buildConversationImagesUri(conversationId);
+        UIIntents.get().launchFullScreenPhotoViewer(
+                activity, photoUri, imageBounds, imagesUri);
+    }
+
+    private void selectMessage(final ConversationMessageView messageView) {
+        selectMessage(messageView, null /* attachment */);
+    }
+
+    private void selectMessage(final ConversationMessageView messageView,
+            final MessagePartData attachment) {
+        mSelectedMessage = messageView;
+        if (mSelectedMessage == null) {
+            mAdapter.setSelectedMessage(null);
+            mHost.dismissActionMode();
+            mSelectedAttachment = null;
+            return;
+        }
+        mSelectedAttachment = attachment;
+        mAdapter.setSelectedMessage(messageView.getData().getMessageId());
+        mHost.startActionMode(mMessageActionModeCallback);
+    }
+
+    @Override
+    public void onSaveInstanceState(final Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mListState != null) {
+            outState.putParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY, mListState);
+        }
+        mComposeMessageView.saveInputState(outState);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        if (mIncomingDraft == null) {
+            mComposeMessageView.requestDraftMessage(mClearLocalDraft);
+        } else {
+            mComposeMessageView.setDraftMessage(mIncomingDraft);
+            mIncomingDraft = null;
+        }
+        mClearLocalDraft = false;
+
+        // On resume, check if there's a pending request for resuming message compose. This
+        // may happen when the user commits the contact selection for a group conversation and
+        // goes from compose back to the conversation fragment.
+        if (mHost.shouldResumeComposeMessage()) {
+            mComposeMessageView.resumeComposeMessage();
+        }
+
+        setConversationFocus();
+
+        // On resume, invalidate all message views to show the updated timestamp.
+        mAdapter.notifyDataSetChanged();
+
+        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
+                mConversationSelfIdChangeReceiver,
+                new IntentFilter(UIIntents.CONVERSATION_SELF_ID_CHANGE_BROADCAST_ACTION));
+    }
+
+    void setConversationFocus() {
+        if (mHost.isActiveAndFocused()) {
+            mBinding.getData().setFocus();
+        }
+    }
+
+    @Override
+    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+        if (mHost.getActionMode() != null) {
+            return;
+        }
+
+        inflater.inflate(R.menu.conversation_menu, menu);
+
+        final ConversationData data = mBinding.getData();
+
+        // Disable the "people & options" item if we haven't loaded participants yet.
+        menu.findItem(R.id.action_people_and_options).setEnabled(data.getParticipantsLoaded());
+
+        // See if we can show add contact action.
+        final ParticipantData participant = data.getOtherParticipant();
+        final boolean addContactActionVisible = (participant != null
+                && TextUtils.isEmpty(participant.getLookupKey()));
+        menu.findItem(R.id.action_add_contact).setVisible(addContactActionVisible);
+
+        // See if we should show archive or unarchive.
+        final boolean isArchived = data.getIsArchived();
+        menu.findItem(R.id.action_archive).setVisible(!isArchived);
+        menu.findItem(R.id.action_unarchive).setVisible(isArchived);
+
+        // Conditionally enable the phone call button.
+        final boolean supportCallAction = (PhoneUtils.getDefault().isVoiceCapable() &&
+                data.getParticipantPhoneNumber() != null);
+        menu.findItem(R.id.action_call).setVisible(supportCallAction);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_people_and_options:
+                Assert.isTrue(mBinding.getData().getParticipantsLoaded());
+                UIIntents.get().launchPeopleAndOptionsActivity(getActivity(), mConversationId);
+                return true;
+
+            case R.id.action_call:
+                final String phoneNumber = mBinding.getData().getParticipantPhoneNumber();
+                Assert.notNull(phoneNumber);
+                // Can't make a call to emergency numbers using ACTION_CALL.
+                if (PhoneNumberUtils.isEmergencyNumber(phoneNumber)) {
+                    UiUtils.showToast(R.string.disallow_emergency_call);
+                } else {
+                    final View targetView = getActivity().findViewById(R.id.action_call);
+                    Point centerPoint;
+                    if (targetView != null) {
+                        final int screenLocation[] = new int[2];
+                        targetView.getLocationOnScreen(screenLocation);
+                        final int centerX = screenLocation[0] + targetView.getWidth() / 2;
+                        final int centerY = screenLocation[1] + targetView.getHeight() / 2;
+                        centerPoint = new Point(centerX, centerY);
+                    } else {
+                        // In the overflow menu, just use the center of the screen.
+                        final Display display =
+                                getActivity().getWindowManager().getDefaultDisplay();
+                        centerPoint = new Point(display.getWidth() / 2, display.getHeight() / 2);
+                    }
+                    UIIntents.get()
+                            .launchPhoneCallActivity(getActivity(), phoneNumber, centerPoint);
+                }
+                return true;
+
+            case R.id.action_archive:
+                mBinding.getData().archiveConversation(mBinding);
+                closeConversation(mConversationId);
+                return true;
+
+            case R.id.action_unarchive:
+                mBinding.getData().unarchiveConversation(mBinding);
+                return true;
+
+            case R.id.action_settings:
+                return true;
+
+            case R.id.action_add_contact:
+                final ParticipantData participant = mBinding.getData().getOtherParticipant();
+                Assert.notNull(participant);
+                final String destination = participant.getNormalizedDestination();
+                final Uri avatarUri = AvatarUriUtil.createAvatarUri(participant);
+                (new AddContactsConfirmationDialog(getActivity(), avatarUri, destination)).show();
+                return true;
+
+            case R.id.action_delete:
+                if (isReadyForAction()) {
+                    new AlertDialog.Builder(getActivity())
+                            .setTitle(getResources().getQuantityString(
+                                    R.plurals.delete_conversations_confirmation_dialog_title, 1))
+                            .setPositiveButton(R.string.delete_conversation_confirmation_button,
+                                    new DialogInterface.OnClickListener() {
+                                        @Override
+                                        public void onClick(final DialogInterface dialog,
+                                                final int button) {
+                                            deleteConversation();
+                                        }
+                            })
+                            .setNegativeButton(R.string.delete_conversation_decline_button, null)
+                            .show();
+                } else {
+                    warnOfMissingActionConditions(false /*sending*/,
+                            null /*commandToRunAfterActionConditionResolved*/);
+                }
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * {@inheritDoc} from ConversationDataListener
+     */
+    @Override
+    public void onConversationMessagesCursorUpdated(final ConversationData data,
+            final Cursor cursor, final ConversationMessageData newestMessage,
+            final boolean isSync) {
+        mBinding.ensureBound(data);
+
+        // This needs to be determined before swapping cursor, which may change the scroll state.
+        final boolean scrolledToBottom = isScrolledToBottom();
+        final int positionFromBottom = getScrollPositionFromBottom();
+
+        // If participants not loaded, assume 1:1 since that's the 99% case
+        final boolean oneOnOne =
+                !data.getParticipantsLoaded() || data.getOtherParticipant() != null;
+        mAdapter.setOneOnOne(oneOnOne, false /* invalidate */);
+
+        // Ensure that the action bar is updated with the current data.
+        invalidateOptionsMenu();
+        final Cursor oldCursor = mAdapter.swapCursor(cursor);
+
+        if (cursor != null && oldCursor == null) {
+            if (mListState != null) {
+                mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
+                // RecyclerView restores scroll states without triggering scroll change events, so
+                // we need to manually ensure that they are correctly handled.
+                mListScrollListener.onScrolled(mRecyclerView, 0, 0);
+            }
+        }
+
+        if (isSync) {
+            // This is a message sync. Syncing messages changes cursor item count, which would
+            // implicitly change RV's scroll position. We'd like the RV to keep scrolled to the same
+            // relative position from the bottom (because RV is stacked from bottom), so that it
+            // stays relatively put as we sync.
+            final int position = Math.max(mAdapter.getItemCount() - 1 - positionFromBottom, 0);
+            scrollToPosition(position, false /* smoothScroll */);
+        } else if (newestMessage != null) {
+            // Show a snack bar notification if we are not scrolled to the bottom and the new
+            // message is an incoming message.
+            if (!scrolledToBottom && newestMessage.getIsIncoming()) {
+                // If the conversation activity is started but not resumed (if another dialog
+                // activity was in the foregrond), we will show a system notification instead of
+                // the snack bar.
+                if (mBinding.getData().isFocused()) {
+                    UiUtils.showSnackBarWithCustomAction(getActivity(),
+                            getView().getRootView(),
+                            getString(R.string.in_conversation_notify_new_message_text),
+                            SnackBar.Action.createCustomAction(new Runnable() {
+                                @Override
+                                public void run() {
+                                    scrollToBottom(true /* smoothScroll */);
+                                    mComposeMessageView.hideAllComposeInputs(false /* animate */);
+                                }
+                            },
+                            getString(R.string.in_conversation_notify_new_message_action)),
+                            null /* interactions */,
+                            SnackBar.Placement.above(mComposeMessageView));
+                }
+            } else {
+                // We are either already scrolled to the bottom or this is an outgoing message,
+                // scroll to the bottom to reveal it.
+                // Don't smooth scroll if we were already at the bottom; instead, we scroll
+                // immediately so RecyclerView's view animation will take place.
+                scrollToBottom(!scrolledToBottom);
+            }
+        }
+
+        if (cursor != null) {
+            mHost.onConversationMessagesUpdated(cursor.getCount());
+
+            // Are we coming from a widget click where we're told to scroll to a particular item?
+            final int scrollToPos = getScrollToMessagePosition();
+            if (scrollToPos >= 0) {
+                if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(LogUtil.BUGLE_TAG, "onConversationMessagesCursorUpdated " +
+                            " scrollToPos: " + scrollToPos +
+                            " cursorCount: " + cursor.getCount());
+                }
+                scrollToPosition(scrollToPos, true /*smoothScroll*/);
+                clearScrollToMessagePosition();
+            }
+        }
+
+        mHost.invalidateActionBar();
+    }
+
+    /**
+     * {@inheritDoc} from ConversationDataListener
+     */
+    @Override
+    public void onConversationMetadataUpdated(final ConversationData conversationData) {
+        mBinding.ensureBound(conversationData);
+
+        if (mSelectedMessage != null && mSelectedAttachment != null) {
+            // We may have just sent a message and the temp attachment we selected is now gone.
+            // and it was replaced with some new attachment.  Since we don't know which one it
+            // is we shouldn't reselect it (unless there is just one) In the multi-attachment
+            // case we would just deselect the message and allow the user to reselect, otherwise we
+            // may act on old temp data and may crash.
+            final List<MessagePartData> currentAttachments = mSelectedMessage.getData().getAttachments();
+            if (currentAttachments.size() == 1) {
+                mSelectedAttachment = currentAttachments.get(0);
+            } else if (!currentAttachments.contains(mSelectedAttachment)) {
+                selectMessage(null);
+            }
+        }
+        // Ensure that the action bar is updated with the current data.
+        invalidateOptionsMenu();
+        mHost.onConversationMetadataUpdated();
+        mAdapter.notifyDataSetChanged();
+    }
+
+    public void setConversationInfo(final Context context, final String conversationId,
+            final MessageData draftData) {
+        // TODO: Eventually I would like the Factory to implement
+        // Factory.get().bindConversationData(mBinding, getActivity(), this, conversationId));
+        if (!mBinding.isBound()) {
+            mConversationId = conversationId;
+            mIncomingDraft = draftData;
+            mBinding.bind(DataModel.get().createConversationData(context, this, conversationId));
+        } else {
+            Assert.isTrue(TextUtils.equals(mBinding.getData().getConversationId(), conversationId));
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        // Unbind all the views that we bound to data
+        if (mComposeMessageView != null) {
+            mComposeMessageView.unbind();
+        }
+
+        // And unbind this fragment from its data
+        mBinding.unbind();
+        mConversationId = null;
+    }
+
+    void suppressWriteDraft() {
+        mSuppressWriteDraft = true;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mComposeMessageView != null && !mSuppressWriteDraft) {
+            mComposeMessageView.writeDraftMessage();
+        }
+        mSuppressWriteDraft = false;
+        mBinding.getData().unsetFocus();
+        mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
+
+        LocalBroadcastManager.getInstance(getActivity())
+                .unregisterReceiver(mConversationSelfIdChangeReceiver);
+    }
+
+    @Override
+    public void onConfigurationChanged(final Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mRecyclerView.getItemAnimator().endAnimations();
+    }
+
+    // TODO: Remove isBound and replace it with ensureBound after b/15704674.
+    public boolean isBound() {
+        return mBinding.isBound();
+    }
+
+    private FragmentManager getFragmentManagerToUse() {
+        return OsUtil.isAtLeastJB_MR1() ? getChildFragmentManager() : getFragmentManager();
+    }
+
+    public MediaPicker getMediaPicker() {
+        return (MediaPicker) getFragmentManagerToUse().findFragmentByTag(
+                MediaPicker.FRAGMENT_TAG);
+    }
+
+    @Override
+    public void sendMessage(final MessageData message) {
+        if (isReadyForAction()) {
+            if (ensureKnownRecipients()) {
+                // Merge the caption text from attachments into the text body of the messages
+                message.consolidateText();
+
+                mBinding.getData().sendMessage(mBinding, message);
+                mComposeMessageView.resetMediaPickerState();
+            } else {
+                LogUtil.w(LogUtil.BUGLE_TAG, "Message can't be sent: conv participants not loaded");
+            }
+        } else {
+            warnOfMissingActionConditions(true /*sending*/,
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            sendMessage(message);
+                        }
+            });
+        }
+    }
+
+    public void setHost(final ConversationFragmentHost host) {
+        mHost = host;
+    }
+
+    public String getConversationName() {
+        return mBinding.getData().getConversationName();
+    }
+
+    @Override
+    public void onComposeEditTextFocused() {
+        mHost.onStartComposeMessage();
+    }
+
+    @Override
+    public void onAttachmentsCleared() {
+        // When attachments are removed, reset transient media picker state such as image selection.
+        mComposeMessageView.resetMediaPickerState();
+    }
+
+    /**
+     * Called to check if all conditions are nominal and a "go" for some action, such as deleting
+     * a message, that requires this app to be the default app. This is also a precondition
+     * required for sending a draft.
+     * @return true if all conditions are nominal and we're ready to send a message
+     */
+    @Override
+    public boolean isReadyForAction() {
+        return UiUtils.isReadyForAction();
+    }
+
+    /**
+     * When there's some condition that prevents an operation, such as sending a message,
+     * call warnOfMissingActionConditions to put up a snackbar and allow the user to repair
+     * that condition.
+     * @param sending - true if we're called during a sending operation
+     * @param commandToRunAfterActionConditionResolved - a runnable to run after the user responds
+     *                  positively to the condition prompt and resolves the condition. If null,
+     *                  the user will be shown a toast to tap the send button again.
+     */
+    @Override
+    public void warnOfMissingActionConditions(final boolean sending,
+            final Runnable commandToRunAfterActionConditionResolved) {
+        if (mChangeDefaultSmsAppHelper == null) {
+            mChangeDefaultSmsAppHelper = new ChangeDefaultSmsAppHelper();
+        }
+        mChangeDefaultSmsAppHelper.warnOfMissingActionConditions(sending,
+                commandToRunAfterActionConditionResolved, mComposeMessageView,
+                getView().getRootView(),
+                getActivity(), this);
+    }
+
+    private boolean ensureKnownRecipients() {
+        final ConversationData conversationData = mBinding.getData();
+
+        if (!conversationData.getParticipantsLoaded()) {
+            // We can't tell yet whether or not we have an unknown recipient
+            return false;
+        }
+
+        final ConversationParticipantsData participants = conversationData.getParticipants();
+        for (final ParticipantData participant : participants) {
+
+
+            if (participant.isUnknownSender()) {
+                UiUtils.showToast(R.string.unknown_sender);
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public void retryDownload(final String messageId) {
+        if (isReadyForAction()) {
+            mBinding.getData().downloadMessage(mBinding, messageId);
+        } else {
+            warnOfMissingActionConditions(false /*sending*/,
+                    null /*commandToRunAfterActionConditionResolved*/);
+        }
+    }
+
+    public void retrySend(final String messageId) {
+        if (isReadyForAction()) {
+            if (ensureKnownRecipients()) {
+                mBinding.getData().resendMessage(mBinding, messageId);
+            }
+        } else {
+            warnOfMissingActionConditions(true /*sending*/,
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            retrySend(messageId);
+                        }
+
+                    });
+        }
+    }
+
+    void deleteMessage(final String messageId) {
+        if (isReadyForAction()) {
+            final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+                    .setTitle(R.string.delete_message_confirmation_dialog_title)
+                    .setMessage(R.string.delete_message_confirmation_dialog_text)
+                    .setPositiveButton(R.string.delete_message_confirmation_button,
+                            new OnClickListener() {
+                        @Override
+                        public void onClick(final DialogInterface dialog, final int which) {
+                            mBinding.getData().deleteMessage(mBinding, messageId);
+                        }
+                    })
+                    .setNegativeButton(android.R.string.cancel, null);
+            if (OsUtil.isAtLeastJB_MR1()) {
+                builder.setOnDismissListener(new OnDismissListener() {
+                    @Override
+                    public void onDismiss(final DialogInterface dialog) {
+                        mHost.dismissActionMode();
+                    }
+                });
+            } else {
+                builder.setOnCancelListener(new OnCancelListener() {
+                    @Override
+                    public void onCancel(final DialogInterface dialog) {
+                        mHost.dismissActionMode();
+                    }
+                });
+            }
+            builder.create().show();
+        } else {
+            warnOfMissingActionConditions(false /*sending*/,
+                    null /*commandToRunAfterActionConditionResolved*/);
+            mHost.dismissActionMode();
+        }
+    }
+
+    public void deleteConversation() {
+        if (isReadyForAction()) {
+            final Context context = getActivity();
+            mBinding.getData().deleteConversation(mBinding);
+            closeConversation(mConversationId);
+        } else {
+            warnOfMissingActionConditions(false /*sending*/,
+                    null /*commandToRunAfterActionConditionResolved*/);
+        }
+    }
+
+    @Override
+    public void closeConversation(final String conversationId) {
+        if (TextUtils.equals(conversationId, mConversationId)) {
+            mHost.onFinishCurrentConversation();
+            // TODO: Explicitly transition to ConversationList (or just go back)?
+        }
+    }
+
+    @Override
+    public void onConversationParticipantDataLoaded(final ConversationData data) {
+        mBinding.ensureBound(data);
+        if (mBinding.getData().getParticipantsLoaded()) {
+            final boolean oneOnOne = mBinding.getData().getOtherParticipant() != null;
+            mAdapter.setOneOnOne(oneOnOne, true /* invalidate */);
+
+            // refresh the options menu which will enable the "people & options" item.
+            invalidateOptionsMenu();
+
+            mHost.invalidateActionBar();
+
+            mRecyclerView.setVisibility(View.VISIBLE);
+            mHost.onConversationParticipantDataLoaded
+                (mBinding.getData().getNumberOfParticipantsExcludingSelf());
+        }
+    }
+
+    @Override
+    public void onSubscriptionListDataLoaded(final ConversationData data) {
+        mBinding.ensureBound(data);
+        mAdapter.notifyDataSetChanged();
+    }
+
+    @Override
+    public void promptForSelfPhoneNumber() {
+        if (mComposeMessageView != null) {
+            // Avoid bug in system which puts soft keyboard over dialog after orientation change
+            ImeUtil.hideSoftInput(getActivity(), mComposeMessageView);
+        }
+
+        final FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
+        final EnterSelfPhoneNumberDialog dialog = EnterSelfPhoneNumberDialog
+                .newInstance(getConversationSelfSubId());
+        dialog.setTargetFragment(this, 0/*requestCode*/);
+        dialog.show(ft, null/*tag*/);
+    }
+
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        if (mChangeDefaultSmsAppHelper == null) {
+            mChangeDefaultSmsAppHelper = new ChangeDefaultSmsAppHelper();
+        }
+        mChangeDefaultSmsAppHelper.handleChangeDefaultSmsResult(requestCode, resultCode, null);
+    }
+
+    public boolean hasMessages() {
+        return mAdapter != null && mAdapter.getItemCount() > 0;
+    }
+
+    public boolean onBackPressed() {
+        if (mComposeMessageView.onBackPressed()) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean onNavigationUpPressed() {
+        return mComposeMessageView.onNavigationUpPressed();
+    }
+
+    @Override
+    public boolean onAttachmentClick(final ConversationMessageView messageView,
+            final MessagePartData attachment, final Rect imageBounds, final boolean longPress) {
+        if (longPress) {
+            selectMessage(messageView, attachment);
+            return true;
+        } else if (messageView.getData().getOneClickResendMessage()) {
+            handleMessageClick(messageView);
+            return true;
+        }
+
+        if (attachment.isImage()) {
+            displayPhoto(attachment.getContentUri(), imageBounds, false /* isDraft */);
+        }
+
+        if (attachment.isVCard()) {
+            UIIntents.get().launchVCardDetailActivity(getActivity(), attachment.getContentUri());
+        }
+
+        return false;
+    }
+
+    private void handleMessageClick(final ConversationMessageView messageView) {
+        if (messageView != mSelectedMessage) {
+            final ConversationMessageData data = messageView.getData();
+            final boolean isReadyToSend = isReadyForAction();
+            if (data.getOneClickResendMessage()) {
+                // Directly resend the message on tap if it's failed
+                retrySend(data.getMessageId());
+                selectMessage(null);
+            } else if (data.getShowResendMessage() && isReadyToSend) {
+                // Select the message to show the resend/download/delete options
+                selectMessage(messageView);
+            } else if (data.getShowDownloadMessage() && isReadyToSend) {
+                // Directly download the message on tap
+                retryDownload(data.getMessageId());
+            } else {
+                // Let the toast from warnOfMissingActionConditions show and skip
+                // selecting
+                warnOfMissingActionConditions(false /*sending*/,
+                        null /*commandToRunAfterActionConditionResolved*/);
+                selectMessage(null);
+            }
+        } else {
+            selectMessage(null);
+        }
+    }
+
+    private static class AttachmentToSave {
+        public final Uri uri;
+        public final String contentType;
+        public Uri persistedUri;
+
+        AttachmentToSave(final Uri uri, final String contentType) {
+            this.uri = uri;
+            this.contentType = contentType;
+        }
+    }
+
+    public static class SaveAttachmentTask extends SafeAsyncTask<Void, Void, Void> {
+        private final Context mContext;
+        private final List<AttachmentToSave> mAttachmentsToSave = new ArrayList<>();
+
+        public SaveAttachmentTask(final Context context, final Uri contentUri,
+                final String contentType) {
+            mContext = context;
+            addAttachmentToSave(contentUri, contentType);
+        }
+
+        public SaveAttachmentTask(final Context context) {
+            mContext = context;
+        }
+
+        public void addAttachmentToSave(final Uri contentUri, final String contentType) {
+            mAttachmentsToSave.add(new AttachmentToSave(contentUri, contentType));
+        }
+
+        public int getAttachmentCount() {
+            return mAttachmentsToSave.size();
+        }
+
+        @Override
+        protected Void doInBackgroundTimed(final Void... arg) {
+            final File appDir = new File(Environment.getExternalStoragePublicDirectory(
+                    Environment.DIRECTORY_PICTURES),
+                    mContext.getResources().getString(R.string.app_name));
+            final File downloadDir = Environment.getExternalStoragePublicDirectory(
+                    Environment.DIRECTORY_DOWNLOADS);
+            for (final AttachmentToSave attachment : mAttachmentsToSave) {
+                final boolean isImageOrVideo = ContentType.isImageType(attachment.contentType)
+                        || ContentType.isVideoType(attachment.contentType);
+                attachment.persistedUri = UriUtil.persistContent(attachment.uri,
+                        isImageOrVideo ? appDir : downloadDir, attachment.contentType);
+           }
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(final Void result) {
+            int failCount = 0;
+            int imageCount = 0;
+            int videoCount = 0;
+            int otherCount = 0;
+            for (final AttachmentToSave attachment : mAttachmentsToSave) {
+                if (attachment.persistedUri == null) {
+                   failCount++;
+                   continue;
+                }
+
+                // Inform MediaScanner about the new file
+                final Intent scanFileIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+                scanFileIntent.setData(attachment.persistedUri);
+                mContext.sendBroadcast(scanFileIntent);
+
+                if (ContentType.isImageType(attachment.contentType)) {
+                    imageCount++;
+                } else if (ContentType.isVideoType(attachment.contentType)) {
+                    videoCount++;
+                } else {
+                    otherCount++;
+                    // Inform DownloadManager of the file so it will show in the "downloads" app
+                    final DownloadManager downloadManager =
+                            (DownloadManager) mContext.getSystemService(
+                                    Context.DOWNLOAD_SERVICE);
+                    final String filePath = attachment.persistedUri.getPath();
+                    final File file = new File(filePath);
+
+                    if (file.exists()) {
+                        downloadManager.addCompletedDownload(
+                                file.getName() /* title */,
+                                mContext.getString(
+                                        R.string.attachment_file_description) /* description */,
+                                        true /* isMediaScannerScannable */,
+                                        attachment.contentType,
+                                        file.getAbsolutePath(),
+                                        file.length(),
+                                        false /* showNotification */);
+                    }
+                }
+            }
+
+            String message;
+            if (failCount > 0) {
+                message = mContext.getResources().getQuantityString(
+                        R.plurals.attachment_save_error, failCount, failCount);
+            } else {
+                int messageId = R.plurals.attachments_saved;
+                if (otherCount > 0) {
+                    if (imageCount + videoCount == 0) {
+                        messageId = R.plurals.attachments_saved_to_downloads;
+                    }
+                } else {
+                    if (videoCount == 0) {
+                        messageId = R.plurals.photos_saved_to_album;
+                    } else if (imageCount == 0) {
+                        messageId = R.plurals.videos_saved_to_album;
+                    } else {
+                        messageId = R.plurals.attachments_saved_to_album;
+                    }
+                }
+                final String appName = mContext.getResources().getString(R.string.app_name);
+                final int count = imageCount + videoCount + otherCount;
+                message = mContext.getResources().getQuantityString(
+                        messageId, count, count, appName);
+            }
+            UiUtils.showToastAtBottom(message);
+        }
+    }
+
+    private void invalidateOptionsMenu() {
+        final Activity activity = getActivity();
+        // TODO: Add the supportInvalidateOptionsMenu call to the host activity.
+        if (activity == null || !(activity instanceof BugleActionBarActivity)) {
+            return;
+        }
+        ((BugleActionBarActivity) activity).supportInvalidateOptionsMenu();
+    }
+
+    @Override
+    public void setOptionsMenuVisibility(final boolean visible) {
+        setHasOptionsMenu(visible);
+    }
+
+    @Override
+    public int getConversationSelfSubId() {
+        final String selfParticipantId = mComposeMessageView.getConversationSelfId();
+        final ParticipantData self = mBinding.getData().getSelfParticipantById(selfParticipantId);
+        // If the self id or the self participant data hasn't been loaded yet, fallback to
+        // the default setting.
+        return self == null ? ParticipantData.DEFAULT_SELF_SUB_ID : self.getSubId();
+    }
+
+    @Override
+    public void invalidateActionBar() {
+        mHost.invalidateActionBar();
+    }
+
+    @Override
+    public void dismissActionMode() {
+        mHost.dismissActionMode();
+    }
+
+    @Override
+    public void selectSim(final SubscriptionListEntry subscriptionData) {
+        mComposeMessageView.selectSim(subscriptionData);
+        mHost.onStartComposeMessage();
+    }
+
+    @Override
+    public void onStartComposeMessage() {
+        mHost.onStartComposeMessage();
+    }
+
+    @Override
+    public SubscriptionListEntry getSubscriptionEntryForSelfParticipant(
+            final String selfParticipantId, final boolean excludeDefault) {
+        // TODO: ConversationMessageView is the only one using this. We should probably
+        // inject this into the view during binding in the ConversationMessageAdapter.
+        return mBinding.getData().getSubscriptionEntryForSelfParticipant(selfParticipantId,
+                excludeDefault);
+    }
+
+    @Override
+    public SimSelectorView getSimSelectorView() {
+        return (SimSelectorView) getView().findViewById(R.id.sim_selector);
+    }
+
+    @Override
+    public MediaPicker createMediaPicker() {
+        return new MediaPicker(getActivity());
+    }
+
+    @Override
+    public void notifyOfAttachmentLoadFailed() {
+        UiUtils.showToastAtBottom(R.string.attachment_load_failed_dialog_message);
+    }
+
+    @Override
+    public void warnOfExceedingMessageLimit(final boolean sending, final boolean tooManyVideos) {
+        warnOfExceedingMessageLimit(sending, mComposeMessageView, mConversationId,
+                getActivity(), tooManyVideos);
+    }
+
+    public static void warnOfExceedingMessageLimit(final boolean sending,
+            final ComposeMessageView composeMessageView, final String conversationId,
+            final Activity activity, final boolean tooManyVideos) {
+        final AlertDialog.Builder builder =
+                new AlertDialog.Builder(activity)
+                    .setTitle(R.string.mms_attachment_limit_reached);
+
+        if (sending) {
+            if (tooManyVideos) {
+                builder.setMessage(R.string.video_attachment_limit_exceeded_when_sending);
+            } else {
+                builder.setMessage(R.string.attachment_limit_reached_dialog_message_when_sending)
+                        .setNegativeButton(R.string.attachment_limit_reached_send_anyway,
+                                new OnClickListener() {
+                                    @Override
+                                    public void onClick(final DialogInterface dialog,
+                                            final int which) {
+                                        composeMessageView.sendMessageIgnoreMessageSizeLimit();
+                                    }
+                                });
+            }
+            builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
+                @Override
+                public void onClick(final DialogInterface dialog, final int which) {
+                    showAttachmentChooser(conversationId, activity);
+                }});
+        } else {
+            builder.setMessage(R.string.attachment_limit_reached_dialog_message_when_composing)
+                    .setPositiveButton(android.R.string.ok, null);
+        }
+        builder.show();
+    }
+
+    @Override
+    public void showAttachmentChooser() {
+        showAttachmentChooser(mConversationId, getActivity());
+    }
+
+    public static void showAttachmentChooser(final String conversationId,
+            final Activity activity) {
+        UIIntents.get().launchAttachmentChooserActivity(activity,
+                conversationId, REQUEST_CHOOSE_ATTACHMENTS);
+    }
+
+    private void updateActionAndStatusBarColor(final ActionBar actionBar) {
+        final int themeColor = ConversationDrawables.get().getConversationThemeColor();
+        actionBar.setBackgroundDrawable(new ColorDrawable(themeColor));
+        UiUtils.setStatusBarColor(getActivity(), themeColor);
+    }
+
+    public void updateActionBar(final ActionBar actionBar) {
+        if (mComposeMessageView == null || !mComposeMessageView.updateActionBar(actionBar)) {
+            updateActionAndStatusBarColor(actionBar);
+            // We update this regardless of whether or not the action bar is showing so that we
+            // don't get a race when it reappears.
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            // Reset the back arrow to its default
+            actionBar.setHomeAsUpIndicator(0);
+            View customView = actionBar.getCustomView();
+            if (customView == null || customView.getId() != R.id.conversation_title_container) {
+                final LayoutInflater inflator = (LayoutInflater)
+                        getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                customView = inflator.inflate(R.layout.action_bar_conversation_name, null);
+                customView.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(final View v) {
+                        onBackPressed();
+                    }
+                });
+                actionBar.setCustomView(customView);
+            }
+
+            final TextView conversationNameView =
+                    (TextView) customView.findViewById(R.id.conversation_title);
+            final String conversationName = getConversationName();
+            if (!TextUtils.isEmpty(conversationName)) {
+                // RTL : To format conversation title if it happens to be phone numbers.
+                final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+                final String formattedName = bidiFormatter.unicodeWrap(
+                        UiUtils.commaEllipsize(
+                                conversationName,
+                                conversationNameView.getPaint(),
+                                conversationNameView.getWidth(),
+                                getString(R.string.plus_one),
+                                getString(R.string.plus_n)).toString(),
+                        TextDirectionHeuristicsCompat.LTR);
+                conversationNameView.setText(formattedName);
+                // In case phone numbers are mixed in the conversation name, we need to vocalize it.
+                final String vocalizedConversationName =
+                        AccessibilityUtil.getVocalizedPhoneNumber(getResources(), conversationName);
+                conversationNameView.setContentDescription(vocalizedConversationName);
+                getActivity().setTitle(conversationName);
+            } else {
+                final String appName = getString(R.string.app_name);
+                conversationNameView.setText(appName);
+                getActivity().setTitle(appName);
+            }
+
+            // When conversation is showing and media picker is not showing, then hide the action
+            // bar only when we are in landscape mode, with IME open.
+            if (mHost.isImeOpen() && UiUtils.isLandscapeMode()) {
+                actionBar.hide();
+            } else {
+                actionBar.show();
+            }
+        }
+    }
+
+    @Override
+    public boolean shouldShowSubjectEditor() {
+        return true;
+    }
+
+    @Override
+    public boolean shouldHideAttachmentsWhenSimSelectorShown() {
+        return false;
+    }
+
+    @Override
+    public void showHideSimSelector(final boolean show) {
+        // no-op for now
+    }
+
+    @Override
+    public int getSimSelectorItemLayoutId() {
+        return R.layout.sim_selector_item_view;
+    }
+
+    @Override
+    public Uri getSelfSendButtonIconUri() {
+        return null;    // use default button icon uri
+    }
+
+    @Override
+    public int overrideCounterColor() {
+        return -1;      // don't override the color
+    }
+
+    @Override
+    public void onAttachmentsChanged(final boolean haveAttachments) {
+        // no-op for now
+    }
+
+    @Override
+    public void onDraftChanged(final DraftMessageData data, final int changeFlags) {
+        mDraftMessageDataModel.ensureBound(data);
+        // We're specifically only interested in ATTACHMENTS_CHANGED from the widget. Ignore
+        // other changes. When the widget changes an attachment, we need to reload the draft.
+        if (changeFlags ==
+                (DraftMessageData.WIDGET_CHANGED | DraftMessageData.ATTACHMENTS_CHANGED)) {
+            mClearLocalDraft = true;        // force a reload of the draft in onResume
+        }
+    }
+
+    @Override
+    public void onDraftAttachmentLimitReached(final DraftMessageData data) {
+        // no-op for now
+    }
+
+    @Override
+    public void onDraftAttachmentLoadFailed() {
+        // no-op for now
+    }
+
+    @Override
+    public int getAttachmentsClearedFlags() {
+        return DraftMessageData.ATTACHMENTS_CHANGED;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationInput.java b/src/com/android/messaging/ui/conversation/ConversationInput.java
new file mode 100644
index 0000000..cf98dbe
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationInput.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+
+/**
+ * The base class for a method of user input, e.g. media picker.
+ */
+public abstract class ConversationInput {
+    /**
+     * The host component where all input components are contained. This is typically the
+     * conversation fragment but may be mocked in test code.
+     */
+    public interface ConversationInputBase {
+        boolean showHideInternal(final ConversationInput target, final boolean show,
+                final boolean animate);
+        String getInputStateKey(final ConversationInput input);
+        void beginUpdate();
+        void handleOnShow(final ConversationInput target);
+        void endUpdate();
+    }
+
+    protected boolean mShowing;
+    protected ConversationInputBase mConversationInputBase;
+
+    public abstract boolean show(boolean animate);
+    public abstract boolean hide(boolean animate);
+
+    public ConversationInput(ConversationInputBase baseHost, final boolean isShowing) {
+        mConversationInputBase = baseHost;
+        mShowing = isShowing;
+    }
+
+    public boolean onBackPressed() {
+        if (mShowing) {
+            mConversationInputBase.showHideInternal(this, false /* show */, true /* animate */);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean onNavigationUpPressed() {
+        return false;
+    }
+
+    /**
+     * Toggle the visibility of this view.
+     * @param animate
+     * @return true if the view is now shown, false if it now hidden
+     */
+    public boolean toggle(final boolean animate) {
+        mConversationInputBase.showHideInternal(this, !mShowing /* show */, true /* animate */);
+        return mShowing;
+    }
+
+    public void saveState(final Bundle savedState) {
+        savedState.putBoolean(mConversationInputBase.getInputStateKey(this), mShowing);
+    }
+
+    public void restoreState(final Bundle savedState) {
+        // Things are hidden by default, so only handle show.
+        if (savedState.getBoolean(mConversationInputBase.getInputStateKey(this))) {
+            mConversationInputBase.showHideInternal(this, true /* show */, false /* animate */);
+        }
+    }
+
+    public boolean updateActionBar(final ActionBar actionBar) {
+        return false;
+    }
+
+    /**
+     * Update our visibility flag in response to visibility change, both for actions
+     * initiated by this class (through the show/hide methods), and for external changes
+     * tracked by event listeners (e.g. ImeStateObserver, MediaPickerListener). As part of
+     * handling an input showing, we will hide all other inputs to ensure they are mutually
+     * exclusive.
+     */
+    protected void onVisibilityChanged(final boolean visible) {
+        if (mShowing != visible) {
+            mConversationInputBase.beginUpdate();
+            mShowing = visible;
+            if (visible) {
+                mConversationInputBase.handleOnShow(this);
+            }
+            mConversationInputBase.endUpdate();
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationInputManager.java b/src/com/android/messaging/ui/conversation/ConversationInputManager.java
new file mode 100644
index 0000000..3d42d78
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationInputManager.java
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.widget.EditText;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationData.SimpleConversationDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.ui.mediapicker.MediaPicker;
+import com.android.messaging.ui.mediapicker.MediaPicker.MediaPickerListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.ImeUtil.ImeStateHost;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.Collection;
+
+/**
+ * Manages showing/hiding/persisting different mutually exclusive UI components nested in
+ * ConversationFragment that take user inputs, i.e. media picker, SIM selector and
+ * IME keyboard (the IME keyboard is not owned by Bugle, but we try to model it the same way
+ * as the other components).
+ */
+public class ConversationInputManager implements ConversationInput.ConversationInputBase {
+    /**
+     * The host component where all input components are contained. This is typically the
+     * conversation fragment but may be mocked in test code.
+     */
+    public interface ConversationInputHost extends DraftMessageSubscriptionDataProvider {
+        void invalidateActionBar();
+        void setOptionsMenuVisibility(boolean visible);
+        void dismissActionMode();
+        void selectSim(SubscriptionListEntry subscriptionData);
+        void onStartComposeMessage();
+        SimSelectorView getSimSelectorView();
+        MediaPicker createMediaPicker();
+        void showHideSimSelector(boolean show);
+        int getSimSelectorItemLayoutId();
+    }
+
+    /**
+     * The "sink" component where all inputs components will direct the user inputs to. This is
+     * typically the ComposeMessageView but may be mocked in test code.
+     */
+    public interface ConversationInputSink {
+        void onMediaItemsSelected(Collection<MessagePartData> items);
+        void onMediaItemsUnselected(MessagePartData item);
+        void onPendingAttachmentAdded(PendingAttachmentData pendingItem);
+        void resumeComposeMessage();
+        EditText getComposeEditText();
+        void setAccessibility(boolean enabled);
+    }
+
+    private final ConversationInputHost mHost;
+    private final ConversationInputSink mSink;
+
+    /** Dependencies injected from the host during construction */
+    private final FragmentManager mFragmentManager;
+    private final Context mContext;
+    private final ImeStateHost mImeStateHost;
+    private final ImmutableBindingRef<ConversationData> mConversationDataModel;
+    private final ImmutableBindingRef<DraftMessageData> mDraftDataModel;
+
+    private final ConversationInput[] mInputs;
+    private final ConversationMediaPicker mMediaInput;
+    private final ConversationSimSelector mSimInput;
+    private final ConversationImeKeyboard mImeInput;
+    private int mUpdateCount;
+
+    private final ImeUtil.ImeStateObserver mImeStateObserver = new ImeUtil.ImeStateObserver() {
+        @Override
+        public void onImeStateChanged(final boolean imeOpen) {
+            mImeInput.onVisibilityChanged(imeOpen);
+        }
+    };
+
+    private final ConversationDataListener mDataListener = new SimpleConversationDataListener() {
+        @Override
+        public void onConversationParticipantDataLoaded(ConversationData data) {
+            mConversationDataModel.ensureBound(data);
+        }
+
+        @Override
+        public void onSubscriptionListDataLoaded(ConversationData data) {
+            mConversationDataModel.ensureBound(data);
+            mSimInput.onSubscriptionListDataLoaded(data.getSubscriptionListData());
+        }
+    };
+
+    public ConversationInputManager(
+            final Context context,
+            final ConversationInputHost host,
+            final ConversationInputSink sink,
+            final ImeStateHost imeStateHost,
+            final FragmentManager fm,
+            final BindingBase<ConversationData> conversationDataModel,
+            final BindingBase<DraftMessageData> draftDataModel,
+            final Bundle savedState) {
+        mHost = host;
+        mSink = sink;
+        mFragmentManager = fm;
+        mContext = context;
+        mImeStateHost = imeStateHost;
+        mConversationDataModel = BindingBase.createBindingReference(conversationDataModel);
+        mDraftDataModel = BindingBase.createBindingReference(draftDataModel);
+
+        // Register listeners on dependencies.
+        mImeStateHost.registerImeStateObserver(mImeStateObserver);
+        mConversationDataModel.getData().addConversationDataListener(mDataListener);
+
+        // Initialize the inputs
+        mMediaInput = new ConversationMediaPicker(this);
+        mSimInput = new SimSelector(this);
+        mImeInput = new ConversationImeKeyboard(this, mImeStateHost.isImeOpen());
+        mInputs = new ConversationInput[] { mMediaInput, mSimInput, mImeInput };
+
+        if (savedState != null) {
+            for (int i = 0; i < mInputs.length; i++) {
+                mInputs[i].restoreState(savedState);
+            }
+        }
+        updateHostOptionsMenu();
+    }
+
+    public void onDetach() {
+        mImeStateHost.unregisterImeStateObserver(mImeStateObserver);
+        // Don't need to explicitly unregister for data model events. It will unregister all
+        // listeners automagically on unbind.
+    }
+
+    public void onSaveInputState(final Bundle savedState) {
+        for (int i = 0; i < mInputs.length; i++) {
+            mInputs[i].saveState(savedState);
+        }
+    }
+
+    @Override
+    public String getInputStateKey(final ConversationInput input) {
+        return input.getClass().getCanonicalName() + "_savedstate_";
+    }
+
+    public boolean onBackPressed() {
+        for (int i = 0; i < mInputs.length; i++) {
+            if (mInputs[i].onBackPressed()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean onNavigationUpPressed() {
+        for (int i = 0; i < mInputs.length; i++) {
+            if (mInputs[i].onNavigationUpPressed()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void resetMediaPickerState() {
+        mMediaInput.resetViewHolderState();
+    }
+
+    public void showHideMediaPicker(final boolean show, final boolean animate) {
+        showHideInternal(mMediaInput, show, animate);
+    }
+
+    /**
+     * Show or hide the sim selector
+     * @param show visibility
+     * @param animate whether to animate the change in visibility
+     * @return true if the state of the visibility was changed
+     */
+    public boolean showHideSimSelector(final boolean show, final boolean animate) {
+        return showHideInternal(mSimInput, show, animate);
+    }
+
+    public void showHideImeKeyboard(final boolean show, final boolean animate) {
+        showHideInternal(mImeInput, show, animate);
+    }
+
+    public void hideAllInputs(final boolean animate) {
+        beginUpdate();
+        for (int i = 0; i < mInputs.length; i++) {
+            showHideInternal(mInputs[i], false, animate);
+        }
+        endUpdate();
+    }
+
+    /**
+     * Toggle the visibility of the sim selector.
+     * @param animate
+     * @param subEntry
+     * @return true if the view is now shown, false if it now hidden
+     */
+    public boolean toggleSimSelector(final boolean animate, final SubscriptionListEntry subEntry) {
+        mSimInput.setSelected(subEntry);
+        return mSimInput.toggle(animate);
+    }
+
+    public boolean updateActionBar(final ActionBar actionBar) {
+        for (int i = 0; i < mInputs.length; i++) {
+            if (mInputs[i].mShowing) {
+                return mInputs[i].updateActionBar(actionBar);
+            }
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    boolean isMediaPickerVisible() {
+        return mMediaInput.mShowing;
+    }
+
+    @VisibleForTesting
+    boolean isSimSelectorVisible() {
+        return mSimInput.mShowing;
+    }
+
+    @VisibleForTesting
+    boolean isImeKeyboardVisible() {
+        return mImeInput.mShowing;
+    }
+
+    @VisibleForTesting
+    void testNotifyImeStateChanged(final boolean imeOpen) {
+        mImeStateObserver.onImeStateChanged(imeOpen);
+    }
+
+    /**
+     * returns true if the state of the visibility was actually changed
+     */
+    @Override
+    public boolean showHideInternal(final ConversationInput target, final boolean show,
+            final boolean animate) {
+        if (!mConversationDataModel.isBound()) {
+            return false;
+        }
+
+        if (target.mShowing == show) {
+            return false;
+        }
+        beginUpdate();
+        boolean success;
+        if (!show) {
+            success = target.hide(animate);
+        } else {
+            success = target.show(animate);
+        }
+
+        if (success) {
+            target.onVisibilityChanged(show);
+        }
+        endUpdate();
+        return true;
+    }
+
+    @Override
+    public void handleOnShow(final ConversationInput target) {
+        if (!mConversationDataModel.isBound()) {
+            return;
+        }
+        beginUpdate();
+
+        // All inputs are mutually exclusive. Showing one will hide everything else.
+        // The one exception, is that the keyboard and location media chooser can be open at the
+        // time to enable searching within that chooser
+        for (int i = 0; i < mInputs.length; i++) {
+            final ConversationInput currInput = mInputs[i];
+            if (currInput != target) {
+                // TODO : If there's more exceptions we will want to make this more
+                // generic
+                if (currInput instanceof ConversationMediaPicker &&
+                        target instanceof ConversationImeKeyboard &&
+                        mMediaInput.getExistingOrCreateMediaPicker() != null &&
+                        mMediaInput.getExistingOrCreateMediaPicker().canShowIme()) {
+                    // Allow the keyboard and location mediaPicker to be open at the same time,
+                    // but ensure the media picker is full screen to allow enough room
+                    mMediaInput.getExistingOrCreateMediaPicker().setFullScreen(true);
+                    continue;
+                }
+                showHideInternal(currInput, false /* show */, false /* animate */);
+            }
+        }
+        // Always dismiss action mode on show.
+        mHost.dismissActionMode();
+        // Invoking any non-keyboard input UI is treated as starting message compose.
+        if (target != mImeInput) {
+            mHost.onStartComposeMessage();
+        }
+        endUpdate();
+    }
+
+    @Override
+    public void beginUpdate() {
+        mUpdateCount++;
+    }
+
+    @Override
+    public void endUpdate() {
+        Assert.isTrue(mUpdateCount > 0);
+        if (--mUpdateCount == 0) {
+            // Always try to update the host action bar after every update cycle.
+            mHost.invalidateActionBar();
+        }
+    }
+
+    private void updateHostOptionsMenu() {
+        mHost.setOptionsMenuVisibility(!mMediaInput.isOpen());
+    }
+
+    /**
+     * Manages showing/hiding the media picker in conversation.
+     */
+    private class ConversationMediaPicker extends ConversationInput {
+        public ConversationMediaPicker(ConversationInputBase baseHost) {
+            super(baseHost, false);
+        }
+
+        private MediaPicker mMediaPicker;
+
+        @Override
+        public boolean show(boolean animate) {
+            if (mMediaPicker == null) {
+                mMediaPicker = getExistingOrCreateMediaPicker();
+                setConversationThemeColor(ConversationDrawables.get().getConversationThemeColor());
+                mMediaPicker.setSubscriptionDataProvider(mHost);
+                mMediaPicker.setDraftMessageDataModel(mDraftDataModel);
+                mMediaPicker.setListener(new MediaPickerListener() {
+                    @Override
+                    public void onOpened() {
+                        handleStateChange();
+                    }
+
+                    @Override
+                    public void onFullScreenChanged(boolean fullScreen) {
+                        // When we're full screen, we want to disable accessibility on the
+                        // ComposeMessageView controls (attach button, message input, sim chooser)
+                        // that are hiding underneath the action bar.
+                        mSink.setAccessibility(!fullScreen /*enabled*/);
+                        handleStateChange();
+                    }
+
+                    @Override
+                    public void onDismissed() {
+                        // Re-enable accessibility on all controls now that the media picker is
+                        // going away.
+                        mSink.setAccessibility(true /*enabled*/);
+                        handleStateChange();
+                    }
+
+                    private void handleStateChange() {
+                        onVisibilityChanged(isOpen());
+                        mHost.invalidateActionBar();
+                        updateHostOptionsMenu();
+                    }
+
+                    @Override
+                    public void onItemsSelected(final Collection<MessagePartData> items,
+                            final boolean resumeCompose) {
+                        mSink.onMediaItemsSelected(items);
+                        mHost.invalidateActionBar();
+                        if (resumeCompose) {
+                            mSink.resumeComposeMessage();
+                        }
+                    }
+
+                    @Override
+                    public void onItemUnselected(final MessagePartData item) {
+                        mSink.onMediaItemsUnselected(item);
+                        mHost.invalidateActionBar();
+                    }
+
+                    @Override
+                    public void onConfirmItemSelection() {
+                        mSink.resumeComposeMessage();
+                    }
+
+                    @Override
+                    public void onPendingItemAdded(final PendingAttachmentData pendingItem) {
+                        mSink.onPendingAttachmentAdded(pendingItem);
+                    }
+
+                    @Override
+                    public void onChooserSelected(final int chooserIndex) {
+                        mHost.invalidateActionBar();
+                        mHost.dismissActionMode();
+                    }
+                });
+            }
+
+            mMediaPicker.open(MediaPicker.MEDIA_TYPE_DEFAULT, animate);
+
+            return isOpen();
+        }
+
+        @Override
+        public boolean hide(boolean animate) {
+            if (mMediaPicker != null) {
+                mMediaPicker.dismiss(animate);
+            }
+            return !isOpen();
+        }
+
+        public void resetViewHolderState() {
+            if (mMediaPicker != null) {
+                mMediaPicker.resetViewHolderState();
+            }
+        }
+
+        public void setConversationThemeColor(final int themeColor) {
+            if (mMediaPicker != null) {
+                mMediaPicker.setConversationThemeColor(themeColor);
+            }
+        }
+
+        private boolean isOpen() {
+            return (mMediaPicker != null && mMediaPicker.isOpen());
+        }
+
+        private MediaPicker getExistingOrCreateMediaPicker() {
+            if (mMediaPicker != null) {
+                return mMediaPicker;
+            }
+            MediaPicker mediaPicker = (MediaPicker)
+                    mFragmentManager.findFragmentByTag(MediaPicker.FRAGMENT_TAG);
+            if (mediaPicker == null) {
+                mediaPicker = mHost.createMediaPicker();
+                if (mediaPicker == null) {
+                    return null;    // this use of ComposeMessageView doesn't support media picking
+                }
+                mFragmentManager.beginTransaction().replace(
+                        R.id.mediapicker_container,
+                        mediaPicker,
+                        MediaPicker.FRAGMENT_TAG).commit();
+            }
+            return mediaPicker;
+        }
+
+        @Override
+        public boolean updateActionBar(ActionBar actionBar) {
+            if (isOpen()) {
+                mMediaPicker.updateActionBar(actionBar);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public boolean onNavigationUpPressed() {
+            if (isOpen() && mMediaPicker.isFullScreen()) {
+                return onBackPressed();
+            }
+            return super.onNavigationUpPressed();
+        }
+
+        public boolean onBackPressed() {
+            if (mMediaPicker != null && mMediaPicker.onBackPressed()) {
+                return true;
+            }
+            return super.onBackPressed();
+        }
+    }
+
+    /**
+     * Manages showing/hiding the SIM selector in conversation.
+     */
+    private class SimSelector extends ConversationSimSelector {
+        public SimSelector(ConversationInputBase baseHost) {
+            super(baseHost);
+        }
+
+        @Override
+        protected SimSelectorView getSimSelectorView() {
+            return mHost.getSimSelectorView();
+        }
+
+        @Override
+        public int getSimSelectorItemLayoutId() {
+            return mHost.getSimSelectorItemLayoutId();
+        }
+
+        @Override
+        protected void selectSim(SubscriptionListEntry item) {
+            mHost.selectSim(item);
+        }
+
+        @Override
+        public boolean show(boolean animate) {
+            final boolean result = super.show(animate);
+            mHost.showHideSimSelector(true /*show*/);
+            return result;
+        }
+
+        @Override
+        public boolean hide(boolean animate) {
+            final boolean result = super.hide(animate);
+            mHost.showHideSimSelector(false /*show*/);
+            return result;
+        }
+    }
+
+    /**
+     * Manages showing/hiding the IME keyboard in conversation.
+     */
+    private class ConversationImeKeyboard extends ConversationInput {
+        public ConversationImeKeyboard(ConversationInputBase baseHost, final boolean isShowing) {
+            super(baseHost, isShowing);
+        }
+
+        @Override
+        public boolean show(boolean animate) {
+            ImeUtil.get().showImeKeyboard(mContext, mSink.getComposeEditText());
+            return true;
+        }
+
+        @Override
+        public boolean hide(boolean animate) {
+            ImeUtil.get().hideImeKeyboard(mContext, mSink.getComposeEditText());
+            return true;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationMessageAdapter.java b/src/com/android/messaging/ui/conversation/ConversationMessageAdapter.java
new file mode 100644
index 0000000..fb04bb4
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationMessageAdapter.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.database.Cursor;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.CursorRecyclerAdapter;
+import com.android.messaging.ui.AsyncImageView.AsyncImageViewDelayLoader;
+import com.android.messaging.ui.conversation.ConversationMessageView.ConversationMessageViewHost;
+import com.android.messaging.util.Assert;
+
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Provides an interface to expose Conversation Message Cursor data to a UI widget like a
+ * RecyclerView.
+ */
+public class ConversationMessageAdapter extends
+    CursorRecyclerAdapter<ConversationMessageAdapter.ConversationMessageViewHolder> {
+
+    private final ConversationMessageViewHost mHost;
+    private final AsyncImageViewDelayLoader mImageViewDelayLoader;
+    private final View.OnClickListener mViewClickListener;
+    private final View.OnLongClickListener mViewLongClickListener;
+    private boolean mOneOnOne;
+    private String mSelectedMessageId;
+
+    public ConversationMessageAdapter(final Context context, final Cursor cursor,
+        final ConversationMessageViewHost host,
+        final AsyncImageViewDelayLoader imageViewDelayLoader,
+        final View.OnClickListener viewClickListener,
+        final View.OnLongClickListener longClickListener) {
+        super(context, cursor, 0);
+        mHost = host;
+        mViewClickListener = viewClickListener;
+        mViewLongClickListener = longClickListener;
+        mImageViewDelayLoader = imageViewDelayLoader;
+        setHasStableIds(true);
+    }
+
+    @Override
+    public void bindViewHolder(final ConversationMessageViewHolder holder,
+            final Context context, final Cursor cursor) {
+        Assert.isTrue(holder.mView instanceof ConversationMessageView);
+        final ConversationMessageView conversationMessageView =
+                (ConversationMessageView) holder.mView;
+        conversationMessageView.bind(cursor, mOneOnOne, mSelectedMessageId);
+    }
+
+    @Override
+    public ConversationMessageViewHolder createViewHolder(final Context context,
+            final ViewGroup parent, final int viewType) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(context);
+        final ConversationMessageView conversationMessageView = (ConversationMessageView)
+                layoutInflater.inflate(R.layout.conversation_message_view, null);
+        conversationMessageView.setHost(mHost);
+        conversationMessageView.setImageViewDelayLoader(mImageViewDelayLoader);
+        return new ConversationMessageViewHolder(conversationMessageView,
+                            mViewClickListener, mViewLongClickListener);
+    }
+
+    public void setSelectedMessage(final String messageId) {
+        mSelectedMessageId = messageId;
+        notifyDataSetChanged();
+    }
+
+    public void setOneOnOne(final boolean oneOnOne, final boolean invalidate) {
+        if (mOneOnOne != oneOnOne) {
+            mOneOnOne = oneOnOne;
+            if (invalidate) {
+                notifyDataSetChanged();
+            }
+        }
+    }
+
+    /**
+    * ViewHolder that holds a ConversationMessageView.
+    */
+    public static class ConversationMessageViewHolder extends RecyclerView.ViewHolder {
+        final View mView;
+
+        /**
+         * @param viewClickListener a View.OnClickListener that should define the interaction when
+         *        an item in the RecyclerView is clicked.
+         */
+        public ConversationMessageViewHolder(final View itemView,
+                final View.OnClickListener viewClickListener,
+                final View.OnLongClickListener viewLongClickListener) {
+            super(itemView);
+            mView = itemView;
+
+            mView.setOnClickListener(viewClickListener);
+            mView.setOnLongClickListener(viewLongClickListener);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationMessageBubbleView.java b/src/com/android/messaging/ui/conversation/ConversationMessageBubbleView.java
new file mode 100644
index 0000000..ef6aeb4
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationMessageBubbleView.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.annotation.VisibleForAnimation;
+import com.android.messaging.datamodel.data.ConversationMessageBubbleData;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Shows the message bubble for one conversation message. It is able to animate size changes
+ * by morphing when the message content changes size.
+ */
+// TODO: Move functionality from ConversationMessageView into this class as appropriate
+public class ConversationMessageBubbleView extends LinearLayout {
+    private int mIntrinsicWidth;
+    private int mMorphedWidth;
+    private ObjectAnimator mAnimator;
+    private boolean mShouldAnimateWidthChange;
+    private final ConversationMessageBubbleData mData;
+    private int mRunningStartWidth;
+    private ViewGroup mBubbleBackground;
+
+    public ConversationMessageBubbleView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mData = new ConversationMessageBubbleData();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mBubbleBackground = (ViewGroup) findViewById(R.id.message_text_and_info);
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        final int newIntrinsicWidth = getMeasuredWidth();
+        if (mIntrinsicWidth == 0 && newIntrinsicWidth != mIntrinsicWidth) {
+            if (mShouldAnimateWidthChange) {
+                kickOffMorphAnimation(mIntrinsicWidth, newIntrinsicWidth);
+            }
+            mIntrinsicWidth = newIntrinsicWidth;
+        }
+
+        if (mMorphedWidth > 0) {
+            mBubbleBackground.getLayoutParams().width = mMorphedWidth;
+        } else {
+            mBubbleBackground.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
+        }
+        mBubbleBackground.requestLayout();
+    }
+
+    @VisibleForAnimation
+    public void setMorphWidth(final int width) {
+        mMorphedWidth = width;
+        requestLayout();
+    }
+
+    public void bind(final ConversationMessageData data) {
+        final boolean changed = mData.bind(data);
+        // Animate width change only when we are binding to the same message, so that we may
+        // animate view size changes on the same message bubble due to things like status text
+        // change.
+        // Don't animate width change when the bubble contains attachments. Width animation is
+        // only suitable for text-only messages (where the bubble size change due to status or
+        // time stamp changes).
+        mShouldAnimateWidthChange = !changed && !data.hasAttachments();
+        if (mAnimator == null) {
+            mMorphedWidth = 0;
+        }
+    }
+
+    public void kickOffMorphAnimation(final int oldWidth, final int newWidth) {
+        if (mAnimator != null) {
+            mAnimator.setIntValues(mRunningStartWidth, newWidth);
+            return;
+        }
+        mRunningStartWidth = oldWidth;
+        mAnimator = ObjectAnimator.ofInt(this, "morphWidth", oldWidth, newWidth);
+        mAnimator.setDuration(UiUtils.MEDIAPICKER_TRANSITION_DURATION);
+        mAnimator.addListener(new AnimatorListener() {
+            @Override
+            public void onAnimationStart(Animator animator) {
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animator) {
+                mAnimator = null;
+                mMorphedWidth = 0;
+                // Allow the bubble to resize if, for example, the status text changed during
+                // the animation.  This will snap to the bigger size if needed.  This is intentional
+                // as animating immediately after looks really bad and switching layout params
+                // during the original animation does not achieve the desired effect.
+                mBubbleBackground.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
+                mBubbleBackground.requestLayout();
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animator) {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animator animator) {
+            }
+        });
+        mAnimator.start();
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationMessageView.java b/src/com/android/messaging/ui/conversation/ConversationMessageView.java
new file mode 100644
index 0000000..282e172
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationMessageView.java
@@ -0,0 +1,1214 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import androidx.annotation.Nullable;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.text.style.URLSpan;
+import android.text.util.Linkify;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.datamodel.media.MessagePartImageRequestDescriptor;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.AsyncImageView.AsyncImageViewDelayLoader;
+import com.android.messaging.ui.AudioAttachmentView;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.ui.MultiAttachmentLayout;
+import com.android.messaging.ui.MultiAttachmentLayout.OnAttachmentClickListener;
+import com.android.messaging.ui.PersonItemView;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.VideoThumbnailView;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.YouTubeUtil;
+import com.google.common.base.Predicate;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * The view for a single entry in a conversation.
+ */
+public class ConversationMessageView extends FrameLayout implements View.OnClickListener,
+        View.OnLongClickListener, OnAttachmentClickListener {
+    public interface ConversationMessageViewHost {
+        boolean onAttachmentClick(ConversationMessageView view, MessagePartData attachment,
+                Rect imageBounds, boolean longPress);
+        SubscriptionListEntry getSubscriptionEntryForSelfParticipant(String selfParticipantId,
+                boolean excludeDefault);
+    }
+
+    private final ConversationMessageData mData;
+
+    private LinearLayout mMessageAttachmentsView;
+    private MultiAttachmentLayout mMultiAttachmentView;
+    private AsyncImageView mMessageImageView;
+    private TextView mMessageTextView;
+    private boolean mMessageTextHasLinks;
+    private boolean mMessageHasYouTubeLink;
+    private TextView mStatusTextView;
+    private TextView mTitleTextView;
+    private TextView mMmsInfoTextView;
+    private LinearLayout mMessageTitleLayout;
+    private TextView mSenderNameTextView;
+    private ContactIconView mContactIconView;
+    private ConversationMessageBubbleView mMessageBubble;
+    private View mSubjectView;
+    private TextView mSubjectLabel;
+    private TextView mSubjectText;
+    private View mDeliveredBadge;
+    private ViewGroup mMessageMetadataView;
+    private ViewGroup mMessageTextAndInfoView;
+    private TextView mSimNameView;
+
+    private boolean mOneOnOne;
+    private ConversationMessageViewHost mHost;
+
+    public ConversationMessageView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        // TODO: we should switch to using Binding and DataModel factory methods.
+        mData = new ConversationMessageData();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mContactIconView = (ContactIconView) findViewById(R.id.conversation_icon);
+        mContactIconView.setOnLongClickListener(new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(final View view) {
+                ConversationMessageView.this.performLongClick();
+                return true;
+            }
+        });
+
+        mMessageAttachmentsView = (LinearLayout) findViewById(R.id.message_attachments);
+        mMultiAttachmentView = (MultiAttachmentLayout) findViewById(R.id.multiple_attachments);
+        mMultiAttachmentView.setOnAttachmentClickListener(this);
+
+        mMessageImageView = (AsyncImageView) findViewById(R.id.message_image);
+        mMessageImageView.setOnClickListener(this);
+        mMessageImageView.setOnLongClickListener(this);
+
+        mMessageTextView = (TextView) findViewById(R.id.message_text);
+        mMessageTextView.setOnClickListener(this);
+        IgnoreLinkLongClickHelper.ignoreLinkLongClick(mMessageTextView, this);
+
+        mStatusTextView = (TextView) findViewById(R.id.message_status);
+        mTitleTextView = (TextView) findViewById(R.id.message_title);
+        mMmsInfoTextView = (TextView) findViewById(R.id.mms_info);
+        mMessageTitleLayout = (LinearLayout) findViewById(R.id.message_title_layout);
+        mSenderNameTextView = (TextView) findViewById(R.id.message_sender_name);
+        mMessageBubble = (ConversationMessageBubbleView) findViewById(R.id.message_content);
+        mSubjectView = findViewById(R.id.subject_container);
+        mSubjectLabel = (TextView) mSubjectView.findViewById(R.id.subject_label);
+        mSubjectText = (TextView) mSubjectView.findViewById(R.id.subject_text);
+        mDeliveredBadge = findViewById(R.id.smsDeliveredBadge);
+        mMessageMetadataView = (ViewGroup) findViewById(R.id.message_metadata);
+        mMessageTextAndInfoView = (ViewGroup) findViewById(R.id.message_text_and_info);
+        mSimNameView = (TextView) findViewById(R.id.sim_name);
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        final int horizontalSpace = MeasureSpec.getSize(widthMeasureSpec);
+        final int iconSize = getResources()
+                .getDimensionPixelSize(R.dimen.conversation_message_contact_icon_size);
+
+        final int unspecifiedMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int iconMeasureSpec = MeasureSpec.makeMeasureSpec(iconSize, MeasureSpec.EXACTLY);
+
+        mContactIconView.measure(iconMeasureSpec, iconMeasureSpec);
+
+        final int arrowWidth =
+                getResources().getDimensionPixelSize(R.dimen.message_bubble_arrow_width);
+
+        // We need to subtract contact icon width twice from the horizontal space to get
+        // the max leftover space because we want the message bubble to extend no further than the
+        // starting position of the message bubble in the opposite direction.
+        final int maxLeftoverSpace = horizontalSpace - mContactIconView.getMeasuredWidth() * 2
+                - arrowWidth - getPaddingLeft() - getPaddingRight();
+        final int messageContentWidthMeasureSpec = MeasureSpec.makeMeasureSpec(maxLeftoverSpace,
+                MeasureSpec.AT_MOST);
+
+        mMessageBubble.measure(messageContentWidthMeasureSpec, unspecifiedMeasureSpec);
+
+        final int maxHeight = Math.max(mContactIconView.getMeasuredHeight(),
+                mMessageBubble.getMeasuredHeight());
+        setMeasuredDimension(horizontalSpace, maxHeight + getPaddingBottom() + getPaddingTop());
+    }
+
+    @Override
+    protected void onLayout(final boolean changed, final int left, final int top, final int right,
+            final int bottom) {
+        final boolean isRtl = AccessibilityUtil.isLayoutRtl(this);
+
+        final int iconWidth = mContactIconView.getMeasuredWidth();
+        final int iconHeight = mContactIconView.getMeasuredHeight();
+        final int iconTop = getPaddingTop();
+        final int contentWidth = (right -left) - iconWidth - getPaddingLeft() - getPaddingRight();
+        final int contentHeight = mMessageBubble.getMeasuredHeight();
+        final int contentTop = iconTop;
+
+        final int iconLeft;
+        final int contentLeft;
+        if (mData.getIsIncoming()) {
+            if (isRtl) {
+                iconLeft = (right - left) - getPaddingRight() - iconWidth;
+                contentLeft = iconLeft - contentWidth;
+            } else {
+                iconLeft = getPaddingLeft();
+                contentLeft = iconLeft + iconWidth;
+            }
+        } else {
+            if (isRtl) {
+                iconLeft = getPaddingLeft();
+                contentLeft = iconLeft + iconWidth;
+            } else {
+                iconLeft = (right - left) - getPaddingRight() - iconWidth;
+                contentLeft = iconLeft - contentWidth;
+            }
+        }
+
+        mContactIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
+
+        mMessageBubble.layout(contentLeft, contentTop, contentLeft + contentWidth,
+                contentTop + contentHeight);
+    }
+
+    /**
+     * Fills in the data associated with this view.
+     *
+     * @param cursor The cursor from a MessageList that this view is in, pointing to its entry.
+     */
+    public void bind(final Cursor cursor) {
+        bind(cursor, true, null);
+    }
+
+    /**
+     * Fills in the data associated with this view.
+     *
+     * @param cursor The cursor from a MessageList that this view is in, pointing to its entry.
+     * @param oneOnOne Whether this is a 1:1 conversation
+     */
+    public void bind(final Cursor cursor,
+            final boolean oneOnOne, final String selectedMessageId) {
+        mOneOnOne = oneOnOne;
+
+        // Update our UI model
+        mData.bind(cursor);
+        setSelected(TextUtils.equals(mData.getMessageId(), selectedMessageId));
+
+        // Update text and image content for the view.
+        updateViewContent();
+
+        // Update colors and layout parameters for the view.
+        updateViewAppearance();
+
+        updateContentDescription();
+    }
+
+    public void setHost(final ConversationMessageViewHost host) {
+        mHost = host;
+    }
+
+    /**
+     * Sets a delay loader instance to manage loading / resuming of image attachments.
+     */
+    public void setImageViewDelayLoader(final AsyncImageViewDelayLoader delayLoader) {
+        Assert.notNull(mMessageImageView);
+        mMessageImageView.setDelayLoader(delayLoader);
+        mMultiAttachmentView.setImageViewDelayLoader(delayLoader);
+    }
+
+    public ConversationMessageData getData() {
+        return mData;
+    }
+
+    /**
+     * Returns whether we should show simplified visual style for the message view (i.e. hide the
+     * avatar and bubble arrow, reduce padding).
+     */
+    private boolean shouldShowSimplifiedVisualStyle() {
+        return mData.getCanClusterWithPreviousMessage();
+    }
+
+    /**
+     * Returns whether we need to show message bubble arrow. We don't show arrow if the message
+     * contains media attachments or if shouldShowSimplifiedVisualStyle() is true.
+     */
+    private boolean shouldShowMessageBubbleArrow() {
+        return !shouldShowSimplifiedVisualStyle()
+                && !(mData.hasAttachments() || mMessageHasYouTubeLink);
+    }
+
+    /**
+     * Returns whether we need to show a message bubble for text content.
+     */
+    private boolean shouldShowMessageTextBubble() {
+        if (mData.hasText()) {
+            return true;
+        }
+        final String subjectText = MmsUtils.cleanseMmsSubject(getResources(),
+                mData.getMmsSubject());
+        if (!TextUtils.isEmpty(subjectText)) {
+            return true;
+        }
+        return false;
+    }
+
+    private void updateViewContent() {
+        updateMessageContent();
+        int titleResId = -1;
+        int statusResId = -1;
+        String statusText = null;
+        switch(mData.getStatus()) {
+            case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
+            case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+            case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                titleResId = R.string.message_title_downloading;
+                statusResId = R.string.message_status_downloading;
+                break;
+
+            case MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD:
+                if (!OsUtil.isSecondaryUser()) {
+                    titleResId = R.string.message_title_manual_download;
+                    if (isSelected()) {
+                        statusResId = R.string.message_status_download_action;
+                    } else {
+                        statusResId = R.string.message_status_download;
+                    }
+                }
+                break;
+
+            case MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE:
+                if (!OsUtil.isSecondaryUser()) {
+                    titleResId = R.string.message_title_download_failed;
+                    statusResId = R.string.message_status_download_error;
+                }
+                break;
+
+            case MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED:
+                if (!OsUtil.isSecondaryUser()) {
+                    titleResId = R.string.message_title_download_failed;
+                    if (isSelected()) {
+                        statusResId = R.string.message_status_download_action;
+                    } else {
+                        statusResId = R.string.message_status_download;
+                    }
+                }
+                break;
+
+            case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND:
+            case MessageData.BUGLE_STATUS_OUTGOING_SENDING:
+                statusResId = R.string.message_status_sending;
+                break;
+
+            case MessageData.BUGLE_STATUS_OUTGOING_RESENDING:
+            case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY:
+                statusResId = R.string.message_status_send_retrying;
+                break;
+
+            case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER:
+                statusResId = R.string.message_status_send_failed_emergency_number;
+                break;
+
+            case MessageData.BUGLE_STATUS_OUTGOING_FAILED:
+                // don't show the error state unless we're the default sms app
+                if (PhoneUtils.getDefault().isDefaultSmsApp()) {
+                    if (isSelected()) {
+                        statusResId = R.string.message_status_resend;
+                    } else {
+                        statusResId = MmsUtils.mapRawStatusToErrorResourceId(
+                                mData.getStatus(), mData.getRawTelephonyStatus());
+                    }
+                    break;
+                }
+                // FALL THROUGH HERE
+
+            case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE:
+            case MessageData.BUGLE_STATUS_OUTGOING_DELIVERED:
+            case MessageData.BUGLE_STATUS_INCOMING_COMPLETE:
+            default:
+                if (!mData.getCanClusterWithNextMessage()) {
+                    statusText = mData.getFormattedReceivedTimeStamp();
+                }
+                break;
+        }
+
+        final boolean titleVisible = (titleResId >= 0);
+        if (titleVisible) {
+            final String titleText = getResources().getString(titleResId);
+            mTitleTextView.setText(titleText);
+
+            final String mmsInfoText = getResources().getString(
+                    R.string.mms_info,
+                    Formatter.formatFileSize(getContext(), mData.getSmsMessageSize()),
+                    DateUtils.formatDateTime(
+                            getContext(),
+                            mData.getMmsExpiry(),
+                            DateUtils.FORMAT_SHOW_DATE |
+                            DateUtils.FORMAT_SHOW_TIME |
+                            DateUtils.FORMAT_NUMERIC_DATE |
+                            DateUtils.FORMAT_NO_YEAR));
+            mMmsInfoTextView.setText(mmsInfoText);
+            mMessageTitleLayout.setVisibility(View.VISIBLE);
+        } else {
+            mMessageTitleLayout.setVisibility(View.GONE);
+        }
+
+        final String subjectText = MmsUtils.cleanseMmsSubject(getResources(),
+                mData.getMmsSubject());
+        final boolean subjectVisible = !TextUtils.isEmpty(subjectText);
+
+        final boolean senderNameVisible = !mOneOnOne && !mData.getCanClusterWithNextMessage()
+                && mData.getIsIncoming();
+        if (senderNameVisible) {
+            mSenderNameTextView.setText(mData.getSenderDisplayName());
+            mSenderNameTextView.setVisibility(View.VISIBLE);
+        } else {
+            mSenderNameTextView.setVisibility(View.GONE);
+        }
+
+        if (statusResId >= 0) {
+            statusText = getResources().getString(statusResId);
+        }
+
+        // We set the text even if the view will be GONE for accessibility
+        mStatusTextView.setText(statusText);
+        final boolean statusVisible = !TextUtils.isEmpty(statusText);
+        if (statusVisible) {
+            mStatusTextView.setVisibility(View.VISIBLE);
+        } else {
+            mStatusTextView.setVisibility(View.GONE);
+        }
+
+        final boolean deliveredBadgeVisible =
+                mData.getStatus() == MessageData.BUGLE_STATUS_OUTGOING_DELIVERED;
+        mDeliveredBadge.setVisibility(deliveredBadgeVisible ? View.VISIBLE : View.GONE);
+
+        // Update the sim indicator.
+        final boolean showSimIconAsIncoming = mData.getIsIncoming() &&
+                (!mData.hasAttachments() || shouldShowMessageTextBubble());
+        final SubscriptionListEntry subscriptionEntry =
+                mHost.getSubscriptionEntryForSelfParticipant(mData.getSelfParticipantId(),
+                        true /* excludeDefault */);
+        final boolean simNameVisible = subscriptionEntry != null &&
+                !TextUtils.isEmpty(subscriptionEntry.displayName) &&
+                !mData.getCanClusterWithNextMessage();
+        if (simNameVisible) {
+            final String simNameText = mData.getIsIncoming() ? getResources().getString(
+                    R.string.incoming_sim_name_text, subscriptionEntry.displayName) :
+                        subscriptionEntry.displayName;
+            mSimNameView.setText(simNameText);
+            mSimNameView.setTextColor(showSimIconAsIncoming ? getResources().getColor(
+                    R.color.timestamp_text_incoming) : subscriptionEntry.displayColor);
+            mSimNameView.setVisibility(VISIBLE);
+        } else {
+            mSimNameView.setText(null);
+            mSimNameView.setVisibility(GONE);
+        }
+
+        final boolean metadataVisible = senderNameVisible || statusVisible
+                || deliveredBadgeVisible || simNameVisible;
+        mMessageMetadataView.setVisibility(metadataVisible ? View.VISIBLE : View.GONE);
+
+        final boolean messageTextAndOrInfoVisible = titleVisible || subjectVisible
+                || mData.hasText() || metadataVisible;
+        mMessageTextAndInfoView.setVisibility(
+                messageTextAndOrInfoVisible ? View.VISIBLE : View.GONE);
+
+        if (shouldShowSimplifiedVisualStyle()) {
+            mContactIconView.setVisibility(View.GONE);
+            mContactIconView.setImageResourceUri(null);
+        } else {
+            mContactIconView.setVisibility(View.VISIBLE);
+            final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                    mData.getSenderProfilePhotoUri(),
+                    mData.getSenderFullName(),
+                    mData.getSenderNormalizedDestination(),
+                    mData.getSenderContactLookupKey());
+            mContactIconView.setImageResourceUri(avatarUri, mData.getSenderContactId(),
+                    mData.getSenderContactLookupKey(), mData.getSenderNormalizedDestination());
+        }
+    }
+
+    private void updateMessageContent() {
+        // We must update the text before the attachments since we search the text to see if we
+        // should make a preview youtube image in the attachments
+        updateMessageText();
+        updateMessageAttachments();
+        updateMessageSubject();
+        mMessageBubble.bind(mData);
+    }
+
+    private void updateMessageAttachments() {
+        // Bind video, audio, and VCard attachments. If there are multiple, they stack vertically.
+        bindAttachmentsOfSameType(sVideoFilter,
+                R.layout.message_video_attachment, mVideoViewBinder, VideoThumbnailView.class);
+        bindAttachmentsOfSameType(sAudioFilter,
+                R.layout.message_audio_attachment, mAudioViewBinder, AudioAttachmentView.class);
+        bindAttachmentsOfSameType(sVCardFilter,
+                R.layout.message_vcard_attachment, mVCardViewBinder, PersonItemView.class);
+
+        // Bind image attachments. If there are multiple, they are shown in a collage view.
+        final List<MessagePartData> imageParts = mData.getAttachments(sImageFilter);
+        if (imageParts.size() > 1) {
+            Collections.sort(imageParts, sImageComparator);
+            mMultiAttachmentView.bindAttachments(imageParts, null, imageParts.size());
+            mMultiAttachmentView.setVisibility(View.VISIBLE);
+        } else {
+            mMultiAttachmentView.setVisibility(View.GONE);
+        }
+
+        // In the case that we have no image attachments and exactly one youtube link in a message
+        // then we will show a preview.
+        String youtubeThumbnailUrl = null;
+        String originalYoutubeLink = null;
+        if (mMessageTextHasLinks && imageParts.size() == 0) {
+            CharSequence messageTextWithSpans = mMessageTextView.getText();
+            final URLSpan[] spans = ((Spanned) messageTextWithSpans).getSpans(0,
+                    messageTextWithSpans.length(), URLSpan.class);
+            for (URLSpan span : spans) {
+                String url = span.getURL();
+                String youtubeLinkForUrl = YouTubeUtil.getYoutubePreviewImageLink(url);
+                if (!TextUtils.isEmpty(youtubeLinkForUrl)) {
+                    if (TextUtils.isEmpty(youtubeThumbnailUrl)) {
+                        // Save the youtube link if we don't already have one
+                        youtubeThumbnailUrl = youtubeLinkForUrl;
+                        originalYoutubeLink = url;
+                    } else {
+                        // We already have a youtube link. This means we have two youtube links so
+                        // we shall show none.
+                        youtubeThumbnailUrl = null;
+                        originalYoutubeLink = null;
+                        break;
+                    }
+                }
+            }
+        }
+        // We need to keep track if we have a youtube link in the message so that we will not show
+        // the arrow
+        mMessageHasYouTubeLink = !TextUtils.isEmpty(youtubeThumbnailUrl);
+
+        // We will show the message image view if there is one attachment or one youtube link
+        if (imageParts.size() == 1 || mMessageHasYouTubeLink) {
+            // Get the display metrics for a hint for how large to pull the image data into
+            final WindowManager windowManager = (WindowManager) getContext().
+                    getSystemService(Context.WINDOW_SERVICE);
+            final DisplayMetrics displayMetrics = new DisplayMetrics();
+            windowManager.getDefaultDisplay().getMetrics(displayMetrics);
+
+            final int iconSize = getResources()
+                    .getDimensionPixelSize(R.dimen.conversation_message_contact_icon_size);
+            final int desiredWidth = displayMetrics.widthPixels - iconSize - iconSize;
+
+            if (imageParts.size() == 1) {
+                final MessagePartData imagePart = imageParts.get(0);
+                // If the image is big, we want to scale it down to save memory since we're going to
+                // scale it down to fit into the bubble width. We don't constrain the height.
+                final ImageRequestDescriptor imageRequest =
+                        new MessagePartImageRequestDescriptor(imagePart,
+                                desiredWidth,
+                                MessagePartData.UNSPECIFIED_SIZE,
+                                false);
+                adjustImageViewBounds(imagePart);
+                mMessageImageView.setImageResourceId(imageRequest);
+                mMessageImageView.setTag(imagePart);
+            } else {
+                // Youtube Thumbnail image
+                final ImageRequestDescriptor imageRequest =
+                        new UriImageRequestDescriptor(Uri.parse(youtubeThumbnailUrl), desiredWidth,
+                            MessagePartData.UNSPECIFIED_SIZE, true /* allowCompression */,
+                            true /* isStatic */, false /* cropToCircle */,
+                            ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                            ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+                mMessageImageView.setImageResourceId(imageRequest);
+                mMessageImageView.setTag(originalYoutubeLink);
+            }
+            mMessageImageView.setVisibility(View.VISIBLE);
+        } else {
+            mMessageImageView.setImageResourceId(null);
+            mMessageImageView.setVisibility(View.GONE);
+        }
+
+        // Show the message attachments container if any of its children are visible
+        boolean attachmentsVisible = false;
+        for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) {
+            final View attachmentView = mMessageAttachmentsView.getChildAt(i);
+            if (attachmentView.getVisibility() == View.VISIBLE) {
+                attachmentsVisible = true;
+                break;
+            }
+        }
+        mMessageAttachmentsView.setVisibility(attachmentsVisible ? View.VISIBLE : View.GONE);
+    }
+
+    private void bindAttachmentsOfSameType(final Predicate<MessagePartData> attachmentTypeFilter,
+            final int attachmentViewLayoutRes, final AttachmentViewBinder viewBinder,
+            final Class<?> attachmentViewClass) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+
+        // Iterate through all attachments of a particular type (video, audio, etc).
+        // Find the first attachment index that matches the given type if possible.
+        int attachmentViewIndex = -1;
+        View existingAttachmentView;
+        do {
+            existingAttachmentView = mMessageAttachmentsView.getChildAt(++attachmentViewIndex);
+        } while (existingAttachmentView != null &&
+                !(attachmentViewClass.isInstance(existingAttachmentView)));
+
+        for (final MessagePartData attachment : mData.getAttachments(attachmentTypeFilter)) {
+            View attachmentView = mMessageAttachmentsView.getChildAt(attachmentViewIndex);
+            if (!attachmentViewClass.isInstance(attachmentView)) {
+                attachmentView = layoutInflater.inflate(attachmentViewLayoutRes,
+                        mMessageAttachmentsView, false /* attachToRoot */);
+                attachmentView.setOnClickListener(this);
+                attachmentView.setOnLongClickListener(this);
+                mMessageAttachmentsView.addView(attachmentView, attachmentViewIndex);
+            }
+            viewBinder.bindView(attachmentView, attachment);
+            attachmentView.setTag(attachment);
+            attachmentView.setVisibility(View.VISIBLE);
+            attachmentViewIndex++;
+        }
+        // If there are unused views left over, unbind or remove them.
+        while (attachmentViewIndex < mMessageAttachmentsView.getChildCount()) {
+            final View attachmentView = mMessageAttachmentsView.getChildAt(attachmentViewIndex);
+            if (attachmentViewClass.isInstance(attachmentView)) {
+                mMessageAttachmentsView.removeViewAt(attachmentViewIndex);
+            } else {
+                // No more views of this type; we're done.
+                break;
+            }
+        }
+    }
+
+    private void updateMessageSubject() {
+        final String subjectText = MmsUtils.cleanseMmsSubject(getResources(),
+                mData.getMmsSubject());
+        final boolean subjectVisible = !TextUtils.isEmpty(subjectText);
+
+        if (subjectVisible) {
+            mSubjectText.setText(subjectText);
+            mSubjectView.setVisibility(View.VISIBLE);
+        } else {
+            mSubjectView.setVisibility(View.GONE);
+        }
+    }
+
+    private void updateMessageText() {
+        final String text = mData.getText();
+        if (!TextUtils.isEmpty(text)) {
+            mMessageTextView.setText(text);
+            // Linkify phone numbers, web urls, emails, and map addresses to allow users to
+            // click on them and take the default intent.
+            mMessageTextHasLinks = Linkify.addLinks(mMessageTextView, Linkify.ALL);
+            mMessageTextView.setVisibility(View.VISIBLE);
+        } else {
+            mMessageTextView.setVisibility(View.GONE);
+            mMessageTextHasLinks = false;
+        }
+    }
+
+    private void updateViewAppearance() {
+        final Resources res = getResources();
+        final ConversationDrawables drawableProvider = ConversationDrawables.get();
+        final boolean incoming = mData.getIsIncoming();
+        final boolean outgoing = !incoming;
+        final boolean showArrow =  shouldShowMessageBubbleArrow();
+
+        final int messageTopPaddingClustered =
+                res.getDimensionPixelSize(R.dimen.message_padding_same_author);
+        final int messageTopPaddingDefault =
+                res.getDimensionPixelSize(R.dimen.message_padding_default);
+        final int arrowWidth = res.getDimensionPixelOffset(R.dimen.message_bubble_arrow_width);
+        final int messageTextMinHeightDefault = res.getDimensionPixelSize(
+                R.dimen.conversation_message_contact_icon_size);
+        final int messageTextLeftRightPadding = res.getDimensionPixelOffset(
+                R.dimen.message_text_left_right_padding);
+        final int textTopPaddingDefault = res.getDimensionPixelOffset(
+                R.dimen.message_text_top_padding);
+        final int textBottomPaddingDefault = res.getDimensionPixelOffset(
+                R.dimen.message_text_bottom_padding);
+
+        // These values depend on whether the message has text, attachments, or both.
+        // We intentionally don't set defaults, so the compiler will tell us if we forget
+        // to set one of them, or if we set one more than once.
+        final int contentLeftPadding, contentRightPadding;
+        final Drawable textBackground;
+        final int textMinHeight;
+        final int textTopMargin;
+        final int textTopPadding, textBottomPadding;
+        final int textLeftPadding, textRightPadding;
+
+        if (mData.hasAttachments()) {
+            if (shouldShowMessageTextBubble()) {
+                // Text and attachment(s)
+                contentLeftPadding = incoming ? arrowWidth : 0;
+                contentRightPadding = outgoing ? arrowWidth : 0;
+                textBackground = drawableProvider.getBubbleDrawable(
+                        isSelected(),
+                        incoming,
+                        false /* needArrow */,
+                        mData.hasIncomingErrorStatus());
+                textMinHeight = messageTextMinHeightDefault;
+                textTopMargin = messageTopPaddingClustered;
+                textTopPadding = textTopPaddingDefault;
+                textBottomPadding = textBottomPaddingDefault;
+                textLeftPadding = messageTextLeftRightPadding;
+                textRightPadding = messageTextLeftRightPadding;
+                mMessageTextView.setTextIsSelectable(isSelected());
+            } else {
+                // Attachment(s) only
+                contentLeftPadding = incoming ? arrowWidth : 0;
+                contentRightPadding = outgoing ? arrowWidth : 0;
+                textBackground = null;
+                textMinHeight = 0;
+                textTopMargin = 0;
+                textTopPadding = 0;
+                textBottomPadding = 0;
+                textLeftPadding = 0;
+                textRightPadding = 0;
+            }
+        } else {
+            // Text only
+            contentLeftPadding = (!showArrow && incoming) ? arrowWidth : 0;
+            contentRightPadding = (!showArrow && outgoing) ? arrowWidth : 0;
+            textBackground = drawableProvider.getBubbleDrawable(
+                    isSelected(),
+                    incoming,
+                    shouldShowMessageBubbleArrow(),
+                    mData.hasIncomingErrorStatus());
+            textMinHeight = messageTextMinHeightDefault;
+            textTopMargin = 0;
+            textTopPadding = textTopPaddingDefault;
+            textBottomPadding = textBottomPaddingDefault;
+            mMessageTextView.setTextIsSelectable(isSelected());
+            if (showArrow && incoming) {
+                textLeftPadding = messageTextLeftRightPadding + arrowWidth;
+            } else {
+                textLeftPadding = messageTextLeftRightPadding;
+            }
+            if (showArrow && outgoing) {
+                textRightPadding = messageTextLeftRightPadding + arrowWidth;
+            } else {
+                textRightPadding = messageTextLeftRightPadding;
+            }
+        }
+
+        // These values do not depend on whether the message includes attachments
+        final int gravity = incoming ? (Gravity.START | Gravity.CENTER_VERTICAL) :
+                (Gravity.END | Gravity.CENTER_VERTICAL);
+        final int messageTopPadding = shouldShowSimplifiedVisualStyle() ?
+                messageTopPaddingClustered : messageTopPaddingDefault;
+        final int metadataTopPadding = res.getDimensionPixelOffset(
+                R.dimen.message_metadata_top_padding);
+
+        // Update the message text/info views
+        ImageUtils.setBackgroundDrawableOnView(mMessageTextAndInfoView, textBackground);
+        mMessageTextAndInfoView.setMinimumHeight(textMinHeight);
+        final LinearLayout.LayoutParams textAndInfoLayoutParams =
+                (LinearLayout.LayoutParams) mMessageTextAndInfoView.getLayoutParams();
+        textAndInfoLayoutParams.topMargin = textTopMargin;
+
+        if (UiUtils.isRtlMode()) {
+            // Need to switch right and left padding in RtL mode
+            mMessageTextAndInfoView.setPadding(textRightPadding, textTopPadding, textLeftPadding,
+                    textBottomPadding);
+            mMessageBubble.setPadding(contentRightPadding, 0, contentLeftPadding, 0);
+        } else {
+            mMessageTextAndInfoView.setPadding(textLeftPadding, textTopPadding, textRightPadding,
+                    textBottomPadding);
+            mMessageBubble.setPadding(contentLeftPadding, 0, contentRightPadding, 0);
+        }
+
+        // Update the message row and message bubble views
+        setPadding(getPaddingLeft(), messageTopPadding, getPaddingRight(), 0);
+        mMessageBubble.setGravity(gravity);
+        updateMessageAttachmentsAppearance(gravity);
+
+        mMessageMetadataView.setPadding(0, metadataTopPadding, 0, 0);
+
+        updateTextAppearance();
+
+        requestLayout();
+    }
+
+    private void updateContentDescription() {
+        StringBuilder description = new StringBuilder();
+
+        Resources res = getResources();
+        String separator = res.getString(R.string.enumeration_comma);
+
+        // Sender information
+        boolean hasPlainTextMessage = !(TextUtils.isEmpty(mData.getText()) ||
+                mMessageTextHasLinks);
+        if (mData.getIsIncoming()) {
+            int senderResId = hasPlainTextMessage
+                ? R.string.incoming_text_sender_content_description
+                : R.string.incoming_sender_content_description;
+            description.append(res.getString(senderResId, mData.getSenderDisplayName()));
+        } else {
+            int senderResId = hasPlainTextMessage
+                ? R.string.outgoing_text_sender_content_description
+                : R.string.outgoing_sender_content_description;
+            description.append(res.getString(senderResId));
+        }
+
+        if (mSubjectView.getVisibility() == View.VISIBLE) {
+            description.append(separator);
+            description.append(mSubjectText.getText());
+        }
+
+        if (mMessageTextView.getVisibility() == View.VISIBLE) {
+            // If the message has hyperlinks, we will let the user navigate to the text message so
+            // that the hyperlink can be clicked. Otherwise, the text message does not need to
+            // be reachable.
+            if (mMessageTextHasLinks) {
+                mMessageTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+            } else {
+                mMessageTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+                description.append(separator);
+                description.append(mMessageTextView.getText());
+            }
+        }
+
+        if (mMessageTitleLayout.getVisibility() == View.VISIBLE) {
+            description.append(separator);
+            description.append(mTitleTextView.getText());
+
+            description.append(separator);
+            description.append(mMmsInfoTextView.getText());
+        }
+
+        if (mStatusTextView.getVisibility() == View.VISIBLE) {
+            description.append(separator);
+            description.append(mStatusTextView.getText());
+        }
+
+        if (mSimNameView.getVisibility() == View.VISIBLE) {
+            description.append(separator);
+            description.append(mSimNameView.getText());
+        }
+
+        if (mDeliveredBadge.getVisibility() == View.VISIBLE) {
+            description.append(separator);
+            description.append(res.getString(R.string.delivered_status_content_description));
+        }
+
+        setContentDescription(description);
+    }
+
+    private void updateMessageAttachmentsAppearance(final int gravity) {
+        mMessageAttachmentsView.setGravity(gravity);
+
+        // Tint image/video attachments when selected
+        final int selectedImageTint = getResources().getColor(R.color.message_image_selected_tint);
+        if (mMessageImageView.getVisibility() == View.VISIBLE) {
+            if (isSelected()) {
+                mMessageImageView.setColorFilter(selectedImageTint);
+            } else {
+                mMessageImageView.clearColorFilter();
+            }
+        }
+        if (mMultiAttachmentView.getVisibility() == View.VISIBLE) {
+            if (isSelected()) {
+                mMultiAttachmentView.setColorFilter(selectedImageTint);
+            } else {
+                mMultiAttachmentView.clearColorFilter();
+            }
+        }
+        for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) {
+            final View attachmentView = mMessageAttachmentsView.getChildAt(i);
+            if (attachmentView instanceof VideoThumbnailView
+                    && attachmentView.getVisibility() == View.VISIBLE) {
+                final VideoThumbnailView videoView = (VideoThumbnailView) attachmentView;
+                if (isSelected()) {
+                    videoView.setColorFilter(selectedImageTint);
+                } else {
+                    videoView.clearColorFilter();
+                }
+            }
+        }
+
+        // If there are multiple attachment bubbles in a single message, add some separation.
+        final int multipleAttachmentPadding =
+                getResources().getDimensionPixelSize(R.dimen.message_padding_same_author);
+
+        boolean previousVisibleView = false;
+        for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) {
+            final View attachmentView = mMessageAttachmentsView.getChildAt(i);
+            if (attachmentView.getVisibility() == View.VISIBLE) {
+                final int margin = previousVisibleView ? multipleAttachmentPadding : 0;
+                ((LinearLayout.LayoutParams) attachmentView.getLayoutParams()).topMargin = margin;
+                // updateViewAppearance calls requestLayout() at the end, so we don't need to here
+                previousVisibleView = true;
+            }
+        }
+    }
+
+    private void updateTextAppearance() {
+        int messageColorResId;
+        int statusColorResId = -1;
+        int infoColorResId = -1;
+        int timestampColorResId;
+        int subjectLabelColorResId;
+        if (isSelected()) {
+            messageColorResId = R.color.message_text_color_incoming;
+            statusColorResId = R.color.message_action_status_text;
+            infoColorResId = R.color.message_action_info_text;
+            if (shouldShowMessageTextBubble()) {
+                timestampColorResId = R.color.message_action_timestamp_text;
+                subjectLabelColorResId = R.color.message_action_timestamp_text;
+            } else {
+                // If there's no text, the timestamp will be shown below the attachments,
+                // against the conversation view background.
+                timestampColorResId = R.color.timestamp_text_outgoing;
+                subjectLabelColorResId = R.color.timestamp_text_outgoing;
+            }
+        } else {
+            messageColorResId = (mData.getIsIncoming() ?
+                    R.color.message_text_color_incoming : R.color.message_text_color_outgoing);
+            statusColorResId = messageColorResId;
+            infoColorResId = R.color.timestamp_text_incoming;
+            switch(mData.getStatus()) {
+
+                case MessageData.BUGLE_STATUS_OUTGOING_FAILED:
+                case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER:
+                    timestampColorResId = R.color.message_failed_timestamp_text;
+                    subjectLabelColorResId = R.color.timestamp_text_outgoing;
+                    break;
+
+                case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND:
+                case MessageData.BUGLE_STATUS_OUTGOING_SENDING:
+                case MessageData.BUGLE_STATUS_OUTGOING_RESENDING:
+                case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY:
+                case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE:
+                case MessageData.BUGLE_STATUS_OUTGOING_DELIVERED:
+                    timestampColorResId = R.color.timestamp_text_outgoing;
+                    subjectLabelColorResId = R.color.timestamp_text_outgoing;
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE:
+                case MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED:
+                    messageColorResId = R.color.message_text_color_incoming_download_failed;
+                    timestampColorResId = R.color.message_download_failed_timestamp_text;
+                    subjectLabelColorResId = R.color.message_text_color_incoming_download_failed;
+                    statusColorResId = R.color.message_download_failed_status_text;
+                    infoColorResId = R.color.message_info_text_incoming_download_failed;
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
+                case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
+                case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+                case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                case MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD:
+                    timestampColorResId = R.color.message_text_color_incoming;
+                    subjectLabelColorResId = R.color.message_text_color_incoming;
+                    infoColorResId = R.color.timestamp_text_incoming;
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_COMPLETE:
+                default:
+                    timestampColorResId = R.color.timestamp_text_incoming;
+                    subjectLabelColorResId = R.color.timestamp_text_incoming;
+                    infoColorResId = -1; // Not used
+                    break;
+            }
+        }
+        final int messageColor = getResources().getColor(messageColorResId);
+        mMessageTextView.setTextColor(messageColor);
+        mMessageTextView.setLinkTextColor(messageColor);
+        mSubjectText.setTextColor(messageColor);
+        if (statusColorResId >= 0) {
+            mTitleTextView.setTextColor(getResources().getColor(statusColorResId));
+        }
+        if (infoColorResId >= 0) {
+            mMmsInfoTextView.setTextColor(getResources().getColor(infoColorResId));
+        }
+        if (timestampColorResId == R.color.timestamp_text_incoming &&
+                mData.hasAttachments() && !shouldShowMessageTextBubble()) {
+            timestampColorResId = R.color.timestamp_text_outgoing;
+        }
+        mStatusTextView.setTextColor(getResources().getColor(timestampColorResId));
+
+        mSubjectLabel.setTextColor(getResources().getColor(subjectLabelColorResId));
+        mSenderNameTextView.setTextColor(getResources().getColor(timestampColorResId));
+    }
+
+    /**
+     * If we don't know the size of the image, we want to show it in a fixed-sized frame to
+     * avoid janks when the image is loaded and resized. Otherwise, we can set the imageview to
+     * take on normal layout params.
+     */
+    private void adjustImageViewBounds(final MessagePartData imageAttachment) {
+        Assert.isTrue(ContentType.isImageType(imageAttachment.getContentType()));
+        final ViewGroup.LayoutParams layoutParams = mMessageImageView.getLayoutParams();
+        if (imageAttachment.getWidth() == MessagePartData.UNSPECIFIED_SIZE ||
+                imageAttachment.getHeight() == MessagePartData.UNSPECIFIED_SIZE) {
+            // We don't know the size of the image attachment, enable letterboxing on the image
+            // and show a fixed sized attachment. This should happen at most once per image since
+            // after the image is loaded we then save the image dimensions to the db so that the
+            // next time we can display the full size.
+            layoutParams.width = getResources()
+                    .getDimensionPixelSize(R.dimen.image_attachment_fallback_width);
+            layoutParams.height = getResources()
+                    .getDimensionPixelSize(R.dimen.image_attachment_fallback_height);
+            mMessageImageView.setScaleType(ScaleType.CENTER_CROP);
+        } else {
+            layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            // ScaleType.CENTER_INSIDE and FIT_CENTER behave similarly for most images. However,
+            // FIT_CENTER works better for small images as it enlarges the image such that the
+            // minimum size ("android:minWidth" etc) is honored.
+            mMessageImageView.setScaleType(ScaleType.FIT_CENTER);
+        }
+    }
+
+    @Override
+    public void onClick(final View view) {
+        final Object tag = view.getTag();
+        if (tag instanceof MessagePartData) {
+            final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
+            onAttachmentClick((MessagePartData) tag, bounds, false /* longPress */);
+        } else if (tag instanceof String) {
+            // Currently the only object that would make a tag of a string is a youtube preview
+            // image
+            UIIntents.get().launchBrowserForUrl(getContext(), (String) tag);
+        }
+    }
+
+    @Override
+    public boolean onLongClick(final View view) {
+        if (view == mMessageTextView) {
+            // Avoid trying to reselect the message
+            if (isSelected()) {
+                return false;
+            }
+
+            // Preemptively handle the long click event on message text so it's not handled by
+            // the link spans.
+            return performLongClick();
+        }
+
+        final Object tag = view.getTag();
+        if (tag instanceof MessagePartData) {
+            final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
+            return onAttachmentClick((MessagePartData) tag, bounds, true /* longPress */);
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean onAttachmentClick(final MessagePartData attachment,
+            final Rect viewBoundsOnScreen, final boolean longPress) {
+        return mHost.onAttachmentClick(this, attachment, viewBoundsOnScreen, longPress);
+    }
+
+    public ContactIconView getContactIconView() {
+        return mContactIconView;
+    }
+
+    // Sort photos in MultiAttachLayout in the same order as the ConversationImagePartsView
+    static final Comparator<MessagePartData> sImageComparator = new Comparator<MessagePartData>(){
+        @Override
+        public int compare(final MessagePartData x, final MessagePartData y) {
+            return x.getPartId().compareTo(y.getPartId());
+        }
+    };
+
+    static final Predicate<MessagePartData> sVideoFilter = new Predicate<MessagePartData>() {
+        @Override
+        public boolean apply(final MessagePartData part) {
+            return part.isVideo();
+        }
+    };
+
+    static final Predicate<MessagePartData> sAudioFilter = new Predicate<MessagePartData>() {
+        @Override
+        public boolean apply(final MessagePartData part) {
+            return part.isAudio();
+        }
+    };
+
+    static final Predicate<MessagePartData> sVCardFilter = new Predicate<MessagePartData>() {
+        @Override
+        public boolean apply(final MessagePartData part) {
+            return part.isVCard();
+        }
+    };
+
+    static final Predicate<MessagePartData> sImageFilter = new Predicate<MessagePartData>() {
+        @Override
+        public boolean apply(final MessagePartData part) {
+            return part.isImage();
+        }
+    };
+
+    interface AttachmentViewBinder {
+        void bindView(View view, MessagePartData attachment);
+        void unbind(View view);
+    }
+
+    final AttachmentViewBinder mVideoViewBinder = new AttachmentViewBinder() {
+        @Override
+        public void bindView(final View view, final MessagePartData attachment) {
+            ((VideoThumbnailView) view).setSource(attachment, mData.getIsIncoming());
+        }
+
+        @Override
+        public void unbind(final View view) {
+            ((VideoThumbnailView) view).setSource((Uri) null, mData.getIsIncoming());
+        }
+    };
+
+    final AttachmentViewBinder mAudioViewBinder = new AttachmentViewBinder() {
+        @Override
+        public void bindView(final View view, final MessagePartData attachment) {
+            final AudioAttachmentView audioView = (AudioAttachmentView) view;
+            audioView.bindMessagePartData(attachment, mData.getIsIncoming(), isSelected());
+            audioView.setBackground(ConversationDrawables.get().getBubbleDrawable(
+                    isSelected(), mData.getIsIncoming(), false /* needArrow */,
+                    mData.hasIncomingErrorStatus()));
+        }
+
+        @Override
+        public void unbind(final View view) {
+            ((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming(), false);
+        }
+    };
+
+    final AttachmentViewBinder mVCardViewBinder = new AttachmentViewBinder() {
+        @Override
+        public void bindView(final View view, final MessagePartData attachment) {
+            final PersonItemView personView = (PersonItemView) view;
+            personView.bind(DataModel.get().createVCardContactItemData(getContext(),
+                    attachment));
+            personView.setBackground(ConversationDrawables.get().getBubbleDrawable(
+                    isSelected(), mData.getIsIncoming(), false /* needArrow */,
+                    mData.hasIncomingErrorStatus()));
+            final int nameTextColorRes;
+            final int detailsTextColorRes;
+            if (isSelected()) {
+                nameTextColorRes = R.color.message_text_color_incoming;
+                detailsTextColorRes = R.color.message_text_color_incoming;
+            } else {
+                nameTextColorRes = mData.getIsIncoming() ? R.color.message_text_color_incoming
+                        : R.color.message_text_color_outgoing;
+                detailsTextColorRes = mData.getIsIncoming() ? R.color.timestamp_text_incoming
+                        : R.color.timestamp_text_outgoing;
+            }
+            personView.setNameTextColor(getResources().getColor(nameTextColorRes));
+            personView.setDetailsTextColor(getResources().getColor(detailsTextColorRes));
+        }
+
+        @Override
+        public void unbind(final View view) {
+            ((PersonItemView) view).bind(null);
+        }
+    };
+
+    /**
+     * A helper class that allows us to handle long clicks on linkified message text view (i.e. to
+     * select the message) so it's not handled by the link spans to launch apps for the links.
+     */
+    private static class IgnoreLinkLongClickHelper implements OnLongClickListener, OnTouchListener {
+        private boolean mIsLongClick;
+        private final OnLongClickListener mDelegateLongClickListener;
+
+        /**
+         * Ignore long clicks on linkified texts for a given text view.
+         * @param textView the TextView to ignore long clicks on
+         * @param longClickListener a delegate OnLongClickListener to be called when the view is
+         *        long clicked.
+         */
+        public static void ignoreLinkLongClick(final TextView textView,
+                @Nullable final OnLongClickListener longClickListener) {
+            final IgnoreLinkLongClickHelper helper =
+                    new IgnoreLinkLongClickHelper(longClickListener);
+            textView.setOnLongClickListener(helper);
+            textView.setOnTouchListener(helper);
+        }
+
+        private IgnoreLinkLongClickHelper(@Nullable final OnLongClickListener longClickListener) {
+            mDelegateLongClickListener = longClickListener;
+        }
+
+        @Override
+        public boolean onLongClick(final View v) {
+            // Record that this click is a long click.
+            mIsLongClick = true;
+            if (mDelegateLongClickListener != null) {
+                return mDelegateLongClickListener.onLongClick(v);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean onTouch(final View v, final MotionEvent event) {
+            if (event.getActionMasked() == MotionEvent.ACTION_UP && mIsLongClick) {
+                // This touch event is a long click, preemptively handle this touch event so that
+                // the link span won't get a onClicked() callback.
+                mIsLongClick = false;
+                return false;
+            }
+
+            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+                mIsLongClick = false;
+            }
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/ConversationSimSelector.java b/src/com/android/messaging/ui/conversation/ConversationSimSelector.java
new file mode 100644
index 0000000..94c7e76
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/ConversationSimSelector.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import androidx.core.util.Pair;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.ui.conversation.SimSelectorView.SimSelectorViewListener;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.ThreadUtil;
+
+/**
+ * Manages showing/hiding the SIM selector in conversation.
+ */
+abstract class ConversationSimSelector extends ConversationInput {
+    private SimSelectorView mSimSelectorView;
+    private Pair<Boolean /* show */, Boolean /* animate */> mPendingShow;
+    private boolean mDataReady;
+    private String mSelectedSimText;
+
+    public ConversationSimSelector(ConversationInputBase baseHost) {
+        super(baseHost, false);
+    }
+
+    public void onSubscriptionListDataLoaded(final SubscriptionListData subscriptionListData) {
+        ensureSimSelectorView();
+        mSimSelectorView.bind(subscriptionListData);
+        mDataReady = subscriptionListData != null && subscriptionListData.hasData();
+        if (mPendingShow != null && mDataReady) {
+            Assert.isTrue(OsUtil.isAtLeastL_MR1());
+            final boolean show = mPendingShow.first;
+            final boolean animate = mPendingShow.second;
+            ThreadUtil.getMainThreadHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    // This will No-Op if we are no longer attached to the host.
+                    mConversationInputBase.showHideInternal(ConversationSimSelector.this,
+                            show, animate);
+                }
+            });
+            mPendingShow = null;
+        }
+    }
+
+    private void announcedSelectedSim() {
+        final Context context = Factory.get().getApplicationContext();
+        if (AccessibilityUtil.isTouchExplorationEnabled(context) &&
+                !TextUtils.isEmpty(mSelectedSimText)) {
+            AccessibilityUtil.announceForAccessibilityCompat(
+                    mSimSelectorView, null,
+                    context.getString(R.string.selected_sim_content_message, mSelectedSimText));
+        }
+    }
+
+    public void setSelected(final SubscriptionListEntry subEntry) {
+        mSelectedSimText = subEntry == null ? null : subEntry.displayName;
+    }
+
+    @Override
+    public boolean show(boolean animate) {
+        announcedSelectedSim();
+        return showHide(true, animate);
+    }
+
+    @Override
+    public boolean hide(boolean animate) {
+        return showHide(false, animate);
+    }
+
+    private boolean showHide(final boolean show, final boolean animate) {
+        if (!OsUtil.isAtLeastL_MR1()) {
+            return false;
+        }
+
+        if (mDataReady) {
+            mSimSelectorView.showOrHide(show, animate);
+            return mSimSelectorView.isOpen() == show;
+        } else {
+            mPendingShow = Pair.create(show, animate);
+            return false;
+        }
+    }
+
+    private void ensureSimSelectorView() {
+        if (mSimSelectorView == null) {
+            // Grab the SIM selector view from the host. This class assumes ownership of it.
+            mSimSelectorView = getSimSelectorView();
+            mSimSelectorView.setItemLayoutId(getSimSelectorItemLayoutId());
+            mSimSelectorView.setListener(new SimSelectorViewListener() {
+
+                @Override
+                public void onSimSelectorVisibilityChanged(boolean visible) {
+                    onVisibilityChanged(visible);
+                }
+
+                @Override
+                public void onSimItemClicked(SubscriptionListEntry item) {
+                    selectSim(item);
+                }
+            });
+        }
+    }
+
+    protected abstract SimSelectorView getSimSelectorView();
+    protected abstract void selectSim(final SubscriptionListEntry item);
+    protected abstract int getSimSelectorItemLayoutId();
+
+}
diff --git a/src/com/android/messaging/ui/conversation/EnterSelfPhoneNumberDialog.java b/src/com/android/messaging/ui/conversation/EnterSelfPhoneNumberDialog.java
new file mode 100644
index 0000000..e3ad601
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/EnterSelfPhoneNumberDialog.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.widget.EditText;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.ParticipantRefresh;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * The dialog for the user to enter the phone number of their sim.
+ */
+public class EnterSelfPhoneNumberDialog extends DialogFragment {
+    private EditText mEditText;
+    private int mSubId;
+
+    public static EnterSelfPhoneNumberDialog newInstance(final int subId) {
+        final EnterSelfPhoneNumberDialog dialog = new EnterSelfPhoneNumberDialog();
+        dialog.mSubId = subId;
+        return dialog;
+    }
+
+    @Override
+    public Dialog onCreateDialog(final Bundle savedInstanceState) {
+        final Context context = getActivity();
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        mEditText = (EditText) inflater.inflate(R.layout.enter_phone_number_view, null, false);
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setTitle(R.string.enter_phone_number_title)
+                .setMessage(R.string.enter_phone_number_text)
+                .setView(mEditText)
+                .setNegativeButton(android.R.string.cancel,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(final DialogInterface dialog,
+                                    final int button) {
+                                dismiss();
+                            }
+                })
+                .setPositiveButton(android.R.string.ok,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(final DialogInterface dialog,
+                                    final int button) {
+                                final String newNumber = mEditText.getText().toString();
+                                dismiss();
+                                if (!TextUtils.isEmpty(newNumber)) {
+                                    savePhoneNumberInPrefs(newNumber);
+                                    // TODO: Remove this toast and just auto-send
+                                    // the message instead
+                                    UiUtils.showToast(
+                                            R.string
+                                        .toast_after_setting_default_sms_app_for_message_send);
+                                }
+                            }
+                });
+        return builder.create();
+    }
+
+    private void savePhoneNumberInPrefs(final String newPhoneNumber) {
+        final BuglePrefs subPrefs = BuglePrefs.getSubscriptionPrefs(mSubId);
+        subPrefs.putString(getString(R.string.mms_phone_number_pref_key),
+                newPhoneNumber);
+        // Update the self participants so the new phone number will be reflected
+        // everywhere in the UI.
+        ParticipantRefresh.refreshSelfParticipants();
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java b/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java
new file mode 100644
index 0000000..c869839
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.LaunchConversationData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Launches ConversationActivity for sending a message to, or viewing messages from, a specific
+ * recipient.
+ * <p>
+ * (This activity should be marked noHistory="true" in AndroidManifest.xml)
+ */
+public class LaunchConversationActivity extends Activity implements
+        LaunchConversationData.LaunchConversationDataListener {
+    private static final int MAX_RECIPIENT_LENGTH = 100;
+    static final String SMS_BODY = "sms_body";
+    static final String ADDRESS = "address";
+    final Binding<LaunchConversationData> mBinding = BindingBase.createBinding(this);
+    String mSmsBody;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (UiUtils.redirectToPermissionCheckIfNeeded(this)) {
+            return;
+        }
+
+        final Intent intent = getIntent();
+        final String action = intent.getAction();
+        if (Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) {
+            String[] recipients = null;
+            final String commaSeparatedRecipients =
+                    UriUtil.parseRecipientsFromSmsMmsUri(intent.getData());
+            if (commaSeparatedRecipients != null) {
+                recipients = commaSeparatedRecipients.split(",");
+            }
+            final boolean haveAddress = !TextUtils.isEmpty(intent.getStringExtra(ADDRESS));
+            final boolean haveEmail = !TextUtils.isEmpty(intent.getStringExtra(Intent.EXTRA_EMAIL));
+            if (recipients == null && (haveAddress || haveEmail)) {
+                if (haveAddress) {
+                    recipients = new String[] { intent.getStringExtra(ADDRESS) };
+                } else {
+                    recipients = new String[] { intent.getStringExtra(Intent.EXTRA_EMAIL) };
+                }
+            }
+            if (recipients != null) {
+                recipients = trimInvalidRecipients(recipients);
+            }
+            mSmsBody = intent.getStringExtra(SMS_BODY);
+            if (TextUtils.isEmpty(mSmsBody)) {
+                // Used by intents sent from the web YouTube (and perhaps others).
+                mSmsBody = getBody(intent.getData());
+                if (TextUtils.isEmpty(mSmsBody)) {
+                    // If that fails, try yet another method apps use to share text
+                    if (ContentType.TEXT_PLAIN.equals(intent.getType())) {
+                        mSmsBody = intent.getStringExtra(Intent.EXTRA_TEXT);
+                    }
+                }
+            }
+            if (recipients != null) {
+                mBinding.bind(DataModel.get().createLaunchConversationData(this));
+                mBinding.getData().getOrCreateConversation(mBinding, recipients);
+            } else {
+                // No recipients were specified in the intent.
+                // Start a new conversation with contact picker. The new conversation will be
+                // primed with the (optional) message in mSmsBody.
+                onGetOrCreateNewConversation(null);
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Unsupported conversation intent action : " + action);
+        }
+        // As of M, activities without a visible window must finish before onResume completes.
+        finish();
+    }
+
+    private String[] trimInvalidRecipients(String[] recipients) {
+        List<String> trimmedRecipients = new ArrayList<>();
+        for (String recipient : recipients) {
+            if (recipient.length() < MAX_RECIPIENT_LENGTH) {
+                trimmedRecipients.add(recipient);
+            }
+        }
+        if (trimmedRecipients.size() > 0) {
+            return trimmedRecipients.toArray(new String[0]);
+        } else {
+            return null;
+        }
+    }
+
+    private String getBody(final Uri uri) {
+        if (uri == null) {
+            return null;
+        }
+        String urlStr = uri.getSchemeSpecificPart();
+        if (!urlStr.contains("?")) {
+            return null;
+        }
+        urlStr = urlStr.substring(urlStr.indexOf('?') + 1);
+        final String[] params = urlStr.split("&");
+        for (final String p : params) {
+            if (p.startsWith("body=")) {
+                try {
+                    return URLDecoder.decode(p.substring(5), "UTF-8");
+                } catch (final UnsupportedEncodingException e) {
+                    // Invalid URL, ignore
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void onGetOrCreateNewConversation(final String conversationId) {
+        final Context context = Factory.get().getApplicationContext();
+        UIIntents.get().launchConversationActivityWithParentStack(context, conversationId,
+                mSmsBody);
+    }
+
+    @Override
+    public void onGetOrCreateNewConversationFailed() {
+        UiUtils.showToastAtBottom(R.string.conversation_creation_failure);
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/MessageBubbleBackground.java b/src/com/android/messaging/ui/conversation/MessageBubbleBackground.java
new file mode 100644
index 0000000..4c22970
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/MessageBubbleBackground.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import com.android.messaging.R;
+
+public class MessageBubbleBackground extends LinearLayout {
+    private final  int mSnapWidthPixels;
+
+    public MessageBubbleBackground(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mSnapWidthPixels = context.getResources().getDimensionPixelSize(
+                R.dimen.conversation_bubble_width_snap);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        final int widthPadding = getPaddingLeft() + getPaddingRight();
+        int bubbleWidth = getMeasuredWidth() - widthPadding;
+        final int maxWidth = MeasureSpec.getSize(widthMeasureSpec) - widthPadding;
+        // Round up to next snapWidthPixels
+        bubbleWidth = Math.min(maxWidth,
+                (int) (Math.ceil(bubbleWidth / (float) mSnapWidthPixels) * mSnapWidthPixels));
+        super.onMeasure(
+                MeasureSpec.makeMeasureSpec(bubbleWidth + widthPadding, MeasureSpec.EXACTLY),
+                heightMeasureSpec);
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/MessageDetailsDialog.java b/src/com/android/messaging/ui/conversation/MessageDetailsDialog.java
new file mode 100644
index 0000000..89b9148
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/MessageDetailsDialog.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.ConversationParticipantsData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.mmslib.pdu.PduHeaders;
+import com.android.messaging.sms.DatabaseMessages.MmsMessage;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.SafeAsyncTask;
+
+import java.util.List;
+
+public class MessageDetailsDialog {
+    private static final String RECIPIENT_SEPARATOR = ", ";
+
+    // All methods are static, no creating this class
+    private MessageDetailsDialog() {
+    }
+
+    public static void show(final Context context, final ConversationMessageData data,
+            final ConversationParticipantsData participants, final ParticipantData self) {
+        if (DebugUtils.isDebugEnabled()) {
+            new SafeAsyncTask<Void, Void, String>() {
+                @Override
+                protected String doInBackgroundTimed(Void... params) {
+                    return getMessageDetails(context, data, participants, self);
+                }
+
+                @Override
+                protected void onPostExecute(String messageDetails) {
+                    showDialog(context, messageDetails);
+                }
+            }.executeOnThreadPool(null, null, null);
+        } else {
+            String messageDetails = getMessageDetails(context, data, participants, self);
+            showDialog(context, messageDetails);
+        }
+    }
+
+    private static String getMessageDetails(final Context context,
+            final ConversationMessageData data,
+            final ConversationParticipantsData participants, final ParticipantData self) {
+        String messageDetails = null;
+        if (data.getIsSms()) {
+            messageDetails = getSmsMessageDetails(data, participants, self);
+        } else {
+            // TODO: Handle SMS_TYPE_MMS_PUSH_NOTIFICATION type differently?
+            messageDetails = getMmsMessageDetails(context, data, participants, self);
+        }
+
+        return messageDetails;
+    }
+
+    private static void showDialog(final Context context, String messageDetails) {
+        if (!TextUtils.isEmpty(messageDetails)) {
+            new AlertDialog.Builder(context)
+                    .setTitle(R.string.message_details_title)
+                    .setMessage(messageDetails)
+                    .setCancelable(true)
+                    .show();
+        }
+    }
+
+    /**
+     * Return a string, separated by newlines, that contains a number of labels and values
+     * for this sms message. The string will be displayed in a modal dialog.
+     * @return string list of various message properties
+     */
+    private static String getSmsMessageDetails(final ConversationMessageData data,
+            final ConversationParticipantsData participants, final ParticipantData self) {
+        final Resources res = Factory.get().getApplicationContext().getResources();
+        final StringBuilder details = new StringBuilder();
+
+        // Type: Text message
+        details.append(res.getString(R.string.message_type_label));
+        details.append(res.getString(R.string.text_message));
+
+        // From: +1425xxxxxxx
+        // or To: +1425xxxxxxx
+        final String rawSender = data.getSenderNormalizedDestination();
+        if (!TextUtils.isEmpty(rawSender)) {
+            details.append('\n');
+            details.append(res.getString(R.string.from_label));
+            details.append(rawSender);
+        }
+        final String rawRecipients = getRecipientParticipantString(participants,
+                data.getParticipantId(), data.getIsIncoming(), data.getSelfParticipantId());
+        if (!TextUtils.isEmpty(rawRecipients)) {
+            details.append('\n');
+            details.append(res.getString(R.string.to_address_label));
+            details.append(rawRecipients);
+        }
+
+        // Sent: Mon 11:42AM
+        if (data.getIsIncoming()) {
+            if (data.getSentTimeStamp() != MmsUtils.INVALID_TIMESTAMP) {
+                details.append('\n');
+                details.append(res.getString(R.string.sent_label));
+                details.append(
+                        Dates.getMessageDetailsTimeString(data.getSentTimeStamp()).toString());
+            }
+        }
+
+        // Sent: Mon 11:43AM
+        // or Received: Mon 11:43AM
+        appendSentOrReceivedTimestamp(res, details, data);
+
+        appendSimInfo(res, self, details);
+
+        if (DebugUtils.isDebugEnabled()) {
+            appendDebugInfo(details, data);
+        }
+
+        return details.toString();
+    }
+
+    /**
+     * Return a string, separated by newlines, that contains a number of labels and values
+     * for this mms message. The string will be displayed in a modal dialog.
+     * @return string list of various message properties
+     */
+    private static String getMmsMessageDetails(Context context, final ConversationMessageData data,
+            final ConversationParticipantsData participants, final ParticipantData self) {
+        final Resources res = Factory.get().getApplicationContext().getResources();
+        // TODO: when we support non-auto-download of mms messages, we'll have to handle
+        // the case when the message is a PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND and display
+        // something different. See the Messaging app's MessageUtils.getNotificationIndDetails()
+
+        final StringBuilder details = new StringBuilder();
+
+        // Type: Multimedia message.
+        details.append(res.getString(R.string.message_type_label));
+        details.append(res.getString(R.string.multimedia_message));
+
+        // From: +1425xxxxxxx
+        final String rawSender = data.getSenderNormalizedDestination();
+        details.append('\n');
+        details.append(res.getString(R.string.from_label));
+        details.append(!TextUtils.isEmpty(rawSender) ? rawSender :
+                res.getString(R.string.hidden_sender_address));
+
+        // To: +1425xxxxxxx
+        final String rawRecipients = getRecipientParticipantString(participants,
+                data.getParticipantId(), data.getIsIncoming(), data.getSelfParticipantId());
+        if (!TextUtils.isEmpty(rawRecipients)) {
+            details.append('\n');
+            details.append(res.getString(R.string.to_address_label));
+            details.append(rawRecipients);
+        }
+
+        // Sent: Tue 3:05PM
+        // or Received: Tue 3:05PM
+        appendSentOrReceivedTimestamp(res, details, data);
+
+        // Subject: You're awesome
+        details.append('\n');
+        details.append(res.getString(R.string.subject_label));
+        if (!TextUtils.isEmpty(MmsUtils.cleanseMmsSubject(res, data.getMmsSubject()))) {
+            details.append(data.getMmsSubject());
+        }
+
+        // Priority: High/Normal/Low
+        details.append('\n');
+        details.append(res.getString(R.string.priority_label));
+        details.append(getPriorityDescription(res, data.getSmsPriority()));
+
+        // Message size: 30 KB
+        if (data.getSmsMessageSize() > 0) {
+            details.append('\n');
+            details.append(res.getString(R.string.message_size_label));
+            details.append(Formatter.formatFileSize(context, data.getSmsMessageSize()));
+        }
+
+        appendSimInfo(res, self, details);
+
+        if (DebugUtils.isDebugEnabled()) {
+            appendDebugInfo(details, data);
+        }
+
+        return details.toString();
+    }
+
+    private static void appendSentOrReceivedTimestamp(Resources res, StringBuilder details,
+            ConversationMessageData data) {
+        int labelId = -1;
+        if (data.getIsIncoming()) {
+            labelId = R.string.received_label;
+        } else if (data.getIsSendComplete()) {
+            labelId = R.string.sent_label;
+        }
+        if (labelId >= 0) {
+            details.append('\n');
+            details.append(res.getString(labelId));
+            details.append(
+                    Dates.getMessageDetailsTimeString(data.getReceivedTimeStamp()).toString());
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    private static void appendDebugInfo(StringBuilder details, ConversationMessageData data) {
+        // We grab the thread id from the database, so this needs to run in the background
+        Assert.isNotMainThread();
+        details.append("\n\n");
+        details.append("DEBUG");
+
+        details.append('\n');
+        details.append("Message id: ");
+        details.append(data.getMessageId());
+
+        final String telephonyUri = data.getSmsMessageUri();
+        details.append('\n');
+        details.append("Telephony uri: ");
+        details.append(telephonyUri);
+
+        final String conversationId = data.getConversationId();
+
+        if (conversationId == null) {
+            return;
+        }
+
+        details.append('\n');
+        details.append("Conversation id: ");
+        details.append(conversationId);
+
+        final long threadId = BugleDatabaseOperations.getThreadId(DataModel.get().getDatabase(),
+                conversationId);
+
+        details.append('\n');
+        details.append("Conversation telephony thread id: ");
+        details.append(threadId);
+
+        MmsMessage mms = null;
+
+        if (data.getIsMms()) {
+            if (telephonyUri == null) {
+                return;
+            }
+            mms = MmsUtils.loadMms(Uri.parse(telephonyUri));
+            if (mms == null) {
+                return;
+            }
+
+            // We log the thread id again to check that they are internally consistent
+            final long mmsThreadId = mms.mThreadId;
+            details.append('\n');
+            details.append("Telephony thread id: ");
+            details.append(mmsThreadId);
+
+            // Log the MMS content location
+            final String mmsContentLocation = mms.mContentLocation;
+            details.append('\n');
+            details.append("Content location URL: ");
+            details.append(mmsContentLocation);
+        }
+
+        final String recipientsString = MmsUtils.getRawRecipientIdsForThread(threadId);
+        if (recipientsString != null) {
+            details.append('\n');
+            details.append("Thread recipient ids: ");
+            details.append(recipientsString);
+        }
+
+        final List<String> recipients = MmsUtils.getRecipientsByThread(threadId);
+        if (recipients != null) {
+            details.append('\n');
+            details.append("Thread recipients: ");
+            details.append(recipients.toString());
+
+            if (mms != null) {
+                final String from = MmsUtils.getMmsSender(recipients, mms.getUri());
+                details.append('\n');
+                details.append("Sender: ");
+                details.append(from);
+            }
+        }
+    }
+
+    private static String getRecipientParticipantString(
+            final ConversationParticipantsData participants, final String senderId,
+            final boolean addSelf, final String selfId) {
+        final StringBuilder recipients = new StringBuilder();
+        for (final ParticipantData participant : participants) {
+            if (TextUtils.equals(participant.getId(), senderId)) {
+                // Don't add sender
+                continue;
+            }
+            if (participant.isSelf() &&
+                    (!participant.getId().equals(selfId) || !addSelf)) {
+                // For self participants, don't add the one that's not relevant to this message
+                // or if we are asked not to add self
+                continue;
+            }
+            final String phoneNumber = participant.getNormalizedDestination();
+            // Don't add empty number. This should not happen. But if that happens
+            // we should not add it.
+            if (!TextUtils.isEmpty(phoneNumber)) {
+                if (recipients.length() > 0) {
+                    recipients.append(RECIPIENT_SEPARATOR);
+                }
+                recipients.append(phoneNumber);
+            }
+        }
+        return recipients.toString();
+    }
+
+    /**
+     * Convert the numeric mms priority into a human-readable string
+     * @param res
+     * @param priorityValue coded PduHeader priority
+     * @return string representation of the priority
+     */
+    private static String getPriorityDescription(final Resources res, final int priorityValue) {
+        switch(priorityValue) {
+            case PduHeaders.PRIORITY_HIGH:
+                return res.getString(R.string.priority_high);
+            case PduHeaders.PRIORITY_LOW:
+                return res.getString(R.string.priority_low);
+            case PduHeaders.PRIORITY_NORMAL:
+            default:
+                return res.getString(R.string.priority_normal);
+        }
+    }
+
+    private static void appendSimInfo(final Resources res,
+            final ParticipantData self, final StringBuilder outString) {
+        if (!OsUtil.isAtLeastL_MR1()
+                || self == null
+                || PhoneUtils.getDefault().getActiveSubscriptionCount() < 2) {
+            return;
+        }
+        // The appended SIM info would look like:
+        // SIM: SUB 01
+        // or SIM: SIM 1
+        // or SIM: Unknown
+        Assert.isTrue(self.isSelf());
+        outString.append('\n');
+        outString.append(res.getString(R.string.sim_label));
+        if (self.isActiveSubscription() && !self.isDefaultSelf()) {
+            final String subscriptionName = self.getSubscriptionName();
+            if (TextUtils.isEmpty(subscriptionName)) {
+                outString.append(res.getString(R.string.sim_slot_identifier,
+                        self.getDisplaySlotId()));
+            } else {
+                outString.append(subscriptionName);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/SimIconView.java b/src/com/android/messaging/ui/conversation/SimIconView.java
new file mode 100644
index 0000000..6799bad
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/SimIconView.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.graphics.Outline;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Shows SIM avatar icon in the SIM switcher / Self-send button.
+ */
+public class SimIconView extends ContactIconView {
+    public SimIconView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        if (OsUtil.isAtLeastL()) {
+            setOutlineProvider(new ViewOutlineProvider() {
+                @Override
+                public void getOutline(View v, Outline outline) {
+                    outline.setOval(0, 0, v.getWidth(), v.getHeight());
+                }
+            });
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (isClickable()) {
+            return super.onTouchEvent(event);
+        }
+        return true;
+    }
+
+    @Override
+    protected void maybeInitializeOnClickListener() {
+        // TODO: SIM icon view shouldn't consume or handle clicks, but it should if
+        // this is the send button for the only SIM in the device or if MSIM is not supported.
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/SimSelectorItemView.java b/src/com/android/messaging/ui/conversation/SimSelectorItemView.java
new file mode 100644
index 0000000..3058d31
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/SimSelectorItemView.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.util.Assert;
+
+/**
+ * Shows a view for a SIM in the SIM selector.
+ */
+public class SimSelectorItemView extends LinearLayout {
+    public interface HostInterface {
+        void onSimItemClicked(SubscriptionListEntry item);
+    }
+
+    private SubscriptionListEntry mData;
+    private TextView mNameTextView;
+    private TextView mDetailsTextView;
+    private SimIconView mSimIconView;
+    private HostInterface mHost;
+
+    public SimSelectorItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mNameTextView = (TextView) findViewById(R.id.name);
+        mDetailsTextView = (TextView) findViewById(R.id.details);
+        mSimIconView = (SimIconView) findViewById(R.id.sim_icon);
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mHost.onSimItemClicked(mData);
+            }
+        });
+    }
+
+    public void bind(final SubscriptionListEntry simEntry) {
+        Assert.notNull(simEntry);
+        mData = simEntry;
+        updateViewAppearance();
+    }
+
+    public void setHostInterface(final HostInterface host) {
+        mHost = host;
+    }
+
+    private void updateViewAppearance() {
+        Assert.notNull(mData);
+        final String displayName = mData.displayName;
+        if (TextUtils.isEmpty(displayName)) {
+            mNameTextView.setVisibility(GONE);
+        } else {
+            mNameTextView.setVisibility(VISIBLE);
+            mNameTextView.setText(displayName);
+        }
+
+        final String details = mData.displayDestination;
+        if (TextUtils.isEmpty(details)) {
+            mDetailsTextView.setVisibility(GONE);
+        } else {
+            mDetailsTextView.setVisibility(VISIBLE);
+            mDetailsTextView.setText(details);
+        }
+
+        mSimIconView.setImageResourceUri(mData.iconUri);
+    }
+}
diff --git a/src/com/android/messaging/ui/conversation/SimSelectorView.java b/src/com/android/messaging/ui/conversation/SimSelectorView.java
new file mode 100644
index 0000000..b07ff19
--- /dev/null
+++ b/src/com/android/messaging/ui/conversation/SimSelectorView.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.ListView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays a SIM selector above the compose message view and overlays the message list.
+ */
+public class SimSelectorView extends FrameLayout implements SimSelectorItemView.HostInterface {
+    public interface SimSelectorViewListener {
+        void onSimItemClicked(SubscriptionListEntry item);
+        void onSimSelectorVisibilityChanged(boolean visible);
+    }
+
+    private ListView mSimListView;
+    private final SimSelectorAdapter mAdapter;
+    private boolean mShow;
+    private SimSelectorViewListener mListener;
+    private int mItemLayoutId;
+
+    public SimSelectorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mAdapter = new SimSelectorAdapter(getContext());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSimListView = (ListView) findViewById(R.id.sim_list);
+        mSimListView.setAdapter(mAdapter);
+
+        // Clicking anywhere outside the switcher list should dismiss.
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showOrHide(false, true);
+            }
+        });
+    }
+
+    public void bind(final SubscriptionListData data) {
+        mAdapter.bindData(data.getActiveSubscriptionEntriesExcludingDefault());
+    }
+
+    public void setItemLayoutId(final int layoutId) {
+        mItemLayoutId = layoutId;
+    }
+
+    public void setListener(final SimSelectorViewListener listener) {
+        mListener = listener;
+    }
+
+    public void toggleVisibility() {
+        showOrHide(!mShow, true);
+    }
+
+    public void showOrHide(final boolean show, final boolean animate) {
+        final boolean oldShow = mShow;
+        mShow = show && mAdapter.getCount() > 1;
+        if (oldShow != mShow) {
+            if (mListener != null) {
+                mListener.onSimSelectorVisibilityChanged(mShow);
+            }
+
+            if (animate) {
+                // Fade in the background pane.
+                setVisibility(VISIBLE);
+                setAlpha(mShow ? 0.0f : 1.0f);
+                animate().alpha(mShow ? 1.0f : 0.0f)
+                    .setDuration(UiUtils.REVEAL_ANIMATION_DURATION)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            setAlpha(1.0f);
+                            setVisibility(mShow ? VISIBLE : GONE);
+                        }
+                    });
+            } else {
+                setVisibility(mShow ? VISIBLE : GONE);
+            }
+
+            // Slide in the SIM selector list via a translate animation.
+            mSimListView.setVisibility(mShow ? VISIBLE : GONE);
+            if (animate) {
+                mSimListView.clearAnimation();
+                final TranslateAnimation translateAnimation = new TranslateAnimation(
+                        Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
+                        Animation.RELATIVE_TO_SELF, mShow ? 1.0f : 0.0f,
+                        Animation.RELATIVE_TO_SELF, mShow ? 0.0f : 1.0f);
+                translateAnimation.setInterpolator(UiUtils.EASE_OUT_INTERPOLATOR);
+                translateAnimation.setDuration(UiUtils.REVEAL_ANIMATION_DURATION);
+                mSimListView.startAnimation(translateAnimation);
+            }
+        }
+    }
+
+    /**
+     * An adapter that takes a list of SubscriptionListEntry and displays them as a list of
+     * available SIMs in the SIM selector.
+     */
+    private class SimSelectorAdapter extends ArrayAdapter<SubscriptionListEntry> {
+        public SimSelectorAdapter(final Context context) {
+            super(context, R.layout.sim_selector_item_view, new ArrayList<SubscriptionListEntry>());
+        }
+
+        public void bindData(final List<SubscriptionListEntry> newList) {
+            clear();
+            addAll(newList);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public View getView(final int position, final View convertView, final ViewGroup parent) {
+            SimSelectorItemView itemView;
+            if (convertView != null && convertView instanceof SimSelectorItemView) {
+                itemView = (SimSelectorItemView) convertView;
+            } else {
+                final LayoutInflater inflater = (LayoutInflater) getContext()
+                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                itemView = (SimSelectorItemView) inflater.inflate(mItemLayoutId,
+                        parent, false);
+                itemView.setHostInterface(SimSelectorView.this);
+            }
+            itemView.bind(getItem(position));
+            return itemView;
+        }
+    }
+
+    @Override
+    public void onSimItemClicked(SubscriptionListEntry item) {
+        mListener.onSimItemClicked(item);
+        showOrHide(false, true);
+    }
+
+    public boolean isOpen() {
+        return mShow;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/AbstractConversationListActivity.java b/src/com/android/messaging/ui/conversationlist/AbstractConversationListActivity.java
new file mode 100644
index 0000000..a2b0bdf
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/AbstractConversationListActivity.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.action.DeleteConversationAction;
+import com.android.messaging.datamodel.action.UpdateConversationArchiveStatusAction;
+import com.android.messaging.datamodel.action.UpdateConversationOptionsAction;
+import com.android.messaging.datamodel.action.UpdateDestinationBlockedAction;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.SnackBar;
+import com.android.messaging.ui.SnackBarInteraction;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.contact.AddContactsConfirmationDialog;
+import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
+import com.android.messaging.ui.conversationlist.MultiSelectActionModeCallback.SelectedConversation;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.Trace;
+import com.android.messaging.util.UiUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Base class for many Conversation List activities. This will handle the common actions of multi
+ * select and common launching of intents.
+ */
+public abstract class AbstractConversationListActivity  extends BugleActionBarActivity
+    implements ConversationListFragmentHost, MultiSelectActionModeCallback.Listener {
+
+    private static final int REQUEST_SET_DEFAULT_SMS_APP = 1;
+
+    protected ConversationListFragment mConversationListFragment;
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        Trace.beginSection("AbstractConversationListActivity.onAttachFragment");
+        // Fragment could be debug dialog
+        if (fragment instanceof ConversationListFragment) {
+            mConversationListFragment = (ConversationListFragment) fragment;
+            mConversationListFragment.setHost(this);
+        }
+        Trace.endSection();
+    }
+
+    @Override
+    public void onBackPressed() {
+        // If action mode is active dismiss it
+        if (getActionMode() != null) {
+            dismissActionMode();
+            return;
+        }
+        super.onBackPressed();
+    }
+
+    protected void startMultiSelectActionMode() {
+        startActionMode(new MultiSelectActionModeCallback(this));
+    }
+
+    protected void exitMultiSelectState() {
+        mConversationListFragment.showFab();
+        dismissActionMode();
+        mConversationListFragment.updateUi();
+    }
+
+    protected boolean isInConversationListSelectMode() {
+        return getActionModeCallback() instanceof MultiSelectActionModeCallback;
+    }
+
+    @Override
+    public boolean isSelectionMode() {
+        return isInConversationListSelectMode();
+    }
+
+    @SuppressWarnings("MissingSuperCall") // TODO: fix me
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+    }
+
+    @Override
+    public void onActionBarDelete(final Collection<SelectedConversation> conversations) {
+        if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
+            // TODO: figure out a good way to combine this with the implementation in
+            // ConversationFragment doing similar things
+            final Activity activity = this;
+            UiUtils.showSnackBarWithCustomAction(this,
+                    getWindow().getDecorView().getRootView(),
+                    getString(R.string.requires_default_sms_app),
+                    SnackBar.Action.createCustomAction(new Runnable() {
+                            @Override
+                            public void run() {
+                                final Intent intent =
+                                        UIIntents.get().getChangeDefaultSmsAppIntent(activity);
+                                startActivityForResult(intent, REQUEST_SET_DEFAULT_SMS_APP);
+                            }
+                        },
+                        getString(R.string.requires_default_sms_change_button)),
+                    null /* interactions */,
+                    null /* placement */);
+            return;
+        }
+
+        new AlertDialog.Builder(this)
+                .setTitle(getResources().getQuantityString(
+                        R.plurals.delete_conversations_confirmation_dialog_title,
+                        conversations.size()))
+                .setPositiveButton(R.string.delete_conversation_confirmation_button,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(final DialogInterface dialog,
+                                    final int button) {
+                                for (final SelectedConversation conversation : conversations) {
+                                    DeleteConversationAction.deleteConversation(
+                                            conversation.conversationId,
+                                            conversation.timestamp);
+                                }
+                                exitMultiSelectState();
+                            }
+                })
+                .setNegativeButton(R.string.delete_conversation_decline_button, null)
+                .show();
+    }
+
+    @Override
+    public void onActionBarArchive(final Iterable<SelectedConversation> conversations,
+            final boolean isToArchive) {
+        final ArrayList<String> conversationIds = new ArrayList<String>();
+        for (final SelectedConversation conversation : conversations) {
+            final String conversationId = conversation.conversationId;
+            conversationIds.add(conversationId);
+            if (isToArchive) {
+                UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
+            } else {
+                UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
+            }
+        }
+
+        final Runnable undoRunnable = new Runnable() {
+            @Override
+            public void run() {
+                for (final String conversationId : conversationIds) {
+                    if (isToArchive) {
+                        UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
+                    } else {
+                        UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
+                    }
+                }
+            }
+        };
+
+        final int textId =
+                isToArchive ? R.string.archived_toast_message : R.string.unarchived_toast_message;
+        final String message = getResources().getString(textId, conversationIds.size());
+        UiUtils.showSnackBar(this, findViewById(android.R.id.list), message, undoRunnable,
+                SnackBar.Action.SNACK_BAR_UNDO,
+                mConversationListFragment.getSnackBarInteractions());
+        exitMultiSelectState();
+    }
+
+    @Override
+    public void onActionBarNotification(final Iterable<SelectedConversation> conversations,
+            final boolean isNotificationOn) {
+        for (final SelectedConversation conversation : conversations) {
+            UpdateConversationOptionsAction.enableConversationNotifications(
+                    conversation.conversationId, isNotificationOn);
+        }
+
+        final int textId = isNotificationOn ?
+                R.string.notification_on_toast_message : R.string.notification_off_toast_message;
+        final String message = getResources().getString(textId, 1);
+        UiUtils.showSnackBar(this, findViewById(android.R.id.list), message,
+            null /* undoRunnable */,
+            SnackBar.Action.SNACK_BAR_UNDO, mConversationListFragment.getSnackBarInteractions());
+        exitMultiSelectState();
+    }
+
+    @Override
+    public void onActionBarAddContact(final SelectedConversation conversation) {
+        final Uri avatarUri;
+        if (conversation.icon != null) {
+            avatarUri = Uri.parse(conversation.icon);
+        } else {
+            avatarUri = null;
+        }
+        final AddContactsConfirmationDialog dialog = new AddContactsConfirmationDialog(
+                this, avatarUri, conversation.otherParticipantNormalizedDestination);
+        dialog.show();
+        exitMultiSelectState();
+    }
+
+    @Override
+    public void onActionBarBlock(final SelectedConversation conversation) {
+        final Resources res = getResources();
+        new AlertDialog.Builder(this)
+                .setTitle(res.getString(R.string.block_confirmation_title,
+                        conversation.otherParticipantNormalizedDestination))
+                .setMessage(res.getString(R.string.block_confirmation_message))
+                .setNegativeButton(android.R.string.cancel, null)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(final DialogInterface arg0, final int arg1) {
+                        final Context context = AbstractConversationListActivity.this;
+                        final View listView = findViewById(android.R.id.list);
+                        final List<SnackBarInteraction> interactions =
+                                mConversationListFragment.getSnackBarInteractions();
+                        final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
+                                undoListener =
+                                        new UpdateDestinationBlockedActionSnackBar(
+                                                context, listView, null /* undoRunnable */,
+                                                interactions);
+                        final Runnable undoRunnable = new Runnable() {
+                            @Override
+                            public void run() {
+                                UpdateDestinationBlockedAction.updateDestinationBlocked(
+                                        conversation.otherParticipantNormalizedDestination, false,
+                                        conversation.conversationId,
+                                        undoListener);
+                            }
+                        };
+                        final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
+                              listener = new UpdateDestinationBlockedActionSnackBar(
+                                      context, listView, undoRunnable, interactions);
+                        UpdateDestinationBlockedAction.updateDestinationBlocked(
+                                conversation.otherParticipantNormalizedDestination, true,
+                                conversation.conversationId,
+                                listener);
+                        exitMultiSelectState();
+                    }
+                })
+                .create()
+                .show();
+    }
+
+    @Override
+    public void onConversationClick(final ConversationListData listData,
+                                    final ConversationListItemData conversationListItemData,
+                                    final boolean isLongClick,
+                                    final ConversationListItemView conversationView) {
+        if (isLongClick && !isInConversationListSelectMode()) {
+            startMultiSelectActionMode();
+        }
+
+        if (isInConversationListSelectMode()) {
+            final MultiSelectActionModeCallback multiSelectActionMode =
+                    (MultiSelectActionModeCallback) getActionModeCallback();
+            multiSelectActionMode.toggleSelect(listData, conversationListItemData);
+            mConversationListFragment.updateUi();
+        } else {
+            final String conversationId = conversationListItemData.getConversationId();
+            Bundle sceneTransitionAnimationOptions = null;
+            boolean hasCustomTransitions = false;
+
+            UIIntents.get().launchConversationActivity(
+                    this, conversationId, null,
+                    sceneTransitionAnimationOptions,
+                    hasCustomTransitions);
+        }
+    }
+
+    @Override
+    public void onCreateConversationClick() {
+        UIIntents.get().launchCreateNewConversationActivity(this, null);
+    }
+
+
+    @Override
+    public boolean isConversationSelected(final String conversationId) {
+        return isInConversationListSelectMode() &&
+                ((MultiSelectActionModeCallback) getActionModeCallback()).isSelected(
+                        conversationId);
+    }
+
+    public void onActionBarDebug() {
+        DebugUtils.showDebugOptions(this);
+    }
+
+    private static class UpdateDestinationBlockedActionSnackBar
+            implements UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener {
+        private final Context mContext;
+        private final View mParentView;
+        private final Runnable mUndoRunnable;
+        private final List<SnackBarInteraction> mInteractions;
+
+        UpdateDestinationBlockedActionSnackBar(final Context context,
+                @NonNull final View parentView, @Nullable final Runnable undoRunnable,
+                @Nullable List<SnackBarInteraction> interactions) {
+            mContext = context;
+            mParentView = parentView;
+            mUndoRunnable = undoRunnable;
+            mInteractions = interactions;
+        }
+
+        @Override
+        public void onUpdateDestinationBlockedAction(
+            final UpdateDestinationBlockedAction action,
+            final boolean success, final boolean block,
+            final String destination) {
+            if (success) {
+                final int messageId = block ? R.string.blocked_toast_message
+                        : R.string.unblocked_toast_message;
+                final String message = mContext.getResources().getString(messageId, 1);
+                UiUtils.showSnackBar(mContext, mParentView, message, mUndoRunnable,
+                        SnackBar.Action.SNACK_BAR_UNDO, mInteractions);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ArchivedConversationListActivity.java b/src/com/android/messaging/ui/conversationlist/ArchivedConversationListActivity.java
new file mode 100644
index 0000000..342c970
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ArchivedConversationListActivity.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.util.DebugUtils;
+
+public class ArchivedConversationListActivity extends AbstractConversationListActivity {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final ConversationListFragment fragment =
+                ConversationListFragment.createArchivedConversationListFragment();
+        getFragmentManager().beginTransaction().add(android.R.id.content, fragment).commit();
+        invalidateActionBar();
+    }
+
+    protected void updateActionBar(ActionBar actionBar) {
+        actionBar.setTitle(getString(R.string.archived_activity_title));
+        actionBar.setDisplayShowTitleEnabled(true);
+        actionBar.setDisplayHomeAsUpEnabled(true);
+        actionBar.setBackgroundDrawable(new ColorDrawable(
+                getResources().getColor(
+                        R.color.archived_conversation_action_bar_background_color_dark)));
+        actionBar.show();
+        super.updateActionBar(actionBar);
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (isInConversationListSelectMode()) {
+            exitMultiSelectState();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (super.onCreateOptionsMenu(menu)) {
+            return true;
+        }
+        getMenuInflater().inflate(R.menu.archived_conversation_list_menu, menu);
+        final MenuItem item = menu.findItem(R.id.action_debug_options);
+        if (item != null) {
+            final boolean enableDebugItems = DebugUtils.isDebugEnabled();
+            item.setVisible(enableDebugItems).setEnabled(enableDebugItems);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem menuItem) {
+        switch(menuItem.getItemId()) {
+            case R.id.action_debug_options:
+                onActionBarDebug();
+                return true;
+            case android.R.id.home:
+                onActionBarHome();
+                return true;
+            default:
+                return super.onOptionsItemSelected(menuItem);
+        }
+    }
+
+    @Override
+    public void onActionBarHome() {
+        onBackPressed();
+    }
+
+    @Override
+    public boolean isSwipeAnimatable() {
+        return false;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListActivity.java b/src/com/android/messaging/ui/conversationlist/ConversationListActivity.java
new file mode 100644
index 0000000..636b0f5
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListActivity.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.Trace;
+
+public class ConversationListActivity extends AbstractConversationListActivity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        Trace.beginSection("ConversationListActivity.onCreate");
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.conversation_list_activity);
+        Trace.endSection();
+        invalidateActionBar();
+    }
+
+    @Override
+    protected void updateActionBar(final ActionBar actionBar) {
+        actionBar.setTitle(getString(R.string.app_name));
+        actionBar.setDisplayShowTitleEnabled(true);
+        actionBar.setDisplayHomeAsUpEnabled(false);
+        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+        actionBar.setBackgroundDrawable(new ColorDrawable(
+                getResources().getColor(R.color.action_bar_background_color)));
+        actionBar.show();
+        super.updateActionBar(actionBar);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // Invalidate the menu as items that are based on settings may have changed
+        // while not in the app (e.g. Talkback enabled/disable affects new conversation
+        // button)
+        supportInvalidateOptionsMenu();
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (isInConversationListSelectMode()) {
+            exitMultiSelectState();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        if (super.onCreateOptionsMenu(menu)) {
+            return true;
+        }
+        getMenuInflater().inflate(R.menu.conversation_list_fragment_menu, menu);
+        final MenuItem item = menu.findItem(R.id.action_debug_options);
+        if (item != null) {
+            final boolean enableDebugItems = DebugUtils.isDebugEnabled();
+            item.setVisible(enableDebugItems).setEnabled(enableDebugItems);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem menuItem) {
+        switch(menuItem.getItemId()) {
+            case R.id.action_start_new_conversation:
+                onActionBarStartNewConversation();
+                return true;
+            case R.id.action_settings:
+                onActionBarSettings();
+                return true;
+            case R.id.action_debug_options:
+                onActionBarDebug();
+                return true;
+            case R.id.action_show_archived:
+                onActionBarArchived();
+                return true;
+            case R.id.action_show_blocked_contacts:
+                onActionBarBlockedParticipants();
+                return true;
+        }
+        return super.onOptionsItemSelected(menuItem);
+    }
+
+    @Override
+    public void onActionBarHome() {
+        exitMultiSelectState();
+    }
+
+    public void onActionBarStartNewConversation() {
+        UIIntents.get().launchCreateNewConversationActivity(this, null);
+    }
+
+    public void onActionBarSettings() {
+        UIIntents.get().launchSettingsActivity(this);
+    }
+
+    public void onActionBarBlockedParticipants() {
+        UIIntents.get().launchBlockedParticipantsActivity(this);
+    }
+
+    public void onActionBarArchived() {
+        UIIntents.get().launchArchivedConversationsActivity(this);
+    }
+
+    @Override
+    public boolean isSwipeAnimatable() {
+        return !isInConversationListSelectMode();
+    }
+
+    @Override
+    public void onWindowFocusChanged(final boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        final ConversationListFragment conversationListFragment =
+                (ConversationListFragment) getFragmentManager().findFragmentById(
+                        R.id.conversation_list_fragment);
+        // When the screen is turned on, the last used activity gets resumed, but it gets
+        // window focus only after the lock screen is unlocked.
+        if (hasFocus && conversationListFragment != null) {
+            conversationListFragment.setScrolledToNewestConversationIfNeeded();
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListAdapter.java b/src/com/android/messaging/ui/conversationlist/ConversationListAdapter.java
new file mode 100644
index 0000000..fc687eb
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListAdapter.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.content.Context;
+import android.database.Cursor;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.CursorRecyclerAdapter;
+import com.android.messaging.ui.conversationlist.ConversationListItemView.HostInterface;
+
+/**
+ * Provides an interface to expose Conversation List Cursor data to a UI widget like a ListView.
+ */
+public class ConversationListAdapter
+        extends CursorRecyclerAdapter<ConversationListAdapter.ConversationListViewHolder> {
+
+    private final ConversationListItemView.HostInterface mClivHostInterface;
+
+    public ConversationListAdapter(final Context context, final Cursor cursor,
+            final ConversationListItemView.HostInterface clivHostInterface) {
+        super(context, cursor, 0);
+        mClivHostInterface = clivHostInterface;
+        setHasStableIds(true);
+    }
+
+    /**
+     * @see com.android.messaging.ui.CursorRecyclerAdapter#bindViewHolder(
+     * androidx.recyclerview.widget.RecyclerView.ViewHolder, android.content.Context,
+     * android.database.Cursor)
+     */
+    @Override
+    public void bindViewHolder(final ConversationListViewHolder holder, final Context context,
+            final Cursor cursor) {
+        final ConversationListItemView conversationListItemView = holder.mView;
+        conversationListItemView.bind(cursor, mClivHostInterface);
+    }
+
+    @Override
+    public ConversationListViewHolder createViewHolder(final Context context,
+            final ViewGroup parent, final int viewType) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(context);
+        final ConversationListItemView itemView =
+                (ConversationListItemView) layoutInflater.inflate(
+                        R.layout.conversation_list_item_view, null);
+        return new ConversationListViewHolder(itemView);
+    }
+
+    /**
+     * ViewHolder that holds a ConversationListItemView.
+     */
+    public static class ConversationListViewHolder extends RecyclerView.ViewHolder {
+        final ConversationListItemView mView;
+
+        public ConversationListViewHolder(final ConversationListItemView itemView) {
+            super(itemView);
+            mView = itemView;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListFragment.java b/src/com/android/messaging/ui/conversationlist/ConversationListFragment.java
new file mode 100644
index 0000000..269efcb
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListFragment.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.ViewGroupCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.ViewPropertyAnimator;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.AbsListView;
+import android.widget.ImageView;
+
+import com.android.messaging.R;
+import com.android.messaging.annotation.VisibleForAnimation;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.ui.BugleAnimationTags;
+import com.android.messaging.ui.ListEmptyView;
+import com.android.messaging.ui.SnackBarInteraction;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Shows a list of conversations.
+ */
+public class ConversationListFragment extends Fragment implements ConversationListDataListener,
+        ConversationListItemView.HostInterface {
+    private static final String BUNDLE_ARCHIVED_MODE = "archived_mode";
+    private static final String BUNDLE_FORWARD_MESSAGE_MODE = "forward_message_mode";
+    private static final boolean VERBOSE = false;
+
+    private MenuItem mShowBlockedMenuItem;
+    private boolean mArchiveMode;
+    private boolean mBlockedAvailable;
+    private boolean mForwardMessageMode;
+
+    public interface ConversationListFragmentHost {
+        public void onConversationClick(final ConversationListData listData,
+                                        final ConversationListItemData conversationListItemData,
+                                        final boolean isLongClick,
+                                        final ConversationListItemView conversationView);
+        public void onCreateConversationClick();
+        public boolean isConversationSelected(final String conversationId);
+        public boolean isSwipeAnimatable();
+        public boolean isSelectionMode();
+        public boolean hasWindowFocus();
+    }
+
+    private ConversationListFragmentHost mHost;
+    private RecyclerView mRecyclerView;
+    private ImageView mStartNewConversationButton;
+    private ListEmptyView mEmptyListMessageView;
+    private ConversationListAdapter mAdapter;
+
+    // Saved Instance State Data - only for temporal data which is nice to maintain but not
+    // critical for correctness.
+    private static final String SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY =
+            "conversationListViewState";
+    private Parcelable mListState;
+
+    @VisibleForTesting
+    final Binding<ConversationListData> mListBinding = BindingBase.createBinding(this);
+
+    public static ConversationListFragment createArchivedConversationListFragment() {
+        return createConversationListFragment(BUNDLE_ARCHIVED_MODE);
+    }
+
+    public static ConversationListFragment createForwardMessageConversationListFragment() {
+        return createConversationListFragment(BUNDLE_FORWARD_MESSAGE_MODE);
+    }
+
+    public static ConversationListFragment createConversationListFragment(String modeKeyName) {
+        final ConversationListFragment fragment = new ConversationListFragment();
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(modeKeyName, true);
+        fragment.setArguments(bundle);
+        return fragment;
+    }
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public void onCreate(final Bundle bundle) {
+        super.onCreate(bundle);
+        mListBinding.getData().init(getLoaderManager(), mListBinding);
+        mAdapter = new ConversationListAdapter(getActivity(), null, this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        Assert.notNull(mHost);
+        setScrolledToNewestConversationIfNeeded();
+
+        updateUi();
+    }
+
+    public void setScrolledToNewestConversationIfNeeded() {
+        if (!mArchiveMode
+                && !mForwardMessageMode
+                && isScrolledToFirstConversation()
+                && mHost.hasWindowFocus()) {
+            mListBinding.getData().setScrolledToNewestConversation(true);
+        }
+    }
+
+    private boolean isScrolledToFirstConversation() {
+        int firstItemPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
+                .findFirstCompletelyVisibleItemPosition();
+        return firstItemPosition == 0;
+    }
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mListBinding.unbind();
+        mHost = null;
+    }
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.conversation_list_fragment,
+                container, false);
+        mRecyclerView = (RecyclerView) rootView.findViewById(android.R.id.list);
+        mEmptyListMessageView = (ListEmptyView) rootView.findViewById(R.id.no_conversations_view);
+        mEmptyListMessageView.setImageHint(R.drawable.ic_oobe_conv_list);
+        // The default behavior for default layout param generation by LinearLayoutManager is to
+        // provide width and height of WRAP_CONTENT, but this is not desirable for
+        // ConversationListFragment; the view in each row should be a width of MATCH_PARENT so that
+        // the entire row is tappable.
+        final Activity activity = getActivity();
+        final LinearLayoutManager manager = new LinearLayoutManager(activity) {
+            @Override
+            public RecyclerView.LayoutParams generateDefaultLayoutParams() {
+                return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT);
+            }
+        };
+        mRecyclerView.setLayoutManager(manager);
+        mRecyclerView.setHasFixedSize(true);
+        mRecyclerView.setAdapter(mAdapter);
+        mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
+            int mCurrentState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
+
+            @Override
+            public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
+                if (mCurrentState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
+                        || mCurrentState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
+                    ImeUtil.get().hideImeKeyboard(getActivity(), mRecyclerView);
+                }
+
+                if (isScrolledToFirstConversation()) {
+                    setScrolledToNewestConversationIfNeeded();
+                } else {
+                    mListBinding.getData().setScrolledToNewestConversation(false);
+                }
+            }
+
+            @Override
+            public void onScrollStateChanged(final RecyclerView recyclerView, final int newState) {
+                mCurrentState = newState;
+            }
+        });
+        mRecyclerView.addOnItemTouchListener(new ConversationListSwipeHelper(mRecyclerView));
+
+        if (savedInstanceState != null) {
+            mListState = savedInstanceState.getParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY);
+        }
+
+        mStartNewConversationButton = (ImageView) rootView.findViewById(
+                R.id.start_new_conversation_button);
+        if (mArchiveMode) {
+            mStartNewConversationButton.setVisibility(View.GONE);
+        } else {
+            mStartNewConversationButton.setVisibility(View.VISIBLE);
+            mStartNewConversationButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(final View clickView) {
+                    mHost.onCreateConversationClick();
+                }
+            });
+        }
+        ViewCompat.setTransitionName(mStartNewConversationButton, BugleAnimationTags.TAG_FABICON);
+
+        // The root view has a non-null background, which by default is deemed by the framework
+        // to be a "transition group," where all child views are animated together during an
+        // activity transition. However, we want each individual items in the recycler view to
+        // show explode animation themselves, so we explicitly tag the root view to be a non-group.
+        ViewGroupCompat.setTransitionGroup(rootView, false);
+
+        setHasOptionsMenu(true);
+        return rootView;
+    }
+
+    @Override
+    public void onAttach(final Activity activity) {
+        super.onAttach(activity);
+        if (VERBOSE) {
+            LogUtil.v(LogUtil.BUGLE_TAG, "Attaching List");
+        }
+        final Bundle arguments = getArguments();
+        if (arguments != null) {
+            mArchiveMode = arguments.getBoolean(BUNDLE_ARCHIVED_MODE, false);
+            mForwardMessageMode = arguments.getBoolean(BUNDLE_FORWARD_MESSAGE_MODE, false);
+        }
+        mListBinding.bind(DataModel.get().createConversationListData(activity, this, mArchiveMode));
+    }
+
+
+    @Override
+    public void onSaveInstanceState(final Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mListState != null) {
+            outState.putParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY, mListState);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
+        mListBinding.getData().setScrolledToNewestConversation(false);
+    }
+
+    /**
+     * Call this immediately after attaching the fragment
+     */
+    public void setHost(final ConversationListFragmentHost host) {
+        Assert.isNull(mHost);
+        mHost = host;
+    }
+
+    @Override
+    public void onConversationListCursorUpdated(final ConversationListData data,
+            final Cursor cursor) {
+        mListBinding.ensureBound(data);
+        final Cursor oldCursor = mAdapter.swapCursor(cursor);
+        updateEmptyListUi(cursor == null || cursor.getCount() == 0);
+        if (mListState != null && cursor != null && oldCursor == null) {
+            mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
+        }
+    }
+
+    @Override
+    public void setBlockedParticipantsAvailable(final boolean blockedAvailable) {
+        mBlockedAvailable = blockedAvailable;
+        if (mShowBlockedMenuItem != null) {
+            mShowBlockedMenuItem.setVisible(blockedAvailable);
+        }
+    }
+
+    public void updateUi() {
+        mAdapter.notifyDataSetChanged();
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        final MenuItem startNewConversationMenuItem =
+                menu.findItem(R.id.action_start_new_conversation);
+        if (startNewConversationMenuItem != null) {
+            // It is recommended for the Floating Action button functionality to be duplicated as a
+            // menu
+            AccessibilityManager accessibilityManager = (AccessibilityManager)
+                    getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
+            startNewConversationMenuItem.setVisible(accessibilityManager
+                    .isTouchExplorationEnabled());
+        }
+
+        final MenuItem archive = menu.findItem(R.id.action_show_archived);
+        if (archive != null) {
+            archive.setVisible(true);
+        }
+    }
+
+    @Override
+    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+        if (!isAdded()) {
+            // Guard against being called before we're added to the activity
+            return;
+        }
+
+        mShowBlockedMenuItem = menu.findItem(R.id.action_show_blocked_contacts);
+        if (mShowBlockedMenuItem != null) {
+            mShowBlockedMenuItem.setVisible(mBlockedAvailable);
+        }
+    }
+
+    /**
+     * {@inheritDoc} from ConversationListItemView.HostInterface
+     */
+    @Override
+    public void onConversationClicked(final ConversationListItemData conversationListItemData,
+            final boolean isLongClick, final ConversationListItemView conversationView) {
+        final ConversationListData listData = mListBinding.getData();
+        mHost.onConversationClick(listData, conversationListItemData, isLongClick,
+                conversationView);
+    }
+
+    /**
+     * {@inheritDoc} from ConversationListItemView.HostInterface
+     */
+    @Override
+    public boolean isConversationSelected(final String conversationId) {
+        return mHost.isConversationSelected(conversationId);
+    }
+
+    @Override
+    public boolean isSwipeAnimatable() {
+        return mHost.isSwipeAnimatable();
+    }
+
+    // Show and hide empty list UI as needed with appropriate text based on view specifics
+    private void updateEmptyListUi(final boolean isEmpty) {
+        if (isEmpty) {
+            int emptyListText;
+            if (!mListBinding.getData().getHasFirstSyncCompleted()) {
+                emptyListText = R.string.conversation_list_first_sync_text;
+            } else if (mArchiveMode) {
+                emptyListText = R.string.archived_conversation_list_empty_text;
+            } else {
+                emptyListText = R.string.conversation_list_empty_text;
+            }
+            mEmptyListMessageView.setTextHint(emptyListText);
+            mEmptyListMessageView.setVisibility(View.VISIBLE);
+            mEmptyListMessageView.setIsImageVisible(true);
+            mEmptyListMessageView.setIsVerticallyCentered(true);
+        } else {
+            mEmptyListMessageView.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public List<SnackBarInteraction> getSnackBarInteractions() {
+        final List<SnackBarInteraction> interactions = new ArrayList<SnackBarInteraction>(1);
+        final SnackBarInteraction fabInteraction =
+                new SnackBarInteraction.BasicSnackBarInteraction(mStartNewConversationButton);
+        interactions.add(fabInteraction);
+        return interactions;
+    }
+
+    private ViewPropertyAnimator getNormalizedFabAnimator() {
+        return mStartNewConversationButton.animate()
+                .setInterpolator(UiUtils.DEFAULT_INTERPOLATOR)
+                .setDuration(getActivity().getResources().getInteger(
+                        R.integer.fab_animation_duration_ms));
+    }
+
+    public ViewPropertyAnimator dismissFab() {
+        // To prevent clicking while animating.
+        mStartNewConversationButton.setEnabled(false);
+        final MarginLayoutParams lp =
+                (MarginLayoutParams) mStartNewConversationButton.getLayoutParams();
+        final float fabWidthWithLeftRightMargin = mStartNewConversationButton.getWidth()
+                + lp.leftMargin + lp.rightMargin;
+        final int direction = AccessibilityUtil.isLayoutRtl(mStartNewConversationButton) ? -1 : 1;
+        return getNormalizedFabAnimator().translationX(direction * fabWidthWithLeftRightMargin);
+    }
+
+    public ViewPropertyAnimator showFab() {
+        return getNormalizedFabAnimator().translationX(0).withEndAction(new Runnable() {
+            @Override
+            public void run() {
+                // Re-enable clicks after the animation.
+                mStartNewConversationButton.setEnabled(true);
+            }
+        });
+    }
+
+    public View getHeroElementForTransition() {
+        return mArchiveMode ? null : mStartNewConversationButton;
+    }
+
+    @VisibleForAnimation
+    public RecyclerView getRecyclerView() {
+        return mRecyclerView;
+    }
+
+    @Override
+    public void startFullScreenPhotoViewer(
+            final Uri initialPhoto, final Rect initialPhotoBounds, final Uri photosUri) {
+        UIIntents.get().launchFullScreenPhotoViewer(
+                getActivity(), initialPhoto, initialPhotoBounds, photosUri);
+    }
+
+    @Override
+    public void startFullScreenVideoViewer(final Uri videoUri) {
+        UIIntents.get().launchFullScreenVideoViewer(getActivity(), videoUri);
+    }
+
+    @Override
+    public boolean isSelectionMode() {
+        return mHost != null && mHost.isSelectionMode();
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java b/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java
new file mode 100644
index 0000000..b22ccfc
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java
@@ -0,0 +1,651 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.net.Uri;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.annotation.VisibleForAnimation;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.UpdateConversationArchiveStatusAction;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.AudioAttachmentView;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.ui.SnackBar;
+import com.android.messaging.ui.SnackBarInteraction;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.Typefaces;
+import com.android.messaging.util.UiUtils;
+import com.android.messaging.util.UriUtil;
+
+import java.util.List;
+
+/**
+ * The view for a single entry in a conversation list.
+ */
+public class ConversationListItemView extends FrameLayout implements OnClickListener,
+        OnLongClickListener, OnLayoutChangeListener {
+    static final int UNREAD_SNIPPET_LINE_COUNT = 3;
+    static final int NO_UNREAD_SNIPPET_LINE_COUNT = 1;
+    private int mListItemReadColor;
+    private int mListItemUnreadColor;
+    private Typeface mListItemReadTypeface;
+    private Typeface mListItemUnreadTypeface;
+    private static String sPlusOneString;
+    private static String sPlusNString;
+
+    public interface HostInterface {
+        boolean isConversationSelected(final String conversationId);
+        void onConversationClicked(final ConversationListItemData conversationListItemData,
+                boolean isLongClick, final ConversationListItemView conversationView);
+        boolean isSwipeAnimatable();
+        List<SnackBarInteraction> getSnackBarInteractions();
+        void startFullScreenPhotoViewer(final Uri initialPhoto, final Rect initialPhotoBounds,
+                final Uri photosUri);
+        void startFullScreenVideoViewer(final Uri videoUri);
+        boolean isSelectionMode();
+    }
+
+    private final OnClickListener fullScreenPreviewClickListener = new OnClickListener() {
+        @Override
+        public void onClick(final View v) {
+            final String previewType = mData.getShowDraft() ?
+                    mData.getDraftPreviewContentType() : mData.getPreviewContentType();
+            Assert.isTrue(ContentType.isImageType(previewType) ||
+                    ContentType.isVideoType(previewType));
+
+            final Uri previewUri = mData.getShowDraft() ?
+                    mData.getDraftPreviewUri() : mData.getPreviewUri();
+            if (ContentType.isImageType(previewType)) {
+                final Uri imagesUri = mData.getShowDraft() ?
+                        MessagingContentProvider.buildDraftImagesUri(mData.getConversationId()) :
+                        MessagingContentProvider
+                                .buildConversationImagesUri(mData.getConversationId());
+                final Rect previewImageBounds = UiUtils.getMeasuredBoundsOnScreen(v);
+                mHostInterface.startFullScreenPhotoViewer(
+                        previewUri, previewImageBounds, imagesUri);
+            } else {
+                mHostInterface.startFullScreenVideoViewer(previewUri);
+            }
+        }
+    };
+
+    private final ConversationListItemData mData;
+
+    private int mAnimatingCount;
+    private ViewGroup mSwipeableContainer;
+    private ViewGroup mCrossSwipeBackground;
+    private ViewGroup mSwipeableContent;
+    private TextView mConversationNameView;
+    private ImageView mWorkProfileIconView;
+    private TextView mSnippetTextView;
+    private TextView mSubjectTextView;
+    private TextView mTimestampTextView;
+    private ContactIconView mContactIconView;
+    private ImageView mContactCheckmarkView;
+    private ImageView mNotificationBellView;
+    private ImageView mFailedStatusIconView;
+    private ImageView mCrossSwipeArchiveLeftImageView;
+    private ImageView mCrossSwipeArchiveRightImageView;
+    private AsyncImageView mImagePreviewView;
+    private AudioAttachmentView mAudioAttachmentView;
+    private HostInterface mHostInterface;
+
+    public ConversationListItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mData = new ConversationListItemData();
+        final Resources res = context.getResources();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mSwipeableContainer = (ViewGroup) findViewById(R.id.swipeableContainer);
+        mCrossSwipeBackground = (ViewGroup) findViewById(R.id.crossSwipeBackground);
+        mSwipeableContent = (ViewGroup) findViewById(R.id.swipeableContent);
+        mConversationNameView = (TextView) findViewById(R.id.conversation_name);
+        mSnippetTextView = (TextView) findViewById(R.id.conversation_snippet);
+        mSubjectTextView = (TextView) findViewById(R.id.conversation_subject);
+        mWorkProfileIconView = (ImageView) findViewById(R.id.work_profile_icon);
+        mTimestampTextView = (TextView) findViewById(R.id.conversation_timestamp);
+        mContactIconView = (ContactIconView) findViewById(R.id.conversation_icon);
+        mContactCheckmarkView = (ImageView) findViewById(R.id.conversation_checkmark);
+        mNotificationBellView = (ImageView) findViewById(R.id.conversation_notification_bell);
+        mFailedStatusIconView = (ImageView) findViewById(R.id.conversation_failed_status_icon);
+        mCrossSwipeArchiveLeftImageView = (ImageView) findViewById(R.id.crossSwipeArchiveIconLeft);
+        mCrossSwipeArchiveRightImageView =
+                (ImageView) findViewById(R.id.crossSwipeArchiveIconRight);
+        mImagePreviewView = (AsyncImageView) findViewById(R.id.conversation_image_preview);
+        mAudioAttachmentView = (AudioAttachmentView) findViewById(R.id.audio_attachment_view);
+        mConversationNameView.addOnLayoutChangeListener(this);
+        mSnippetTextView.addOnLayoutChangeListener(this);
+
+        final Resources resources = getContext().getResources();
+        mListItemReadColor = resources.getColor(R.color.conversation_list_item_read);
+        mListItemUnreadColor = resources.getColor(R.color.conversation_list_item_unread);
+
+        mListItemReadTypeface = Typefaces.getRobotoNormal();
+        mListItemUnreadTypeface = Typefaces.getRobotoBold();
+
+        if (OsUtil.isAtLeastL()) {
+            setTransitionGroup(true);
+        }
+    }
+
+    @Override
+    public void onLayoutChange(final View v, final int left, final int top, final int right,
+            final int bottom, final int oldLeft, final int oldTop, final int oldRight,
+            final int oldBottom) {
+        if (v == mConversationNameView) {
+            setConversationName();
+        } else if (v == mSnippetTextView) {
+            setSnippet();
+        } else if (v == mSubjectTextView) {
+            setSubject();
+        }
+    }
+
+    private void setWorkProfileIcon() {
+        mWorkProfileIconView.setVisibility(mData.isEnterprise() ? View.VISIBLE : View.GONE);
+    }
+
+    private void setConversationName() {
+        if (mData.getIsRead() || mData.getShowDraft()) {
+            mConversationNameView.setTextColor(mListItemReadColor);
+            mConversationNameView.setTypeface(mListItemReadTypeface);
+        } else {
+            mConversationNameView.setTextColor(mListItemUnreadColor);
+            mConversationNameView.setTypeface(mListItemUnreadTypeface);
+        }
+
+        final String conversationName = mData.getName();
+
+        // For group conversations, ellipsize the group members that do not fit
+        final CharSequence ellipsizedName = UiUtils.commaEllipsize(
+                conversationName,
+                mConversationNameView.getPaint(),
+                mConversationNameView.getMeasuredWidth(),
+                getPlusOneString(),
+                getPlusNString());
+        // RTL : To format conversation name if it happens to be phone number.
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+        final String bidiFormattedName = bidiFormatter.unicodeWrap(
+                ellipsizedName.toString(),
+                TextDirectionHeuristicsCompat.LTR);
+
+        mConversationNameView.setText(bidiFormattedName);
+    }
+
+    private static String getPlusOneString() {
+        if (sPlusOneString == null) {
+            sPlusOneString =  Factory.get().getApplicationContext().getResources()
+                    .getString(R.string.plus_one);
+        }
+        return sPlusOneString;
+    }
+
+    private static String getPlusNString() {
+        if (sPlusNString == null) {
+            sPlusNString =  Factory.get().getApplicationContext().getResources()
+                    .getString(R.string.plus_n);
+        }
+        return sPlusNString;
+    }
+
+    private void setSubject() {
+        final String subjectText = mData.getShowDraft() ?
+                mData.getDraftSubject() :
+                    MmsUtils.cleanseMmsSubject(getContext().getResources(), mData.getSubject());
+        if (!TextUtils.isEmpty(subjectText)) {
+            final String subjectPrepend = getResources().getString(R.string.subject_label);
+            mSubjectTextView.setText(TextUtils.concat(subjectPrepend, subjectText));
+            mSubjectTextView.setVisibility(VISIBLE);
+        } else {
+            mSubjectTextView.setVisibility(GONE);
+        }
+    }
+
+    private void setSnippet() {
+        mSnippetTextView.setText(getSnippetText());
+    }
+
+    // Resource Ids of content descriptions prefixes for different message status.
+    private static final int [][][] sPrimaryContentDescriptions = {
+        // 1:1 conversation
+        {
+            // Incoming message
+            {
+                R.string.one_on_one_incoming_failed_message_prefix,
+                R.string.one_on_one_incoming_successful_message_prefix
+            },
+            // Outgoing message
+            {
+                R.string.one_on_one_outgoing_failed_message_prefix,
+                R.string.one_on_one_outgoing_successful_message_prefix,
+                R.string.one_on_one_outgoing_draft_message_prefix,
+                R.string.one_on_one_outgoing_sending_message_prefix,
+            }
+        },
+
+        // Group conversation
+        {
+            // Incoming message
+            {
+                R.string.group_incoming_failed_message_prefix,
+                R.string.group_incoming_successful_message_prefix,
+            },
+            // Outgoing message
+            {
+                R.string.group_outgoing_failed_message_prefix,
+                R.string.group_outgoing_successful_message_prefix,
+                R.string.group_outgoing_draft_message_prefix,
+                R.string.group_outgoing_sending_message_prefix,
+            }
+        }
+    };
+
+    // Resource Id of the secondary part of the content description for an edge case of a message
+    // which is in both draft status and failed status.
+    private static final int sSecondaryContentDescription =
+                                        R.string.failed_message_content_description;
+
+    // 1:1 versus group
+    private static final int CONV_TYPE_ONE_ON_ONE_INDEX = 0;
+    private static final int CONV_TYPE_ONE_GROUP_INDEX = 1;
+    // Direction
+    private static final int DIRECTION_INCOMING_INDEX = 0;
+    private static final int DIRECTION_OUTGOING_INDEX = 1;
+    // Message status
+    private static final int MESSAGE_STATUS_FAILED_INDEX = 0;
+    private static final int MESSAGE_STATUS_SUCCESSFUL_INDEX = 1;
+    private static final int MESSAGE_STATUS_DRAFT_INDEX = 2;
+    private static final int MESSAGE_STATUS_SENDING_INDEX = 3;
+
+    private static final int WIDTH_FOR_ACCESSIBLE_CONVERSATION_NAME = 600;
+
+    public static String buildContentDescription(final Resources resources,
+            final ConversationListItemData data, final TextPaint conversationNameViewPaint) {
+        int messageStatusIndex;
+        boolean outgoingSnippet = data.getIsMessageTypeOutgoing() || data.getShowDraft();
+        if (outgoingSnippet) {
+            if (data.getShowDraft()) {
+                messageStatusIndex = MESSAGE_STATUS_DRAFT_INDEX;
+            } else if (data.getIsSendRequested()) {
+                messageStatusIndex = MESSAGE_STATUS_SENDING_INDEX;
+            } else {
+                messageStatusIndex = data.getIsFailedStatus() ? MESSAGE_STATUS_FAILED_INDEX
+                        : MESSAGE_STATUS_SUCCESSFUL_INDEX;
+            }
+        } else {
+            messageStatusIndex = data.getIsFailedStatus() ? MESSAGE_STATUS_FAILED_INDEX
+                    : MESSAGE_STATUS_SUCCESSFUL_INDEX;
+        }
+
+        int resId = sPrimaryContentDescriptions
+                [data.getIsGroup() ? CONV_TYPE_ONE_GROUP_INDEX : CONV_TYPE_ONE_ON_ONE_INDEX]
+                [outgoingSnippet ? DIRECTION_OUTGOING_INDEX : DIRECTION_INCOMING_INDEX]
+                [messageStatusIndex];
+
+        final String snippetText = data.getShowDraft() ?
+                data.getDraftSnippetText() : data.getSnippetText();
+
+        final String conversationName = data.getName();
+        String senderOrConvName = outgoingSnippet ? conversationName : data.getSnippetSenderName();
+
+        String primaryContentDescription = resources.getString(resId, senderOrConvName,
+                snippetText == null ? "" : snippetText,
+                data.getFormattedTimestamp(),
+                // This is used only for incoming group messages
+                conversationName);
+        String contentDescription = primaryContentDescription;
+
+        // An edge case : for an outgoing message, it might be in both draft status and
+        // failed status.
+        if (outgoingSnippet && data.getShowDraft() && data.getIsFailedStatus()) {
+            StringBuilder contentDescriptionBuilder = new StringBuilder();
+            contentDescriptionBuilder.append(primaryContentDescription);
+
+            String secondaryContentDescription =
+                    resources.getString(sSecondaryContentDescription);
+            contentDescriptionBuilder.append(" ");
+            contentDescriptionBuilder.append(secondaryContentDescription);
+            contentDescription = contentDescriptionBuilder.toString();
+        }
+        return contentDescription;
+    }
+
+    /**
+     * Fills in the data associated with this view.
+     *
+     * @param cursor The cursor from a ConversationList that this view is in, pointing to its
+     * entry.
+     */
+    public void bind(final Cursor cursor, final HostInterface hostInterface) {
+        // Update our UI model
+        mHostInterface = hostInterface;
+        mData.bind(cursor);
+
+        resetAnimatingState();
+
+        mSwipeableContainer.setOnClickListener(this);
+        mSwipeableContainer.setOnLongClickListener(this);
+
+        final Resources resources = getContext().getResources();
+
+        int color;
+        final int maxLines;
+        final Typeface typeface;
+        final int typefaceStyle = mData.getShowDraft() ? Typeface.ITALIC : Typeface.NORMAL;
+        final String snippetText = getSnippetText();
+
+        if (mData.getIsRead() || mData.getShowDraft()) {
+            maxLines = TextUtils.isEmpty(snippetText) ? 0 : NO_UNREAD_SNIPPET_LINE_COUNT;
+            color = mListItemReadColor;
+            typeface = mListItemReadTypeface;
+        } else {
+            maxLines = TextUtils.isEmpty(snippetText) ? 0 : UNREAD_SNIPPET_LINE_COUNT;
+            color = mListItemUnreadColor;
+            typeface = mListItemUnreadTypeface;
+        }
+
+        mSnippetTextView.setMaxLines(maxLines);
+        mSnippetTextView.setTextColor(color);
+        mSnippetTextView.setTypeface(typeface, typefaceStyle);
+        mSubjectTextView.setTextColor(color);
+        mSubjectTextView.setTypeface(typeface, typefaceStyle);
+
+        setSnippet();
+        setConversationName();
+        setSubject();
+        setWorkProfileIcon();
+        setContentDescription(buildContentDescription(resources, mData,
+                mConversationNameView.getPaint()));
+
+        final boolean isDefaultSmsApp = PhoneUtils.getDefault().isDefaultSmsApp();
+        // don't show the error state unless we're the default sms app
+        if (mData.getIsFailedStatus() && isDefaultSmsApp) {
+            mTimestampTextView.setTextColor(resources.getColor(R.color.conversation_list_error));
+            mTimestampTextView.setTypeface(mListItemReadTypeface, typefaceStyle);
+            int failureMessageId = R.string.message_status_download_failed;
+            if (mData.getIsMessageTypeOutgoing()) {
+                failureMessageId = MmsUtils.mapRawStatusToErrorResourceId(mData.getMessageStatus(),
+                        mData.getMessageRawTelephonyStatus());
+            }
+            mTimestampTextView.setText(resources.getString(failureMessageId));
+        } else if (mData.getShowDraft()
+                || mData.getMessageStatus() == MessageData.BUGLE_STATUS_OUTGOING_DRAFT
+                // also check for unknown status which we get because sometimes the conversation
+                // row is left with a latest_message_id of a no longer existing message and
+                // therefore the join values come back as null (or in this case zero).
+                || mData.getMessageStatus() == MessageData.BUGLE_STATUS_UNKNOWN) {
+            mTimestampTextView.setTextColor(mListItemReadColor);
+            mTimestampTextView.setTypeface(mListItemReadTypeface, typefaceStyle);
+            mTimestampTextView.setText(resources.getString(
+                    R.string.conversation_list_item_view_draft_message));
+         } else {
+            mTimestampTextView.setTextColor(mListItemReadColor);
+            mTimestampTextView.setTypeface(mListItemReadTypeface, typefaceStyle);
+            final String formattedTimestamp = mData.getFormattedTimestamp();
+            if (mData.getIsSendRequested()) {
+                mTimestampTextView.setText(R.string.message_status_sending);
+            } else {
+                mTimestampTextView.setText(formattedTimestamp);
+            }
+        }
+
+        final boolean isSelected = mHostInterface.isConversationSelected(mData.getConversationId());
+        setSelected(isSelected);
+        Uri iconUri = null;
+        int contactIconVisibility = GONE;
+        int checkmarkVisiblity = GONE;
+        int failStatusVisiblity = GONE;
+        if (isSelected) {
+            checkmarkVisiblity = VISIBLE;
+        } else {
+            contactIconVisibility = VISIBLE;
+            // Only show the fail icon if it is not a group conversation.
+            // And also require that we be the default sms app.
+            if (mData.getIsFailedStatus() && !mData.getIsGroup() && isDefaultSmsApp) {
+                failStatusVisiblity = VISIBLE;
+            }
+        }
+        if (mData.getIcon() != null) {
+            iconUri = Uri.parse(mData.getIcon());
+        }
+        mContactIconView.setImageResourceUri(iconUri, mData.getParticipantContactId(),
+                mData.getParticipantLookupKey(), mData.getOtherParticipantNormalizedDestination());
+        mContactIconView.setVisibility(contactIconVisibility);
+        mContactIconView.setOnLongClickListener(this);
+        mContactIconView.setClickable(!mHostInterface.isSelectionMode());
+        mContactIconView.setLongClickable(!mHostInterface.isSelectionMode());
+
+        mContactCheckmarkView.setVisibility(checkmarkVisiblity);
+        mFailedStatusIconView.setVisibility(failStatusVisiblity);
+
+        final Uri previewUri = mData.getShowDraft() ?
+                mData.getDraftPreviewUri() : mData.getPreviewUri();
+        final String previewContentType = mData.getShowDraft() ?
+                mData.getDraftPreviewContentType() : mData.getPreviewContentType();
+        OnClickListener previewClickListener = null;
+        Uri previewImageUri = null;
+        int previewImageVisibility = GONE;
+        int audioPreviewVisiblity = GONE;
+        if (previewUri != null && !TextUtils.isEmpty(previewContentType)) {
+            if (ContentType.isAudioType(previewContentType)) {
+                boolean incoming = !(mData.getShowDraft() || mData.getIsMessageTypeOutgoing());
+                mAudioAttachmentView.bind(previewUri, incoming, false);
+                audioPreviewVisiblity = VISIBLE;
+            } else if (ContentType.isVideoType(previewContentType)) {
+                previewImageUri = UriUtil.getUriForResourceId(
+                        getContext(), R.drawable.ic_preview_play);
+                previewClickListener = fullScreenPreviewClickListener;
+                previewImageVisibility = VISIBLE;
+            } else if (ContentType.isImageType(previewContentType)) {
+                previewImageUri = previewUri;
+                previewClickListener = fullScreenPreviewClickListener;
+                previewImageVisibility = VISIBLE;
+            }
+        }
+
+        final int imageSize = resources.getDimensionPixelSize(
+                R.dimen.conversation_list_image_preview_size);
+        mImagePreviewView.setImageResourceId(
+                new UriImageRequestDescriptor(previewImageUri, imageSize, imageSize,
+                        true /* allowCompression */, false /* isStatic */, false /*cropToCircle*/,
+                        ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                        ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */));
+        mImagePreviewView.setOnLongClickListener(this);
+        mImagePreviewView.setVisibility(previewImageVisibility);
+        mImagePreviewView.setOnClickListener(previewClickListener);
+        mAudioAttachmentView.setOnLongClickListener(this);
+        mAudioAttachmentView.setVisibility(audioPreviewVisiblity);
+
+        final int notificationBellVisiblity = mData.getNotificationEnabled() ? GONE : VISIBLE;
+        mNotificationBellView.setVisibility(notificationBellVisiblity);
+    }
+
+    public boolean isSwipeAnimatable() {
+        return mHostInterface.isSwipeAnimatable();
+    }
+
+    @VisibleForAnimation
+    public float getSwipeTranslationX() {
+        return mSwipeableContainer.getTranslationX();
+    }
+
+    @VisibleForAnimation
+    public void setSwipeTranslationX(final float translationX) {
+        mSwipeableContainer.setTranslationX(translationX);
+        if (translationX == 0) {
+            mCrossSwipeBackground.setVisibility(View.GONE);
+            mCrossSwipeArchiveLeftImageView.setVisibility(GONE);
+            mCrossSwipeArchiveRightImageView.setVisibility(GONE);
+
+            mSwipeableContainer.setBackgroundColor(Color.TRANSPARENT);
+        } else {
+            mCrossSwipeBackground.setVisibility(View.VISIBLE);
+            if (translationX > 0) {
+                mCrossSwipeArchiveLeftImageView.setVisibility(VISIBLE);
+                mCrossSwipeArchiveRightImageView.setVisibility(GONE);
+            } else {
+                mCrossSwipeArchiveLeftImageView.setVisibility(GONE);
+                mCrossSwipeArchiveRightImageView.setVisibility(VISIBLE);
+            }
+            mSwipeableContainer.setBackgroundResource(R.drawable.swipe_shadow_drag);
+        }
+    }
+
+    public void onSwipeComplete() {
+        final String conversationId = mData.getConversationId();
+        UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
+
+        final Runnable undoRunnable = new Runnable() {
+            @Override
+            public void run() {
+                UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
+            }
+        };
+        final String message = getResources().getString(R.string.archived_toast_message, 1);
+        UiUtils.showSnackBar(getContext(), getRootView(), message, undoRunnable,
+                SnackBar.Action.SNACK_BAR_UNDO,
+                mHostInterface.getSnackBarInteractions());
+    }
+
+    private void setShortAndLongClickable(final boolean clickable) {
+        setClickable(clickable);
+        setLongClickable(clickable);
+    }
+
+    private void resetAnimatingState() {
+        mAnimatingCount = 0;
+        setShortAndLongClickable(true);
+        setSwipeTranslationX(0);
+    }
+
+    /**
+     * Notifies this view that it is undergoing animation. This view should disable its click
+     * targets.
+     *
+     * The animating counter is used to reset the swipe controller when the counter becomes 0. A
+     * positive counter also makes the view not clickable.
+     */
+    public final void setAnimating(final boolean animating) {
+        final int oldAnimatingCount = mAnimatingCount;
+        if (animating) {
+            mAnimatingCount++;
+        } else {
+            mAnimatingCount--;
+            if (mAnimatingCount < 0) {
+                mAnimatingCount = 0;
+            }
+        }
+
+        if (mAnimatingCount == 0) {
+            // New count is 0. All animations ended.
+            setShortAndLongClickable(true);
+        } else if (oldAnimatingCount == 0) {
+            // New count is > 0. Waiting for some animations to end.
+            setShortAndLongClickable(false);
+        }
+    }
+
+    public boolean isAnimating() {
+        return mAnimatingCount > 0;
+    }
+
+    /**
+     * {@inheritDoc} from OnClickListener
+     */
+    @Override
+    public void onClick(final View v) {
+        processClick(v, false);
+    }
+
+    /**
+     * {@inheritDoc} from OnLongClickListener
+     */
+    @Override
+    public boolean onLongClick(final View v) {
+        return processClick(v, true);
+    }
+
+    private boolean processClick(final View v, final boolean isLongClick) {
+        Assert.isTrue(v == mSwipeableContainer || v == mContactIconView || v == mImagePreviewView);
+        Assert.notNull(mData.getName());
+
+        if (mHostInterface != null) {
+            mHostInterface.onConversationClicked(mData, isLongClick, this);
+            return true;
+        }
+        return false;
+    }
+
+    public View getSwipeableContent() {
+        return mSwipeableContent;
+    }
+
+    public View getContactIconView() {
+        return mContactIconView;
+    }
+
+    private String getSnippetText() {
+        String snippetText = mData.getShowDraft() ?
+                mData.getDraftSnippetText() : mData.getSnippetText();
+        final String previewContentType = mData.getShowDraft() ?
+                mData.getDraftPreviewContentType() : mData.getPreviewContentType();
+        if (TextUtils.isEmpty(snippetText)) {
+            Resources resources = getResources();
+            // Use the attachment type as a snippet so the preview doesn't look odd
+            if (ContentType.isAudioType(previewContentType)) {
+                snippetText = resources.getString(R.string.conversation_list_snippet_audio_clip);
+            } else if (ContentType.isImageType(previewContentType)) {
+                snippetText = resources.getString(R.string.conversation_list_snippet_picture);
+            } else if (ContentType.isVideoType(previewContentType)) {
+                snippetText = resources.getString(R.string.conversation_list_snippet_video);
+            } else if (ContentType.isVCardType(previewContentType)) {
+                snippetText = resources.getString(R.string.conversation_list_snippet_vcard);
+            }
+        }
+        return snippetText;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListSwipeHelper.java b/src/com/android/messaging/ui/conversationlist/ConversationListSwipeHelper.java
new file mode 100644
index 0000000..e5859a6
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListSwipeHelper.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.content.res.Resources;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import com.android.messaging.R;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Animation and touch helper class for Conversation List swipe.
+ */
+public class ConversationListSwipeHelper implements OnItemTouchListener {
+    private static final int UNIT_SECONDS = 1000;
+    private static final boolean ANIMATING = true;
+
+    private static final float ERROR_FACTOR_MULTIPLIER = 1.2f;
+    private static final float PERCENTAGE_OF_WIDTH_TO_DISMISS = 0.4f;
+    private static final float FLING_PERCENTAGE_OF_WIDTH_TO_DISMISS = 0.05f;
+
+    private static final int SWIPE_DIRECTION_NONE = 0;
+    private static final int SWIPE_DIRECTION_LEFT = 1;
+    private static final int SWIPE_DIRECTION_RIGHT = 2;
+
+    private final RecyclerView mRecyclerView;
+    private final long mDefaultRestoreAnimationDuration;
+    private final long mDefaultDismissAnimationDuration;
+    private final long mMaxTranslationAnimationDuration;
+    private final int mTouchSlop;
+    private final int mMinimumFlingVelocity;
+    private final int mMaximumFlingVelocity;
+
+    /* Valid throughout a single gesture. */
+    private VelocityTracker mVelocityTracker;
+    private float mInitialX;
+    private float mInitialY;
+    private boolean mIsSwiping;
+    private ConversationListItemView mListItemView;
+
+    public ConversationListSwipeHelper(final RecyclerView recyclerView) {
+        mRecyclerView = recyclerView;
+
+        final Context context = mRecyclerView.getContext();
+        final Resources res = context.getResources();
+        mDefaultRestoreAnimationDuration = res.getInteger(R.integer.swipe_duration_ms);
+        mDefaultDismissAnimationDuration = res.getInteger(R.integer.swipe_duration_ms);
+        mMaxTranslationAnimationDuration = res.getInteger(R.integer.swipe_duration_ms);
+
+        final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
+        mTouchSlop = viewConfiguration.getScaledPagingTouchSlop();
+        mMaximumFlingVelocity = Math.min(
+                viewConfiguration.getScaledMaximumFlingVelocity(),
+                res.getInteger(R.integer.swipe_max_fling_velocity_px_per_s));
+        mMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(final RecyclerView recyclerView, final MotionEvent event) {
+        if (event.getPointerCount() > 1) {
+            // Ignore subsequent pointers.
+            return false;
+        }
+
+        // We are not yet tracking a swipe gesture. Begin detection by spying on
+        // touch events bubbling down to our children.
+        final int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                if (!hasGestureSwipeTarget()) {
+                    onGestureStart();
+
+                    mVelocityTracker.addMovement(event);
+                    mInitialX = event.getX();
+                    mInitialY = event.getY();
+
+                    final View viewAtPoint = mRecyclerView.findChildViewUnder(mInitialX, mInitialY);
+                    final ConversationListItemView child = (ConversationListItemView) viewAtPoint;
+                    if (viewAtPoint instanceof ConversationListItemView &&
+                            child != null && child.isSwipeAnimatable()) {
+                        // Begin detecting swipe on the target for the rest of the gesture.
+                        mListItemView = child;
+                        if (mListItemView.isAnimating()) {
+                            mListItemView = null;
+                        }
+                    } else {
+                        mListItemView = null;
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (hasValidGestureSwipeTarget()) {
+                    mVelocityTracker.addMovement(event);
+
+                    final int historicalCount = event.getHistorySize();
+                    // First consume the historical events, then consume the current ones.
+                    for (int i = 0; i < historicalCount + 1; i++) {
+                        float currX;
+                        float currY;
+                        if (i < historicalCount) {
+                            currX = event.getHistoricalX(i);
+                            currY = event.getHistoricalY(i);
+                        } else {
+                            currX = event.getX();
+                            currY = event.getY();
+                        }
+                        final float deltaX = currX - mInitialX;
+                        final float deltaY = currY - mInitialY;
+                        final float absDeltaX = Math.abs(deltaX);
+                        final float absDeltaY = Math.abs(deltaY);
+
+                        if (!mIsSwiping && absDeltaY > mTouchSlop
+                                && absDeltaY > (ERROR_FACTOR_MULTIPLIER * absDeltaX)) {
+                            // Stop detecting swipe for the remainder of this gesture.
+                            onGestureEnd();
+                            return false;
+                        }
+
+                        if (absDeltaX > mTouchSlop) {
+                            // Swipe detected. Return true so we can handle the gesture in
+                            // onTouchEvent.
+                            mIsSwiping = true;
+
+                            // We don't want to suddenly jump the slop distance.
+                            mInitialX = event.getX();
+                            mInitialY = event.getY();
+
+                            onSwipeGestureStart(mListItemView);
+                            return true;
+                        }
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                if (hasGestureSwipeTarget()) {
+                    onGestureEnd();
+                }
+                break;
+        }
+
+        // Start intercepting touch events from children if we detect a swipe.
+        return mIsSwiping;
+    }
+
+    @Override
+    public void onTouchEvent(final RecyclerView recyclerView, final MotionEvent event) {
+        // We should only be here if we intercepted the touch due to swipe.
+        Assert.isTrue(mIsSwiping);
+
+        // We are now tracking a swipe gesture.
+        mVelocityTracker.addMovement(event);
+
+        final int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_OUTSIDE:
+            case MotionEvent.ACTION_MOVE:
+                if (hasValidGestureSwipeTarget()) {
+                    mListItemView.setSwipeTranslationX(event.getX() - mInitialX);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (hasValidGestureSwipeTarget()) {
+                    final float maxVelocity = mMaximumFlingVelocity;
+                    mVelocityTracker.computeCurrentVelocity(UNIT_SECONDS, maxVelocity);
+                    final float velocityX = getLastComputedXVelocity();
+
+                    final float translationX = mListItemView.getSwipeTranslationX();
+
+                    int swipeDirection = SWIPE_DIRECTION_NONE;
+                    if (translationX != 0) {
+                        swipeDirection =
+                                translationX > 0 ? SWIPE_DIRECTION_RIGHT : SWIPE_DIRECTION_LEFT;
+                    } else if (velocityX != 0) {
+                        swipeDirection =
+                                velocityX > 0 ? SWIPE_DIRECTION_RIGHT : SWIPE_DIRECTION_LEFT;
+                    }
+
+                    final boolean fastEnough = isTargetSwipedFastEnough();
+                    final boolean farEnough = isTargetSwipedFarEnough();
+
+                    final boolean shouldDismiss =  (fastEnough || farEnough);
+
+                    if (shouldDismiss) {
+                        if (fastEnough) {
+                            animateDismiss(mListItemView, velocityX);
+                        } else {
+                            animateDismiss(mListItemView, swipeDirection);
+                        }
+                    } else {
+                        animateRestore(mListItemView, velocityX);
+                    }
+
+                    onSwipeGestureEnd(mListItemView,
+                            shouldDismiss ? swipeDirection : SWIPE_DIRECTION_NONE);
+                } else {
+                    onGestureEnd();
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                if (hasValidGestureSwipeTarget()) {
+                    animateRestore(mListItemView, 0f);
+                    onSwipeGestureEnd(mListItemView, SWIPE_DIRECTION_NONE);
+                } else {
+                    onGestureEnd();
+                }
+                break;
+        }
+    }
+
+
+    @Override
+    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+    }
+
+    /**
+     * We have started to intercept a series of touch events.
+     */
+    private void onGestureStart() {
+        mIsSwiping = false;
+        // Work around bug in RecyclerView that sends two identical ACTION_DOWN
+        // events to #onInterceptTouchEvent.
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+        mVelocityTracker.clear();
+    }
+
+    /**
+     * The series of touch events has been detected as a swipe.
+     *
+     * Now that the gesture is a swipe, we will begin translating the view of the
+     * given viewHolder.
+     */
+    private void onSwipeGestureStart(final ConversationListItemView itemView) {
+        mRecyclerView.getParent().requestDisallowInterceptTouchEvent(true);
+        setHardwareAnimatingLayerType(itemView, ANIMATING);
+        itemView.setAnimating(true);
+    }
+
+    /**
+     * The current swipe gesture is complete.
+     */
+    private void onSwipeGestureEnd(final ConversationListItemView itemView,
+            final int swipeDirection) {
+        if (swipeDirection == SWIPE_DIRECTION_RIGHT || swipeDirection == SWIPE_DIRECTION_LEFT) {
+            itemView.onSwipeComplete();
+        }
+
+        // Balances out onSwipeGestureStart.
+        itemView.setAnimating(false);
+
+        onGestureEnd();
+    }
+
+    /**
+     * The series of touch events has ended in an {@link MotionEvent#ACTION_UP}
+     * or {@link MotionEvent#ACTION_CANCEL}.
+     */
+    private void onGestureEnd() {
+        mVelocityTracker.recycle();
+        mVelocityTracker = null;
+        mIsSwiping = false;
+        mListItemView = null;
+    }
+
+    /**
+     * A swipe animation has started.
+     */
+    private void onSwipeAnimationStart(final ConversationListItemView itemView) {
+        // Disallow interactions.
+        itemView.setAnimating(true);
+        ViewCompat.setHasTransientState(itemView, true);
+        setHardwareAnimatingLayerType(itemView, ANIMATING);
+    }
+
+    /**
+     * The swipe animation has ended.
+     */
+    private void onSwipeAnimationEnd(final ConversationListItemView itemView) {
+        // Restore interactions.
+        itemView.setAnimating(false);
+        ViewCompat.setHasTransientState(itemView, false);
+        setHardwareAnimatingLayerType(itemView, !ANIMATING);
+    }
+
+    /**
+     * Animate the dismissal of the given item. The given velocityX is taken into consideration for
+     * the animation duration. Whether the item is dismissed to the left or right is dependent on
+     * the given velocityX.
+     */
+    private void animateDismiss(final ConversationListItemView itemView, final float velocityX) {
+        Assert.isTrue(velocityX != 0);
+        final int direction = velocityX > 0 ? SWIPE_DIRECTION_RIGHT : SWIPE_DIRECTION_LEFT;
+        animateDismiss(itemView, direction, velocityX);
+    }
+
+    /**
+     * Animate the dismissal of the given item. The velocityX is assumed to be 0.
+     */
+    private void animateDismiss(final ConversationListItemView itemView, final int swipeDirection) {
+        animateDismiss(itemView, swipeDirection, 0f);
+    }
+
+    /**
+     * Animate the dismissal of the given item.
+     */
+    private void animateDismiss(final ConversationListItemView itemView,
+            final int swipeDirection, final float velocityX) {
+        Assert.isTrue(swipeDirection != SWIPE_DIRECTION_NONE);
+
+        onSwipeAnimationStart(itemView);
+
+        final float animateTo = (swipeDirection == SWIPE_DIRECTION_RIGHT) ?
+                mRecyclerView.getWidth() : -mRecyclerView.getWidth();
+        final long duration;
+        if (velocityX != 0) {
+            final float deltaX = animateTo - itemView.getSwipeTranslationX();
+            duration = calculateTranslationDuration(deltaX, velocityX);
+        } else {
+            duration = mDefaultDismissAnimationDuration;
+        }
+
+        final ObjectAnimator animator = getSwipeTranslationXAnimator(
+                itemView, animateTo, duration, UiUtils.DEFAULT_INTERPOLATOR);
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(final Animator animation) {
+                onSwipeAnimationEnd(itemView);
+            }
+        });
+        animator.start();
+    }
+
+    /**
+     * Animate the bounce back of the given item.
+     */
+    private void animateRestore(final ConversationListItemView itemView,
+            final float velocityX) {
+        onSwipeAnimationStart(itemView);
+
+        final float translationX = itemView.getSwipeTranslationX();
+        final long duration;
+        if (velocityX != 0 // Has velocity.
+                && velocityX > 0 != translationX > 0) { // Right direction.
+            duration = calculateTranslationDuration(translationX, velocityX);
+        } else {
+            duration = mDefaultRestoreAnimationDuration;
+        }
+        final ObjectAnimator animator = getSwipeTranslationXAnimator(
+                itemView, 0f, duration, UiUtils.DEFAULT_INTERPOLATOR);
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(final Animator animation) {
+                       onSwipeAnimationEnd(itemView);
+            }
+        });
+        animator.start();
+    }
+
+    /**
+     * Create and start an animator that animates the given view's translationX
+     * from its current value to the value given by animateTo.
+     */
+    private ObjectAnimator getSwipeTranslationXAnimator(final ConversationListItemView itemView,
+            final float animateTo, final long duration, final TimeInterpolator interpolator) {
+        final ObjectAnimator animator =
+                ObjectAnimator.ofFloat(itemView, "swipeTranslationX", animateTo);
+        animator.setDuration(duration);
+        animator.setInterpolator(interpolator);
+        return animator;
+    }
+
+    /**
+     * Determine if the swipe has enough velocity to be dismissed.
+     */
+    private boolean isTargetSwipedFastEnough() {
+        final float velocityX = getLastComputedXVelocity();
+        final float velocityY = mVelocityTracker.getYVelocity();
+        final float minVelocity = mMinimumFlingVelocity;
+        final float translationX = mListItemView.getSwipeTranslationX();
+        final float width = mListItemView.getWidth();
+        return (Math.abs(velocityX) > minVelocity) // Fast enough.
+                && (Math.abs(velocityX) > Math.abs(velocityY)) // Not unintentional.
+                && (velocityX > 0) == (translationX > 0) // Right direction.
+                && Math.abs(translationX) >
+                    FLING_PERCENTAGE_OF_WIDTH_TO_DISMISS * width; // Enough movement.
+  }
+
+    /**
+     * Only used during a swipe gesture. Determine if the swipe has enough distance to be
+     * dismissed.
+     */
+    private boolean isTargetSwipedFarEnough() {
+        final float velocityX = getLastComputedXVelocity();
+
+        final float translationX = mListItemView.getSwipeTranslationX();
+        final float width = mListItemView.getWidth();
+
+        return (velocityX >= 0) == (translationX > 0) // Right direction.
+                && Math.abs(translationX) >
+                    PERCENTAGE_OF_WIDTH_TO_DISMISS * width; // Enough movement.
+  }
+
+    private long calculateTranslationDuration(final float deltaPosition, final float velocity) {
+        Assert.isTrue(velocity != 0);
+        final float durationInSeconds = Math.abs(deltaPosition / velocity);
+        return Math.min((int) (durationInSeconds * UNIT_SECONDS), mMaxTranslationAnimationDuration);
+    }
+
+    private boolean hasGestureSwipeTarget() {
+        return mListItemView != null;
+    }
+
+    private boolean hasValidGestureSwipeTarget() {
+        return hasGestureSwipeTarget() && mListItemView.getParent() == mRecyclerView;
+    }
+
+    /**
+     * Enable a hardware layer for the it view and build that layer.
+     */
+    private void setHardwareAnimatingLayerType(final ConversationListItemView itemView,
+            final boolean animating) {
+        if (animating) {
+            itemView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            if (itemView.getWindowToken() != null) {
+                itemView.buildLayer();
+            }
+        } else {
+            itemView.setLayerType(View.LAYER_TYPE_NONE, null);
+        }
+    }
+
+    private float getLastComputedXVelocity() {
+        return mVelocityTracker.getXVelocity();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/conversationlist/ForwardMessageActivity.java b/src/com/android/messaging/ui/conversationlist/ForwardMessageActivity.java
new file mode 100644
index 0000000..61e3640
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ForwardMessageActivity.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.app.Fragment;
+import android.os.Bundle;
+
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.ui.BaseBugleActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
+import com.android.messaging.util.Assert;
+
+/**
+ * An activity that lets the user forward a SMS/MMS message by picking from a conversation in the
+ * conversation list.
+ */
+public class ForwardMessageActivity extends BaseBugleActivity
+    implements ConversationListFragmentHost {
+    private MessageData mDraftMessage;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final ConversationListFragment fragment =
+                ConversationListFragment.createForwardMessageConversationListFragment();
+        getFragmentManager().beginTransaction().add(android.R.id.content, fragment).commit();
+        mDraftMessage = getIntent().getParcelableExtra(UIIntents.UI_INTENT_EXTRA_DRAFT_DATA);
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        Assert.isTrue(fragment instanceof ConversationListFragment);
+        final ConversationListFragment clf = (ConversationListFragment) fragment;
+        clf.setHost(this);
+    }
+
+    @Override
+    public void onConversationClick(final ConversationListData listData,
+                                    final ConversationListItemData conversationListItemData,
+            final boolean isLongClick, final ConversationListItemView converastionView) {
+        UIIntents.get().launchConversationActivity(
+                this, conversationListItemData.getConversationId(), mDraftMessage);
+    }
+
+    @Override
+    public void onCreateConversationClick() {
+        UIIntents.get().launchCreateNewConversationActivity(this, mDraftMessage);
+    }
+
+    @Override
+    public boolean isConversationSelected(final String conversationId) {
+        return false;
+    }
+
+    @Override
+    public boolean isSwipeAnimatable() {
+        return false;
+    }
+
+    @Override
+    public boolean isSelectionMode() {
+        return false;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/MultiSelectActionModeCallback.java b/src/com/android/messaging/ui/conversationlist/MultiSelectActionModeCallback.java
new file mode 100644
index 0000000..64d1436
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/MultiSelectActionModeCallback.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import androidx.collection.ArrayMap;
+import android.text.TextUtils;
+import android.view.ActionMode;
+import android.view.ActionMode.Callback;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.util.Assert;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+public class MultiSelectActionModeCallback implements Callback {
+    private HashSet<String> mBlockedSet;
+
+    public interface Listener {
+        void onActionBarDelete(Collection<SelectedConversation> conversations);
+        void onActionBarArchive(Iterable<SelectedConversation> conversations,
+                boolean isToArchive);
+        void onActionBarNotification(Iterable<SelectedConversation> conversations,
+                boolean isNotificationOn);
+        void onActionBarAddContact(final SelectedConversation conversation);
+        void onActionBarBlock(final SelectedConversation conversation);
+        void onActionBarHome();
+    }
+
+    static class SelectedConversation {
+        public final String conversationId;
+        public final long timestamp;
+        public final String icon;
+        public final String otherParticipantNormalizedDestination;
+        public final CharSequence participantLookupKey;
+        public final boolean isGroup;
+        public final boolean isArchived;
+        public final boolean notificationEnabled;
+        public SelectedConversation(ConversationListItemData data) {
+            conversationId = data.getConversationId();
+            timestamp = data.getTimestamp();
+            icon = data.getIcon();
+            otherParticipantNormalizedDestination = data.getOtherParticipantNormalizedDestination();
+            participantLookupKey = data.getParticipantLookupKey();
+            isGroup = data.getIsGroup();
+            isArchived = data.getIsArchived();
+            notificationEnabled = data.getNotificationEnabled();
+        }
+    }
+
+    private final ArrayMap<String, SelectedConversation> mSelectedConversations;
+
+    private Listener mListener;
+    private MenuItem mArchiveMenuItem;
+    private MenuItem mUnarchiveMenuItem;
+    private MenuItem mAddContactMenuItem;
+    private MenuItem mBlockMenuItem;
+    private MenuItem mNotificationOnMenuItem;
+    private MenuItem mNotificationOffMenuItem;
+    private boolean mHasInflated;
+
+    public MultiSelectActionModeCallback(final Listener listener) {
+        mListener = listener;
+        mSelectedConversations = new ArrayMap<>();
+
+    }
+
+    @Override
+    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+        actionMode.getMenuInflater().inflate(R.menu.conversation_list_fragment_select_menu, menu);
+        mArchiveMenuItem = menu.findItem(R.id.action_archive);
+        mUnarchiveMenuItem = menu.findItem(R.id.action_unarchive);
+        mAddContactMenuItem = menu.findItem(R.id.action_add_contact);
+        mBlockMenuItem = menu.findItem(R.id.action_block);
+        mNotificationOffMenuItem = menu.findItem(R.id.action_notification_off);
+        mNotificationOnMenuItem = menu.findItem(R.id.action_notification_on);
+        mHasInflated = true;
+        updateActionIconsVisiblity();
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
+        return true;
+    }
+
+    @Override
+    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
+        switch(menuItem.getItemId()) {
+            case R.id.action_delete:
+                mListener.onActionBarDelete(mSelectedConversations.values());
+                return true;
+            case R.id.action_archive:
+                mListener.onActionBarArchive(mSelectedConversations.values(), true);
+                return true;
+            case R.id.action_unarchive:
+                mListener.onActionBarArchive(mSelectedConversations.values(), false);
+                return true;
+            case R.id.action_notification_off:
+                mListener.onActionBarNotification(mSelectedConversations.values(), false);
+                return true;
+            case R.id.action_notification_on:
+                mListener.onActionBarNotification(mSelectedConversations.values(), true);
+                return true;
+            case R.id.action_add_contact:
+                Assert.isTrue(mSelectedConversations.size() == 1);
+                mListener.onActionBarAddContact(mSelectedConversations.valueAt(0));
+                return true;
+            case R.id.action_block:
+                Assert.isTrue(mSelectedConversations.size() == 1);
+                mListener.onActionBarBlock(mSelectedConversations.valueAt(0));
+                return true;
+            case android.R.id.home:
+                mListener.onActionBarHome();
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public void onDestroyActionMode(ActionMode actionMode) {
+        mListener = null;
+        mSelectedConversations.clear();
+        mHasInflated = false;
+    }
+
+    public void toggleSelect(final ConversationListData listData,
+                             final ConversationListItemData conversationListItemData) {
+        Assert.notNull(conversationListItemData);
+        mBlockedSet = listData.getBlockedParticipants();
+        final String id = conversationListItemData.getConversationId();
+        if (mSelectedConversations.containsKey(id)) {
+            mSelectedConversations.remove(id);
+        } else {
+            mSelectedConversations.put(id, new SelectedConversation(conversationListItemData));
+        }
+
+        if (mSelectedConversations.isEmpty()) {
+            mListener.onActionBarHome();
+        } else {
+            updateActionIconsVisiblity();
+        }
+    }
+
+    public boolean isSelected(final String selectedId) {
+        return mSelectedConversations.containsKey(selectedId);
+    }
+
+    private void updateActionIconsVisiblity() {
+        if (!mHasInflated) {
+            return;
+        }
+
+        if (mSelectedConversations.size() == 1) {
+            final SelectedConversation conversation = mSelectedConversations.valueAt(0);
+            // The look up key is a key given to us by contacts app, so if we have a look up key,
+            // we know that the participant is already in contacts.
+            final boolean isInContacts = !TextUtils.isEmpty(conversation.participantLookupKey);
+            mAddContactMenuItem.setVisible(!conversation.isGroup && !isInContacts);
+            // ParticipantNormalizedDestination is always null for group conversations.
+            final String otherParticipant = conversation.otherParticipantNormalizedDestination;
+            mBlockMenuItem.setVisible(otherParticipant != null
+                    && !mBlockedSet.contains(otherParticipant));
+        } else {
+            mBlockMenuItem.setVisible(false);
+            mAddContactMenuItem.setVisible(false);
+        }
+
+        boolean hasCurrentlyArchived = false;
+        boolean hasCurrentlyUnarchived = false;
+        boolean hasCurrentlyOnNotification = false;
+        boolean hasCurrentlyOffNotification = false;
+        final Iterable<SelectedConversation> conversations = mSelectedConversations.values();
+        for (final SelectedConversation conversation : conversations) {
+            if (conversation.notificationEnabled) {
+                hasCurrentlyOnNotification = true;
+            } else {
+                hasCurrentlyOffNotification = true;
+            }
+
+            if (conversation.isArchived) {
+                hasCurrentlyArchived = true;
+            } else {
+                hasCurrentlyUnarchived = true;
+            }
+
+            // If we found at least one of each example we don't need to keep looping.
+            if (hasCurrentlyOffNotification && hasCurrentlyOnNotification &&
+                    hasCurrentlyArchived && hasCurrentlyUnarchived) {
+                break;
+            }
+        }
+        // If we have notification off conversations we show on button, if we have notification on
+        // conversation we show off button. We can show both if we have a mixture.
+        mNotificationOffMenuItem.setVisible(hasCurrentlyOnNotification);
+        mNotificationOnMenuItem.setVisible(hasCurrentlyOffNotification);
+
+        mArchiveMenuItem.setVisible(hasCurrentlyUnarchived);
+        mUnarchiveMenuItem.setVisible(hasCurrentlyArchived);
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java b/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java
new file mode 100644
index 0000000..9ac6e6b
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.app.Fragment;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.collection.ArrayMap;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.ui.BaseBugleActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaMetadataRetrieverWrapper;
+import com.android.messaging.util.FileUtil;
+import com.android.messaging.util.UriUtil;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+
+public class ShareIntentActivity extends BaseBugleActivity implements
+        ShareIntentFragment.HostInterface {
+
+    private MessageData mDraftMessage;
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Intent intent = getIntent();
+        if (Intent.ACTION_SEND.equals(intent.getAction()) &&
+                (!TextUtils.isEmpty(intent.getStringExtra("address")) ||
+                !TextUtils.isEmpty(intent.getStringExtra(Intent.EXTRA_EMAIL)))) {
+            // This is really more like a SENDTO intent because a destination is supplied.
+            // It's coming through the SEND intent because that's the intent that is used
+            // when invoking the chooser with Intent.createChooser().
+            final Intent convIntent = UIIntents.get().getLaunchConversationActivityIntent(this);
+            // Copy the important items from the original intent to the new intent.
+            convIntent.putExtras(intent);
+            convIntent.setAction(Intent.ACTION_SENDTO);
+            convIntent.setDataAndType(intent.getData(), intent.getType());
+            // We have to fire off the intent and finish before trying to show the fragment,
+            // otherwise we get some flashing.
+            startActivity(convIntent);
+            finish();
+            return;
+        }
+        new ShareIntentFragment().show(getFragmentManager(), "ShareIntentFragment");
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        final Intent intent = getIntent();
+        final String action = intent.getAction();
+
+        String sharedSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
+        if (sharedSubject == null) {
+            sharedSubject = intent.getStringExtra(Intent.EXTRA_TITLE);
+        }
+
+        if (Intent.ACTION_SEND.equals(action)) {
+            final Uri contentUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
+            if (UriUtil.isFileUri(contentUri)) {
+                LogUtil.i(
+                    LogUtil.BUGLE_TAG,
+                    "Ignoring attachment from file URI which are no longer supported.");
+                return;
+            }
+            final String contentType = extractContentType(contentUri, intent.getType());
+            if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
+                LogUtil.d(LogUtil.BUGLE_TAG, String.format(
+                        "onAttachFragment: contentUri=%s, intent.getType()=%s, inferredType=%s",
+                        contentUri, intent.getType(), contentType));
+            }
+            if (ContentType.TEXT_PLAIN.equals(contentType)) {
+                String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
+                if (sharedText == null) {
+                    // Try to get text string from content uri.
+                    sharedText = getTextStringFromContentUri(contentUri);
+                }
+                if (sharedText != null) {
+                    mDraftMessage = MessageData.createSharedMessage(sharedText, sharedSubject);
+                } else {
+                    mDraftMessage = null;
+                }
+            } else if (PendingAttachmentData.isSupportedMediaType(contentType)) {
+                if (contentUri != null) {
+                    mDraftMessage = MessageData.createSharedMessage(null, sharedSubject);
+                    addSharedPartToDraft(contentType, contentUri);
+                } else {
+                    mDraftMessage = null;
+                }
+            } else {
+                // Unsupported content type.
+                LogUtil.e(LogUtil.BUGLE_TAG, "Unsupported shared content type for " + contentUri
+                        + ": " + contentType + " (" + intent.getType() + ")");
+                mDraftMessage = null;
+            }
+        } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+            final String contentType = intent.getType();
+            // Handle sharing multiple contents.
+            final ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+            if (uris != null && !uris.isEmpty()) {
+                ArrayMap<Uri, String> uriMap = new ArrayMap<Uri, String>();
+                StringBuffer strBuffer = new StringBuffer();
+                for (final Uri uri : uris) {
+                    if (UriUtil.isFileUri(uri)) {
+                        LogUtil.i(LogUtil.BUGLE_TAG,
+                                "Ignoring attachment from file URI which are no longer supported.");
+                        continue;
+                    }
+                    final String actualContentType = extractContentType(uri, contentType);
+                    if (ContentType.TEXT_PLAIN.equals(actualContentType)) {
+                        // Try to get text string from content uri.
+                        String sharedText = getTextStringFromContentUri(uri);
+                        if (sharedText != null) {
+                            if (strBuffer.length() > 0) {
+                                strBuffer.append("\n");
+                            }
+                            strBuffer.append(sharedText);
+                        }
+                    } else if (PendingAttachmentData.isSupportedMediaType(actualContentType)) {
+                        uriMap.put(uri, actualContentType);
+                    } else {
+                        // Unsupported content type.
+                        LogUtil.e(LogUtil.BUGLE_TAG, "Unsupported shared content type for " + uri
+                                + ": " + actualContentType);
+                    }
+                }
+
+                if (strBuffer.length() > 0 || !uriMap.isEmpty()) {
+                    mDraftMessage =
+                            MessageData.createSharedMessage(strBuffer.toString(), sharedSubject);
+                    for (final Map.Entry<Uri, String> e : uriMap.entrySet()) {
+                        addSharedPartToDraft(e.getValue(), e.getKey());
+                    }
+                }
+            } else {
+                // No EXTRA_STREAM.
+                LogUtil.e(LogUtil.BUGLE_TAG, "No shared URI.");
+                mDraftMessage = null;
+            }
+        } else {
+            // Unsupported action.
+            Assert.fail("Unsupported action type for sharing: " + action);
+        }
+    }
+
+    private static String getTextStringFromContentUri(final Uri contentUri) {
+        if (contentUri == null) {
+            return null;
+        }
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        BufferedReader reader = null;
+        try {
+            final InputStream in = resolver.openInputStream(contentUri);
+            reader = new BufferedReader(new InputStreamReader(in));
+            String line = reader.readLine();
+            if (line == null) {
+                return null;
+            }
+            StringBuffer strBuffer = new StringBuffer(line);
+            while ((line = reader.readLine()) != null) {
+                strBuffer.append("\n").append(line);
+            }
+            return strBuffer.toString();
+        } catch (FileNotFoundException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Can not find contentUri " + contentUri);
+        } catch (IOException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Can not read contentUri", e);
+        } finally {
+            try {
+                if (reader != null) {
+                    reader.close();
+                }
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+        return null;
+    }
+
+    private static String extractContentType(final Uri uri, final String contentType) {
+        if (uri == null) {
+            return contentType;
+        }
+        // First try looking at file extension.  This is less reliable in some ways but it's
+        // recommended by
+        // https://developer.android.com/training/secure-file-sharing/retrieve-info.html
+        // Some implementations of MediaMetadataRetriever get things horribly
+        // wrong for common formats such as jpeg (reports as video/ffmpeg)
+        final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        final String typeFromExtension = resolver.getType(uri);
+        if (typeFromExtension != null) {
+            return typeFromExtension;
+        }
+        final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
+        try {
+            retriever.setDataSource(uri);
+            final String extractedType = retriever.extractMetadata(
+                    MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
+            if (extractedType != null) {
+                return extractedType;
+            }
+        } catch (final IOException e) {
+            LogUtil.i(LogUtil.BUGLE_TAG, "Could not determine type of " + uri, e);
+        } finally {
+            retriever.release();
+        }
+        return contentType;
+    }
+
+    private void addSharedPartToDraft(final String contentType, final Uri uri) {
+        if (FileUtil.isInPrivateDir(uri)) {
+            Assert.fail("Cannot send private file " + uri.toString());
+        } else {
+            mDraftMessage.addPart(
+                    PendingAttachmentData.createPendingAttachmentData(contentType, uri));
+        }
+    }
+
+    @Override
+    public void onConversationClick(final ConversationListItemData conversationListItemData) {
+        UIIntents.get().launchConversationActivity(
+                this, conversationListItemData.getConversationId(), mDraftMessage);
+        finish();
+    }
+
+    @Override
+    public void onCreateConversationClick() {
+        UIIntents.get().launchCreateNewConversationActivity(this, mDraftMessage);
+        finish();
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ShareIntentAdapter.java b/src/com/android/messaging/ui/conversationlist/ShareIntentAdapter.java
new file mode 100644
index 0000000..6d465ee
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ShareIntentAdapter.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.ui.CursorRecyclerAdapter;
+import com.android.messaging.ui.PersonItemView;
+import com.android.messaging.ui.PersonItemView.PersonItemViewListener;
+import com.android.messaging.util.PhoneUtils;
+
+/**
+ * Turn conversation rows into PeopleItemViews
+ */
+public class ShareIntentAdapter
+        extends CursorRecyclerAdapter<ShareIntentAdapter.ShareIntentViewHolder> {
+
+    public interface HostInterface {
+        void onConversationClicked(final ConversationListItemData conversationListItemData);
+    }
+
+    private final HostInterface mHostInterface;
+
+    public ShareIntentAdapter(final Context context, final Cursor cursor,
+            final HostInterface hostInterface) {
+        super(context, cursor, 0);
+        mHostInterface = hostInterface;
+        setHasStableIds(true);
+    }
+
+    @Override
+    public void bindViewHolder(final ShareIntentViewHolder holder, final Context context,
+            final Cursor cursor) {
+        holder.bind(cursor);
+    }
+
+    @Override
+    public ShareIntentViewHolder createViewHolder(final Context context,
+            final ViewGroup parent, final int viewType) {
+        final PersonItemView itemView = (PersonItemView) LayoutInflater.from(context).inflate(
+                R.layout.people_list_item_view, null);
+        return new ShareIntentViewHolder(itemView);
+    }
+
+    /**
+     * Holds a PersonItemView and keeps it synced with a ConversationListItemData.
+     */
+    public class ShareIntentViewHolder extends RecyclerView.ViewHolder implements
+            PersonItemView.PersonItemViewListener {
+        private final ConversationListItemData mData = new ConversationListItemData();
+        private final PersonItemData mItemData = new PersonItemData() {
+            @Override
+            public Uri getAvatarUri() {
+                return mData.getIcon() == null ? null : Uri.parse(mData.getIcon());
+            }
+
+            @Override
+            public String getDisplayName() {
+                return mData.getName();
+            }
+
+            @Override
+            public String getDetails() {
+                final String conversationName = mData.getName();
+                final String conversationPhone = PhoneUtils.getDefault().formatForDisplay(
+                        mData.getOtherParticipantNormalizedDestination());
+                if (conversationPhone == null || conversationPhone.equals(conversationName)) {
+                    return null;
+                }
+                return conversationPhone;
+            }
+
+            @Override
+            public Intent getClickIntent() {
+                return null;
+            }
+
+            @Override
+            public long getContactId() {
+                return ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED;
+            }
+
+            @Override
+            public String getLookupKey() {
+                return null;
+            }
+
+            @Override
+            public String getNormalizedDestination() {
+                return null;
+            }
+        };
+
+        public ShareIntentViewHolder(final PersonItemView itemView) {
+            super(itemView);
+            itemView.setListener(this);
+        }
+
+        public void bind(Cursor cursor) {
+            mData.bind(cursor);
+            ((PersonItemView) itemView).bind(mItemData);
+        }
+
+        @Override
+        public void onPersonClicked(PersonItemData data) {
+            mHostInterface.onConversationClicked(mData);
+        }
+
+        @Override
+        public boolean onPersonLongClicked(PersonItemData data) {
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationlist/ShareIntentFragment.java b/src/com/android/messaging/ui/conversationlist/ShareIntentFragment.java
new file mode 100644
index 0000000..beafb53
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationlist/ShareIntentFragment.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationlist;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.database.Cursor;
+import android.os.Bundle;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+import com.android.messaging.ui.ListEmptyView;
+import com.android.messaging.datamodel.DataModel;
+
+/**
+ * Allow user to pick conversation to which an incoming attachment will be shared.
+ */
+public class ShareIntentFragment extends DialogFragment implements ConversationListDataListener,
+        ShareIntentAdapter.HostInterface {
+    public static final String HIDE_NEW_CONVERSATION_BUTTON_KEY = "hide_conv_button_key";
+
+    public interface HostInterface {
+        public void onConversationClick(final ConversationListItemData conversationListItemData);
+        public void onCreateConversationClick();
+    }
+
+    private final Binding<ConversationListData> mListBinding = BindingBase.createBinding(this);
+    private RecyclerView mRecyclerView;
+    private ListEmptyView mEmptyListMessageView;
+    private ShareIntentAdapter mAdapter;
+    private HostInterface mHost;
+    private boolean mDismissed;
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public Dialog onCreateDialog(final Bundle bundle) {
+        final Activity activity = getActivity();
+        final LayoutInflater inflater = activity.getLayoutInflater();
+        View view = inflater.inflate(R.layout.share_intent_conversation_list_view, null);
+        mEmptyListMessageView = (ListEmptyView) view.findViewById(R.id.no_conversations_view);
+        mEmptyListMessageView.setImageHint(R.drawable.ic_oobe_conv_list);
+        // The default behavior for default layout param generation by LinearLayoutManager is to
+        // provide width and height of WRAP_CONTENT, but this is not desirable for
+        // ShareIntentFragment; the view in each row should be a width of MATCH_PARENT so that
+        // the entire row is tappable.
+        final LinearLayoutManager manager = new LinearLayoutManager(activity) {
+            @Override
+            public RecyclerView.LayoutParams generateDefaultLayoutParams() {
+                return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT);
+            }
+        };
+        mListBinding.getData().init(getLoaderManager(), mListBinding);
+        mAdapter = new ShareIntentAdapter(activity, null, this);
+        mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
+        mRecyclerView.setLayoutManager(manager);
+        mRecyclerView.setHasFixedSize(true);
+        mRecyclerView.setAdapter(mAdapter);
+        final Builder dialogBuilder = new AlertDialog.Builder(activity)
+                .setView(view)
+                .setTitle(R.string.share_intent_activity_label);
+
+        final Bundle arguments = getArguments();
+        if (arguments == null || !arguments.getBoolean(HIDE_NEW_CONVERSATION_BUTTON_KEY)) {
+            dialogBuilder.setPositiveButton(R.string.share_new_message, new OnClickListener() {
+                        @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                            mDismissed = true;
+                            mHost.onCreateConversationClick();
+                    }
+                });
+        }
+        return dialogBuilder.setNegativeButton(R.string.share_cancel, null)
+                .create();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        if (!mDismissed) {
+            final Activity activity = getActivity();
+            if (activity != null) {
+                activity.finish();
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc} from Fragment
+     */
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mListBinding.unbind();
+    }
+
+    @Override
+    public void onAttach(final Activity activity) {
+        super.onAttach(activity);
+        if (activity instanceof HostInterface) {
+            mHost = (HostInterface) activity;
+        }
+        mListBinding.bind(DataModel.get().createConversationListData(activity, this, false));
+    }
+
+    @Override
+    public void onConversationListCursorUpdated(final ConversationListData data,
+            final Cursor cursor) {
+        mListBinding.ensureBound(data);
+        mAdapter.swapCursor(cursor);
+        updateEmptyListUi(cursor == null || cursor.getCount() == 0);
+    }
+
+    /**
+     * {@inheritDoc} from SharIntentItemView.HostInterface
+     */
+    @Override
+    public void onConversationClicked(final ConversationListItemData conversationListItemData) {
+        mHost.onConversationClick(conversationListItemData);
+    }
+
+    // Show and hide empty list UI as needed with appropriate text based on view specifics
+    private void updateEmptyListUi(final boolean isEmpty) {
+        if (isEmpty) {
+            mEmptyListMessageView.setTextHint(R.string.conversation_list_empty_text);
+            mEmptyListMessageView.setVisibility(View.VISIBLE);
+        } else {
+            mEmptyListMessageView.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void setBlockedParticipantsAvailable(boolean blockedAvailable) {
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationsettings/CopyContactDetailDialog.java b/src/com/android/messaging/ui/conversationsettings/CopyContactDetailDialog.java
new file mode 100644
index 0000000..d727001
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationsettings/CopyContactDetailDialog.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationsettings;
+
+import android.app.AlertDialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.util.AccessibilityUtil;
+
+public class CopyContactDetailDialog implements DialogInterface.OnClickListener {
+
+    private final Context mContext;
+    private final String mContactDetail;
+
+    public CopyContactDetailDialog(final Context context, final String contactDetail) {
+        mContext = context;
+        mContactDetail = contactDetail;
+    }
+
+    public void show() {
+        new AlertDialog.Builder(mContext)
+                .setView(createBodyView())
+                .setTitle(R.string.copy_to_clipboard_dialog_title)
+                .setPositiveButton(R.string.copy_to_clipboard, this)
+                .show();
+    }
+
+    @Override
+    public void onClick(final DialogInterface dialog, final int which) {
+        final ClipboardManager clipboard =
+                (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+        clipboard.setPrimaryClip(ClipData.newPlainText(null /* label */, mContactDetail));
+    }
+
+    private View createBodyView() {
+        LayoutInflater inflater = (LayoutInflater) mContext
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        TextView textView = (TextView) inflater.inflate(R.layout.copy_contact_dialog_view, null,
+                false);
+        textView.setText(mContactDetail);
+        final String vocalizedDisplayName = AccessibilityUtil.getVocalizedPhoneNumber(
+                mContext.getResources(), mContactDetail);
+        textView.setContentDescription(vocalizedDisplayName);
+        return textView;
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsActivity.java b/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsActivity.java
new file mode 100644
index 0000000..f017328
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationsettings;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.MenuItem;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+
+/**
+ * Shows a list of participants in a conversation.
+ */
+public class PeopleAndOptionsActivity extends BugleActionBarActivity {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.people_and_options_activity);
+
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    @Override
+    public void onAttachFragment(final Fragment fragment) {
+        if (fragment instanceof PeopleAndOptionsFragment) {
+            final String conversationId =
+                    getIntent().getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+            Assert.notNull(conversationId);
+            final PeopleAndOptionsFragment peopleAndOptionsFragment =
+                    (PeopleAndOptionsFragment) fragment;
+            peopleAndOptionsFragment.setConversationId(conversationId);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                // Treat the home press as back press so that when we go back to
+                // ConversationActivity, it doesn't lose its original intent (conversation id etc.)
+                onBackPressed();
+                return true;
+
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsFragment.java b/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsFragment.java
new file mode 100644
index 0000000..b86d952
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationsettings/PeopleAndOptionsFragment.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationsettings;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.media.RingtoneManager;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantListItemData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
+import com.android.messaging.datamodel.data.PeopleOptionsItemData;
+import com.android.messaging.datamodel.data.PersonItemData;
+import com.android.messaging.ui.CompositeAdapter;
+import com.android.messaging.ui.PersonItemView;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.conversation.ConversationActivity;
+import com.android.messaging.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Shows a list of participants of a conversation and displays options.
+ */
+public class PeopleAndOptionsFragment extends Fragment
+        implements PeopleAndOptionsDataListener, PeopleOptionsItemView.HostInterface {
+    private ListView mListView;
+    private OptionsListAdapter mOptionsListAdapter;
+    private PeopleListAdapter mPeopleListAdapter;
+    private final Binding<PeopleAndOptionsData> mBinding =
+            BindingBase.createBinding(this);
+
+    private static final int REQUEST_CODE_RINGTONE_PICKER = 1000;
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mBinding.getData().init(getLoaderManager(), mBinding);
+    }
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.people_and_options_fragment, container, false);
+        mListView = (ListView) view.findViewById(android.R.id.list);
+        mPeopleListAdapter = new PeopleListAdapter(getActivity());
+        mOptionsListAdapter = new OptionsListAdapter();
+        final CompositeAdapter compositeAdapter = new CompositeAdapter(getActivity());
+        compositeAdapter.addPartition(new PeopleAndOptionsPartition(mOptionsListAdapter,
+                R.string.general_settings_title, false));
+        compositeAdapter.addPartition(new PeopleAndOptionsPartition(mPeopleListAdapter,
+                R.string.participant_list_title, true));
+        mListView.setAdapter(compositeAdapter);
+        return view;
+    }
+
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_RINGTONE_PICKER) {
+            final Parcelable pick = data.getParcelableExtra(
+                    RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+            final String pickedUri = pick == null ? "" : pick.toString();
+            mBinding.getData().setConversationNotificationSound(mBinding, pickedUri);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mBinding.unbind();
+    }
+
+    public void setConversationId(final String conversationId) {
+        Assert.isTrue(getView() == null);
+        Assert.notNull(conversationId);
+        mBinding.bind(DataModel.get().createPeopleAndOptionsData(conversationId, getActivity(),
+                this));
+    }
+
+    @Override
+    public void onOptionsCursorUpdated(final PeopleAndOptionsData data, final Cursor cursor) {
+        Assert.isTrue(cursor == null || cursor.getCount() == 1);
+        mBinding.ensureBound(data);
+        mOptionsListAdapter.swapCursor(cursor);
+    }
+
+    @Override
+    public void onParticipantsListLoaded(final PeopleAndOptionsData data,
+            final List<ParticipantData> participants) {
+        mBinding.ensureBound(data);
+        mPeopleListAdapter.updateParticipants(participants);
+        final ParticipantData otherParticipant = participants.size() == 1 ?
+                participants.get(0) : null;
+        mOptionsListAdapter.setOtherParticipant(otherParticipant);
+    }
+
+    @Override
+    public void onOptionsItemViewClicked(final PeopleOptionsItemData item,
+            final boolean isChecked) {
+        switch (item.getItemId()) {
+            case PeopleOptionsItemData.SETTING_NOTIFICATION_ENABLED:
+                mBinding.getData().enableConversationNotifications(mBinding, isChecked);
+                break;
+
+            case PeopleOptionsItemData.SETTING_NOTIFICATION_SOUND_URI:
+                final Intent ringtonePickerIntent = UIIntents.get().getRingtonePickerIntent(
+                        getString(R.string.notification_sound_pref_title),
+                        item.getRingtoneUri(), Settings.System.DEFAULT_NOTIFICATION_URI,
+                        RingtoneManager.TYPE_NOTIFICATION);
+                startActivityForResult(ringtonePickerIntent, REQUEST_CODE_RINGTONE_PICKER);
+                break;
+
+            case PeopleOptionsItemData.SETTING_NOTIFICATION_VIBRATION:
+                mBinding.getData().enableConversationNotificationVibration(mBinding,
+                        isChecked);
+                break;
+
+            case PeopleOptionsItemData.SETTING_BLOCKED:
+                if (item.getOtherParticipant().isBlocked()) {
+                    mBinding.getData().setDestinationBlocked(mBinding, false);
+                    break;
+                }
+                final Resources res = getResources();
+                final Activity activity = getActivity();
+                new AlertDialog.Builder(activity)
+                        .setTitle(res.getString(R.string.block_confirmation_title,
+                                item.getOtherParticipant().getDisplayDestination()))
+                        .setMessage(res.getString(R.string.block_confirmation_message))
+                        .setNegativeButton(android.R.string.cancel, null)
+                        .setPositiveButton(android.R.string.ok,
+                                new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface arg0, int arg1) {
+                                mBinding.getData().setDestinationBlocked(mBinding, true);
+                                activity.setResult(ConversationActivity.FINISH_RESULT_CODE);
+                                activity.finish();
+                            }
+                        })
+                        .create()
+                        .show();
+                break;
+        }
+    }
+
+    /**
+     * A simple adapter that takes a conversation metadata cursor and binds
+     * PeopleAndOptionsItemViews to individual COLUMNS of the first cursor record. (Note
+     * that this is not a CursorAdapter because it treats individual columns of the cursor as
+     * separate options to display for the conversation, e.g. notification settings).
+     */
+    private class OptionsListAdapter extends BaseAdapter {
+        private Cursor mOptionsCursor;
+        private ParticipantData mOtherParticipantData;
+
+        public Cursor swapCursor(final Cursor newCursor) {
+            final Cursor oldCursor = mOptionsCursor;
+            if (newCursor != oldCursor) {
+                mOptionsCursor = newCursor;
+                notifyDataSetChanged();
+            }
+            return oldCursor;
+        }
+
+        public void setOtherParticipant(final ParticipantData participantData) {
+            if (mOtherParticipantData != participantData) {
+                mOtherParticipantData = participantData;
+                notifyDataSetChanged();
+            }
+        }
+
+        @Override
+        public int getCount() {
+            int count = PeopleOptionsItemData.SETTINGS_COUNT;
+            if (mOtherParticipantData == null) {
+                count--;
+            }
+            return mOptionsCursor == null ? 0 : count;
+        }
+
+        @Override
+        public Object getItem(final int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(final int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(final int position, final View convertView, final ViewGroup parent) {
+            final PeopleOptionsItemView itemView;
+            if (convertView != null && convertView instanceof PeopleOptionsItemView) {
+                itemView = (PeopleOptionsItemView) convertView;
+            } else {
+                final LayoutInflater inflater = (LayoutInflater) getActivity()
+                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                itemView = (PeopleOptionsItemView)
+                        inflater.inflate(R.layout.people_options_item_view, parent, false);
+            }
+            mOptionsCursor.moveToFirst();
+            itemView.bind(mOptionsCursor, position, mOtherParticipantData,
+                    PeopleAndOptionsFragment.this);
+            return itemView;
+        }
+    }
+
+    /**
+     * An adapter that takes a list of ParticipantData and displays them as a list of
+     * ParticipantListItemViews.
+     */
+    private class PeopleListAdapter extends ArrayAdapter<ParticipantData> {
+        public PeopleListAdapter(final Context context) {
+            super(context, R.layout.people_list_item_view, new ArrayList<ParticipantData>());
+        }
+
+        public void updateParticipants(final List<ParticipantData> newList) {
+            clear();
+            addAll(newList);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public View getView(final int position, final View convertView, final ViewGroup parent) {
+            PersonItemView itemView;
+            final ParticipantData item = getItem(position);
+            if (convertView != null && convertView instanceof PersonItemView) {
+                itemView = (PersonItemView) convertView;
+            } else {
+                final LayoutInflater inflater = (LayoutInflater) getContext()
+                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                itemView = (PersonItemView) inflater.inflate(R.layout.people_list_item_view, parent,
+                        false);
+            }
+            final ParticipantListItemData itemData =
+                    DataModel.get().createParticipantListItemData(item);
+            itemView.bind(itemData);
+
+            // Any click on the row should have the same effect as clicking the avatar icon
+            final PersonItemView itemViewClosure = itemView;
+            itemView.setListener(new PersonItemView.PersonItemViewListener() {
+                @Override
+                public void onPersonClicked(final PersonItemData data) {
+                    itemViewClosure.performClickOnAvatar();
+                }
+
+                @Override
+                public boolean onPersonLongClicked(final PersonItemData data) {
+                    if (mBinding.isBound()) {
+                        final CopyContactDetailDialog dialog = new CopyContactDetailDialog(
+                                getContext(), data.getDetails());
+                        dialog.show();
+                        return true;
+                    }
+                    return false;
+                }
+            });
+            return itemView;
+        }
+    }
+
+    /**
+     * Represents a partition/section in the People & Options list (e.g. "general options" and
+     * "people in this conversation" sections).
+     */
+    private class PeopleAndOptionsPartition extends CompositeAdapter.Partition {
+        private final int mHeaderResId;
+        private final boolean mNeedDivider;
+
+        public PeopleAndOptionsPartition(final BaseAdapter adapter, final int headerResId,
+                final boolean needDivider) {
+            super(true /* showIfEmpty */, true /* hasHeader */, adapter);
+            mHeaderResId = headerResId;
+            mNeedDivider = needDivider;
+        }
+
+        @Override
+        public View getHeaderView(final View convertView, final ViewGroup parentView) {
+            View view = null;
+            if (convertView != null && convertView.getId() == R.id.people_and_options_header) {
+                view = convertView;
+            } else {
+                view = LayoutInflater.from(getActivity()).inflate(
+                        R.layout.people_and_options_section_header, parentView, false);
+            }
+            final TextView text = (TextView) view.findViewById(R.id.header_text);
+            final View divider = view.findViewById(R.id.divider);
+            text.setText(mHeaderResId);
+            divider.setVisibility(mNeedDivider ? View.VISIBLE : View.GONE);
+            return view;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/conversationsettings/PeopleOptionsItemView.java b/src/com/android/messaging/ui/conversationsettings/PeopleOptionsItemView.java
new file mode 100644
index 0000000..5b6f3b0
--- /dev/null
+++ b/src/com/android/messaging/ui/conversationsettings/PeopleOptionsItemView.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversationsettings;
+
+import android.content.Context;
+import android.database.Cursor;
+import androidx.appcompat.widget.SwitchCompat;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.PeopleOptionsItemData;
+import com.android.messaging.util.Assert;
+
+/**
+ * The view for a single entry in the options section of people & options activity.
+ */
+public class PeopleOptionsItemView extends LinearLayout {
+    /**
+     * Implemented by the host of this view that handles options click event.
+     */
+    public interface HostInterface {
+        void onOptionsItemViewClicked(PeopleOptionsItemData item, boolean isChecked);
+    }
+
+    private TextView mTitle;
+    private TextView mSubtitle;
+    private SwitchCompat mSwitch;
+    private final PeopleOptionsItemData mData;
+    private HostInterface mHostInterface;
+
+    public PeopleOptionsItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mData = DataModel.get().createPeopleOptionsItemData(context);
+    }
+
+    @Override
+    protected void onFinishInflate () {
+        mTitle = (TextView) findViewById(R.id.title);
+        mSubtitle = (TextView) findViewById(R.id.subtitle);
+        mSwitch = (SwitchCompat) findViewById(R.id.switch_button);
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                mHostInterface.onOptionsItemViewClicked(mData, !mData.getChecked());
+            }
+        });
+    }
+
+    public void bind(final Cursor cursor, final int columnIndex, ParticipantData otherParticipant,
+            final HostInterface hostInterface) {
+        Assert.isTrue(columnIndex < PeopleOptionsItemData.SETTINGS_COUNT && columnIndex >= 0);
+        mData.bind(cursor, otherParticipant, columnIndex);
+        mHostInterface = hostInterface;
+
+        mTitle.setText(mData.getTitle());
+        final String subtitle = mData.getSubtitle();
+        if (TextUtils.isEmpty(subtitle)) {
+            mSubtitle.setVisibility(GONE);
+        } else {
+            mSubtitle.setVisibility(VISIBLE);
+            mSubtitle.setText(subtitle);
+        }
+
+        if (mData.getCheckable()) {
+            mSwitch.setVisibility(VISIBLE);
+            mSwitch.setChecked(mData.getChecked());
+        } else {
+            mSwitch.setVisibility(GONE);
+        }
+
+        final boolean enabled = mData.getEnabled();
+        if (enabled != isEnabled()) {
+            mTitle.setEnabled(enabled);
+            mSubtitle.setEnabled(enabled);
+            mSwitch.setEnabled(enabled);
+            setAlpha(enabled ? 1.0f : 0.5f);
+            setEnabled(enabled);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/debug/DebugMmsConfigActivity.java b/src/com/android/messaging/ui/debug/DebugMmsConfigActivity.java
new file mode 100644
index 0000000..485dcf7
--- /dev/null
+++ b/src/com/android/messaging/ui/debug/DebugMmsConfigActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.debug;
+
+import android.os.Bundle;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.BaseBugleActivity;
+
+/**
+ * Show list of all MmsConfig key/value pairs and allow editing.
+ */
+public class DebugMmsConfigActivity extends BaseBugleActivity {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.debug_mmsconfig_activity);
+    }
+}
diff --git a/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java b/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java
new file mode 100644
index 0000000..f7da331
--- /dev/null
+++ b/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.debug;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.telephony.SubscriptionInfo;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.ui.debug.DebugMmsConfigItemView.MmsConfigItemListener;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Show list of all MmsConfig key/value pairs and allow editing.
+ */
+public class DebugMmsConfigFragment extends Fragment {
+    @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View fragmentView = inflater.inflate(R.layout.mms_config_debug_fragment, container,
+                false);
+        final ListView listView = (ListView) fragmentView.findViewById(android.R.id.list);
+        final Spinner spinner = (Spinner) fragmentView.findViewById(R.id.sim_selector);
+        final Integer[] subIdArray = getActiveSubIds();
+        ArrayAdapter<Integer> spinnerAdapter = new ArrayAdapter<Integer>(getActivity(),
+                android.R.layout.simple_spinner_item, subIdArray);
+        spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        spinner.setAdapter(spinnerAdapter);
+        spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                listView.setAdapter(new MmsConfigAdapter(getActivity(), subIdArray[position]));
+
+                final int[] mccmnc = PhoneUtils.get(subIdArray[position]).getMccMnc();
+                // Set the title with the mcc/mnc
+                final TextView title = (TextView) fragmentView.findViewById(R.id.sim_title);
+                title.setText("(" + mccmnc[0] + "/" + mccmnc[1] + ") " +
+                        getActivity().getString(R.string.debug_sub_id_spinner_text));
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+            }
+        });
+
+        return fragmentView;
+    }
+
+    public static Integer[] getActiveSubIds() {
+        if (!OsUtil.isAtLeastL_MR1()) {
+            return new Integer[] { ParticipantData.DEFAULT_SELF_SUB_ID };
+        }
+        final List<SubscriptionInfo> subRecords =
+                PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList();
+        if (subRecords == null) {
+            return new Integer[0];
+        }
+        final Integer[] retArray = new Integer[subRecords.size()];
+        for (int i = 0; i < subRecords.size(); i++) {
+            retArray[i] = subRecords.get(i).getSubscriptionId();
+        }
+        return retArray;
+    }
+
+    private class MmsConfigAdapter extends BaseAdapter implements
+            DebugMmsConfigItemView.MmsConfigItemListener {
+        private final LayoutInflater mInflater;
+        private final List<String> mKeys;
+        private final MmsConfig mMmsConfig;
+
+        public MmsConfigAdapter(Context context, int subId) {
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mMmsConfig = MmsConfig.get(subId);
+            mKeys = new ArrayList<>(mMmsConfig.keySet());
+            Iterator<String> it = mKeys.iterator();
+            while (it.hasNext()) {
+                // Remove a config if the MmsConfig.sKeyTypeMap doesn't have it.
+                if (MmsConfig.getKeyType(it.next()) == null) {
+                    it.remove();
+                }
+            }
+            Collections.sort(mKeys);
+        }
+
+        @Override
+        public View getView(final int position, final View convertView, final ViewGroup parent) {
+            final DebugMmsConfigItemView view;
+            if (convertView != null && convertView instanceof DebugMmsConfigItemView) {
+                view = (DebugMmsConfigItemView) convertView;
+            } else {
+                view = (DebugMmsConfigItemView) mInflater.inflate(
+                        R.layout.debug_mmsconfig_item_view, parent, false);
+            }
+            final String key = mKeys.get(position);
+            view.bind(key,
+                    MmsConfig.getKeyType(key),
+                    String.valueOf(mMmsConfig.getValue(key)),
+                    this);
+            return view;
+        }
+
+        @Override
+        public void onValueChanged(String key, String keyType, String value) {
+            mMmsConfig.update(keyType, key, value);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mKeys.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mKeys.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/debug/DebugMmsConfigItemView.java b/src/com/android/messaging/ui/debug/DebugMmsConfigItemView.java
new file mode 100644
index 0000000..7b899c0
--- /dev/null
+++ b/src/com/android/messaging/ui/debug/DebugMmsConfigItemView.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.debug;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnShowListener;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.util.LogUtil;
+
+public class DebugMmsConfigItemView extends LinearLayout implements OnClickListener,
+        OnCheckedChangeListener, DialogInterface.OnClickListener {
+
+    public interface MmsConfigItemListener {
+        void onValueChanged(String key, String keyType, String value);
+    }
+
+    private TextView mTitle;
+    private TextView mTextValue;
+    private Switch mSwitch;
+    private String mKey;
+    private String mKeyType;
+    private MmsConfigItemListener mListener;
+    private EditText mEditText;
+
+    public DebugMmsConfigItemView(Context context, AttributeSet attributeSet) {
+        super(context, attributeSet);
+    }
+
+    @Override
+    protected void onFinishInflate () {
+        mTitle = (TextView) findViewById(R.id.title);
+        mTextValue = (TextView) findViewById(R.id.text_value);
+        mSwitch = (Switch) findViewById(R.id.switch_button);
+        setOnClickListener(this);
+        mSwitch.setOnCheckedChangeListener(this);
+    }
+
+    public void bind(final String key, final String keyType, final String value,
+            final MmsConfigItemListener listener) {
+        mListener = listener;
+        mKey = key;
+        mKeyType = keyType;
+        mTitle.setText(key);
+
+        switch (keyType) {
+            case MmsConfig.KEY_TYPE_BOOL:
+                mSwitch.setVisibility(View.VISIBLE);
+                mTextValue.setVisibility(View.GONE);
+                mSwitch.setChecked(Boolean.valueOf(value));
+                break;
+            case MmsConfig.KEY_TYPE_STRING:
+            case MmsConfig.KEY_TYPE_INT:
+                mTextValue.setVisibility(View.VISIBLE);
+                mSwitch.setVisibility(View.GONE);
+                mTextValue.setText(value);
+                break;
+            default:
+                mTextValue.setVisibility(View.GONE);
+                mSwitch.setVisibility(View.GONE);
+                LogUtil.e(LogUtil.BUGLE_TAG, "Unexpected keytype: " + keyType);
+                break;
+        }
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        mListener.onValueChanged(mKey, mKeyType, String.valueOf(isChecked));
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (MmsConfig.KEY_TYPE_BOOL.equals(mKeyType)) {
+            return;
+        }
+        final Context context = getContext();
+        mEditText = new EditText(context);
+        mEditText.setText(mTextValue.getText());
+        mEditText.setFocusable(true);
+        if (MmsConfig.KEY_TYPE_INT.equals(mKeyType)) {
+            mEditText.setInputType(InputType.TYPE_CLASS_PHONE);
+        } else {
+            mEditText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+        }
+        final AlertDialog dialog = new AlertDialog.Builder(context)
+                .setTitle(mKey)
+                .setView(mEditText)
+                .setPositiveButton(android.R.string.ok, this)
+                .setNegativeButton(android.R.string.cancel, null)
+                .create();
+        dialog.setOnShowListener(new OnShowListener() {
+            @Override
+            public void onShow(DialogInterface dialog) {
+                mEditText.requestFocus();
+                mEditText.selectAll();
+                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE))
+                        .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
+            }
+        });
+        dialog.show();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mListener.onValueChanged(mKey, mKeyType, mEditText.getText().toString());
+    }
+}
diff --git a/src/com/android/messaging/ui/debug/DebugSmsMmsFromDumpFileDialogFragment.java b/src/com/android/messaging/ui/debug/DebugSmsMmsFromDumpFileDialogFragment.java
new file mode 100644
index 0000000..1aa8be3
--- /dev/null
+++ b/src/com/android/messaging/ui/debug/DebugSmsMmsFromDumpFileDialogFragment.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.debug;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.telephony.SmsMessage;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.action.ReceiveMmsMessageAction;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.receiver.SmsReceiver;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Class that displays UI for choosing SMS/MMS dump files for debugging
+ */
+public class DebugSmsMmsFromDumpFileDialogFragment extends DialogFragment {
+    public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
+    public static final String KEY_DUMP_FILES = "dump_files";
+    public static final String KEY_ACTION = "action";
+
+    public static final String ACTION_LOAD = "load";
+    public static final String ACTION_EMAIL = "email";
+
+    private String[] mDumpFiles;
+    private String mAction;
+
+    public static DebugSmsMmsFromDumpFileDialogFragment newInstance(final String[] dumpFiles,
+            final String action) {
+        final DebugSmsMmsFromDumpFileDialogFragment frag =
+                new DebugSmsMmsFromDumpFileDialogFragment();
+        final Bundle args = new Bundle();
+        args.putSerializable(KEY_DUMP_FILES, dumpFiles);
+        args.putString(KEY_ACTION, action);
+        frag.setArguments(args);
+        return frag;
+    }
+
+    @Override
+    public Dialog onCreateDialog(final Bundle savedInstanceState) {
+        final Bundle args = getArguments();
+        mDumpFiles = (String[]) args.getSerializable(KEY_DUMP_FILES);
+        mAction = args.getString(KEY_ACTION);
+
+        final LayoutInflater inflater = getActivity().getLayoutInflater();
+        final View layout = inflater.inflate(
+                R.layout.debug_sms_mms_from_dump_file_dialog, null/*root*/);
+        final ListView list = (ListView) layout.findViewById(R.id.dump_file_list);
+        list.setAdapter(new DumpFileListAdapter(getActivity(), mDumpFiles));
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        final Resources resources = getResources();
+        if (ACTION_LOAD.equals(mAction)) {
+            builder.setTitle(resources.getString(
+                    R.string.load_sms_mms_from_dump_file_dialog_title));
+        } else if (ACTION_EMAIL.equals(mAction)) {
+            builder.setTitle(resources.getString(
+                    R.string.email_sms_mms_from_dump_file_dialog_title));
+        }
+        builder.setView(layout);
+        return builder.create();
+    }
+
+    private class DumpFileListAdapter extends ArrayAdapter<String> {
+        public DumpFileListAdapter(final Context context, final String[] dumpFiles) {
+            super(context, R.layout.sms_mms_dump_file_list_item, dumpFiles);
+        }
+
+        @Override
+        public View getView(final int position, final View view, final ViewGroup parent) {
+            TextView actionItemView;
+            if (view == null || !(view instanceof TextView)) {
+                final LayoutInflater inflater = LayoutInflater.from(getContext());
+                actionItemView = (TextView) inflater.inflate(
+                        R.layout.sms_mms_dump_file_list_item, parent, false);
+            } else {
+                actionItemView = (TextView) view;
+            }
+
+            final String file = getItem(position);
+            actionItemView.setText(file);
+            actionItemView.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(final View view) {
+                    dismiss();
+                    if (ACTION_LOAD.equals(mAction)) {
+                        receiveFromDumpFile(file);
+                    } else if (ACTION_EMAIL.equals(mAction)) {
+                        emailDumpFile(file);
+                    }
+                }
+            });
+            return actionItemView;
+        }
+    }
+
+    /**
+     * Load MMS/SMS from the dump file
+     */
+    private void receiveFromDumpFile(final String dumpFileName) {
+        if (dumpFileName.startsWith(MmsUtils.SMS_DUMP_PREFIX)) {
+            final SmsMessage[] messages = DebugUtils.retreiveSmsFromDumpFile(dumpFileName);
+            if (messages != null) {
+                SmsReceiver.deliverSmsMessages(getActivity(), ParticipantData.DEFAULT_SELF_SUB_ID,
+                        0, messages);
+            } else {
+                LogUtil.e(LogUtil.BUGLE_TAG,
+                        "receiveFromDumpFile: invalid sms dump file " + dumpFileName);
+            }
+        } else if (dumpFileName.startsWith(MmsUtils.MMS_DUMP_PREFIX)) {
+            final byte[] data = MmsUtils.createDebugNotificationInd(dumpFileName);
+            if (data != null) {
+                final ReceiveMmsMessageAction action = new ReceiveMmsMessageAction(
+                        ParticipantData.DEFAULT_SELF_SUB_ID, data);
+                action.start();
+            } else {
+                LogUtil.e(LogUtil.BUGLE_TAG,
+                        "receiveFromDumpFile: invalid mms dump file " + dumpFileName);
+            }
+        } else {
+            LogUtil.e(LogUtil.BUGLE_TAG,
+                    "receiveFromDumpFile: invalid dump file name " + dumpFileName);
+        }
+    }
+
+    /**
+     * Launch email app to send the dump file
+     */
+    private void emailDumpFile(final String file) {
+        final Resources resources = getResources();
+        final String fileLocation = "file://"
+                + Environment.getExternalStorageDirectory() + "/" + file;
+        final Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+        sharingIntent.setType(APPLICATION_OCTET_STREAM);
+        sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(fileLocation));
+        sharingIntent.putExtra(Intent.EXTRA_SUBJECT,
+                resources.getString(R.string.email_sms_mms_dump_file_subject));
+        getActivity().startActivity(Intent.createChooser(sharingIntent,
+                resources.getString(R.string.email_sms_mms_dump_file_chooser_title)));
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/AudioLevelSource.java b/src/com/android/messaging/ui/mediapicker/AudioLevelSource.java
new file mode 100644
index 0000000..a211058
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/AudioLevelSource.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import com.google.common.base.Preconditions;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Keeps track of the speech level as last observed by the recognition
+ * engine as microphone data flows through it. Can be polled by the UI to
+ * animate its views.
+ */
+@ThreadSafe
+public class AudioLevelSource {
+    private volatile int mSpeechLevel;
+    private volatile Listener mListener;
+
+    public static final int LEVEL_UNKNOWN = -1;
+
+    public interface Listener {
+        void onSpeechLevel(int speechLevel);
+    }
+
+    public void setSpeechLevel(int speechLevel) {
+        Preconditions.checkArgument(speechLevel >= 0 && speechLevel <= 100 ||
+                speechLevel == LEVEL_UNKNOWN);
+        mSpeechLevel = speechLevel;
+        maybeNotify();
+    }
+
+    public int getSpeechLevel() {
+        return mSpeechLevel;
+    }
+
+    public void reset() {
+        setSpeechLevel(LEVEL_UNKNOWN);
+    }
+
+    public boolean isValid() {
+        return mSpeechLevel > 0;
+    }
+
+    private void maybeNotify() {
+        final Listener l = mListener;
+        if (l != null) {
+            l.onSpeechLevel(mSpeechLevel);
+        }
+    }
+
+    public synchronized void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    public synchronized void clearListener(Listener listener) {
+        if (mListener == listener) {
+            mListener = null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/AudioMediaChooser.java b/src/com/android/messaging/ui/mediapicker/AudioMediaChooser.java
new file mode 100644
index 0000000..5d79293
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/AudioMediaChooser.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Chooser which allows the user to record audio
+ */
+class AudioMediaChooser extends MediaChooser implements
+        AudioRecordView.HostInterface {
+    private View mEnabledView;
+    private View mMissingPermissionView;
+
+    AudioMediaChooser(final MediaPicker mediaPicker) {
+        super(mediaPicker);
+    }
+
+    @Override
+    public int getSupportedMediaTypes() {
+        return MediaPicker.MEDIA_TYPE_AUDIO;
+    }
+
+    @Override
+    public int getIconResource() {
+        return R.drawable.ic_audio_light;
+    }
+
+    @Override
+    public int getIconDescriptionResource() {
+        return R.string.mediapicker_audioChooserDescription;
+    }
+
+    @Override
+    public void onAudioRecorded(final MessagePartData item) {
+        mMediaPicker.dispatchItemsSelected(item, true);
+    }
+
+    @Override
+    public void setThemeColor(final int color) {
+        if (mView != null) {
+            ((AudioRecordView) mView).setThemeColor(color);
+        }
+    }
+
+    @Override
+    protected View createView(final ViewGroup container) {
+        final LayoutInflater inflater = getLayoutInflater();
+        final AudioRecordView view = (AudioRecordView) inflater.inflate(
+                R.layout.mediapicker_audio_chooser,
+                container /* root */,
+                false /* attachToRoot */);
+        view.setHostInterface(this);
+        view.setThemeColor(mMediaPicker.getConversationThemeColor());
+        mEnabledView = view.findViewById(R.id.mediapicker_enabled);
+        mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
+        return view;
+    }
+
+    @Override
+    int getActionBarTitleResId() {
+        return R.string.mediapicker_audio_title;
+    }
+
+    @Override
+    public boolean isHandlingTouch() {
+        // Whenever the user is in the process of recording audio, we want to allow the user
+        // to move the finger within the panel without interpreting that as dragging the media
+        // picker panel.
+        return ((AudioRecordView) mView).shouldHandleTouch();
+    }
+
+    @Override
+    public void stopTouchHandling() {
+        ((AudioRecordView) mView).stopTouchHandling();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mView != null) {
+            ((AudioRecordView) mView).onPause();
+        }
+    }
+
+    @Override
+    protected void setSelected(final boolean selected) {
+        super.setSelected(selected);
+        if (selected && !OsUtil.hasRecordAudioPermission()) {
+            requestRecordAudioPermission();
+        }
+    }
+
+    private void requestRecordAudioPermission() {
+        mMediaPicker.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO },
+                MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE);
+    }
+
+    @Override
+    protected void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (requestCode == MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE) {
+            final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+            mEnabledView.setVisibility(permissionGranted ? View.VISIBLE : View.GONE);
+            mMissingPermissionView.setVisibility(permissionGranted ? View.GONE : View.VISIBLE);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/AudioRecordView.java b/src/com/android/messaging/ui/mediapicker/AudioRecordView.java
new file mode 100644
index 0000000..fba493f
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/AudioRecordView.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.media.MediaRecorder;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
+import com.android.messaging.datamodel.data.MediaPickerMessagePartData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.MediaUtil.OnCompletionListener;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.ThreadUtil;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Hosts an audio recorder with tap and hold to record functionality.
+ */
+public class AudioRecordView extends FrameLayout implements
+        MediaRecorder.OnErrorListener,
+        MediaRecorder.OnInfoListener {
+    /**
+     * An interface that communicates with the hosted AudioRecordView.
+     */
+    public interface HostInterface extends DraftMessageSubscriptionDataProvider {
+        void onAudioRecorded(final MessagePartData item);
+    }
+
+    /** The initial state, the user may press and hold to start recording */
+    private static final int MODE_IDLE = 1;
+
+    /** The user has pressed the record button and we are playing the sound indicating the
+     *  start of recording session. Don't record yet since we don't want the beeping sound
+     *  to get into the recording. */
+    private static final int MODE_STARTING = 2;
+
+    /** When the user is actively recording */
+    private static final int MODE_RECORDING = 3;
+
+    /** When the user has finished recording, we need to record for some additional time. */
+    private static final int MODE_STOPPING = 4;
+
+    // Bug: 16020175: The framework's MediaRecorder would cut off the ending portion of the
+    // recorded audio by about half a second. To mitigate this issue, we continue the recording
+    // for some extra time before stopping it.
+    private static final int AUDIO_RECORD_ENDING_BUFFER_MILLIS = 500;
+
+    /**
+     * The minimum duration of any recording. Below this threshold, it will be treated as if the
+     * user clicked the record button and inform the user to tap and hold to record.
+     */
+    private static final int AUDIO_RECORD_MINIMUM_DURATION_MILLIS = 300;
+
+    // For accessibility, the touchable record button is bigger than the record button visual.
+    private ImageView mRecordButtonVisual;
+    private View mRecordButton;
+    private SoundLevels mSoundLevels;
+    private TextView mHintTextView;
+    private PausableChronometer mTimerTextView;
+    private LevelTrackingMediaRecorder mMediaRecorder;
+    private long mAudioRecordStartTimeMillis;
+
+    private int mCurrentMode = MODE_IDLE;
+    private HostInterface mHostInterface;
+    private int mThemeColor;
+
+    public AudioRecordView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mMediaRecorder = new LevelTrackingMediaRecorder();
+    }
+
+    public void setHostInterface(final HostInterface hostInterface) {
+        mHostInterface = hostInterface;
+    }
+
+    @VisibleForTesting
+    public void testSetMediaRecorder(final LevelTrackingMediaRecorder recorder) {
+        mMediaRecorder = recorder;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSoundLevels = (SoundLevels) findViewById(R.id.sound_levels);
+        mRecordButtonVisual = (ImageView) findViewById(R.id.record_button_visual);
+        mRecordButton = findViewById(R.id.record_button);
+        mHintTextView = (TextView) findViewById(R.id.hint_text);
+        mTimerTextView = (PausableChronometer) findViewById(R.id.timer_text);
+        mSoundLevels.setLevelSource(mMediaRecorder.getLevelSource());
+        mRecordButton.setOnTouchListener(new OnTouchListener() {
+            @Override
+            public boolean onTouch(final View v, final MotionEvent event) {
+                final int action = event.getActionMasked();
+                switch (action) {
+                    case MotionEvent.ACTION_DOWN:
+                        onRecordButtonTouchDown();
+
+                        // Don't let the record button handle the down event to let it fall through
+                        // so that we can handle it for the entire panel in onTouchEvent(). This is
+                        // done so that: 1) the user taps on the record button to start recording
+                        // 2) the entire panel owns the touch event so we'd keep recording even
+                        // if the user moves outside the button region.
+                        return false;
+                }
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public boolean onTouchEvent(final MotionEvent event) {
+        final int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                return shouldHandleTouch();
+
+            case MotionEvent.ACTION_MOVE:
+                return true;
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                return onRecordButtonTouchUp();
+        }
+        return super.onTouchEvent(event);
+    }
+
+    public void onPause() {
+        // The conversation draft cannot take any updates when it's paused. Therefore, forcibly
+        // stop recording on pause.
+        stopRecording();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        stopRecording();
+    }
+
+    private boolean isRecording() {
+        return mMediaRecorder.isRecording() && mCurrentMode == MODE_RECORDING;
+    }
+
+    public boolean shouldHandleTouch() {
+        return mCurrentMode != MODE_IDLE;
+    }
+
+    public void stopTouchHandling() {
+        setMode(MODE_IDLE);
+        stopRecording();
+    }
+
+    private void setMode(final int mode) {
+        if (mCurrentMode != mode) {
+            mCurrentMode = mode;
+            updateVisualState();
+        }
+    }
+
+    private void updateVisualState() {
+        switch (mCurrentMode) {
+            case MODE_IDLE:
+                mHintTextView.setVisibility(VISIBLE);
+                mHintTextView.setTypeface(null, Typeface.NORMAL);
+                mTimerTextView.setVisibility(GONE);
+                mSoundLevels.setEnabled(false);
+                mTimerTextView.stop();
+                break;
+
+            case MODE_RECORDING:
+            case MODE_STOPPING:
+                mHintTextView.setVisibility(GONE);
+                mTimerTextView.setVisibility(VISIBLE);
+                mSoundLevels.setEnabled(true);
+                mTimerTextView.restart();
+                break;
+
+            case MODE_STARTING:
+                break;  // No-Op.
+
+            default:
+                Assert.fail("invalid mode for AudioRecordView!");
+                break;
+        }
+        updateRecordButtonAppearance();
+    }
+
+    public void setThemeColor(final int color) {
+        mThemeColor = color;
+        updateRecordButtonAppearance();
+    }
+
+    private void updateRecordButtonAppearance() {
+        final Drawable foregroundDrawable = getResources().getDrawable(R.drawable.ic_mp_audio_mic);
+        final GradientDrawable backgroundDrawable = ((GradientDrawable) getResources()
+                .getDrawable(R.drawable.audio_record_control_button_background));
+        if (isRecording()) {
+            foregroundDrawable.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
+            backgroundDrawable.setColor(mThemeColor);
+        } else {
+            foregroundDrawable.setColorFilter(mThemeColor, PorterDuff.Mode.SRC_ATOP);
+            backgroundDrawable.setColor(Color.WHITE);
+        }
+        mRecordButtonVisual.setImageDrawable(foregroundDrawable);
+        mRecordButtonVisual.setBackground(backgroundDrawable);
+    }
+
+    @VisibleForTesting
+    boolean onRecordButtonTouchDown() {
+        if (!mMediaRecorder.isRecording() && mCurrentMode == MODE_IDLE) {
+            setMode(MODE_STARTING);
+            playAudioStartSound(new OnCompletionListener() {
+                @Override
+                public void onCompletion() {
+                    // Double-check the current mode before recording since the user may have
+                    // lifted finger from the button before the beeping sound is played through.
+                    final int maxSize = MmsConfig.get(mHostInterface.getConversationSelfSubId())
+                            .getMaxMessageSize();
+                    if (mCurrentMode == MODE_STARTING &&
+                            mMediaRecorder.startRecording(AudioRecordView.this,
+                                    AudioRecordView.this, maxSize)) {
+                        setMode(MODE_RECORDING);
+                    }
+                }
+            });
+            mAudioRecordStartTimeMillis = System.currentTimeMillis();
+            return true;
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    boolean onRecordButtonTouchUp() {
+        if (System.currentTimeMillis() - mAudioRecordStartTimeMillis <
+                AUDIO_RECORD_MINIMUM_DURATION_MILLIS) {
+            // The recording is too short, bolden the hint text to instruct the user to
+            // "tap+hold" to record audio.
+            final Uri outputUri = stopRecording();
+            if (outputUri != null) {
+                SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                    @Override
+                    public void run() {
+                        Factory.get().getApplicationContext().getContentResolver().delete(
+                                outputUri, null, null);
+                    }
+                });
+            }
+            setMode(MODE_IDLE);
+            mHintTextView.setTypeface(null, Typeface.BOLD);
+        } else if (isRecording()) {
+            // Record for some extra time to ensure the ending part is saved.
+            setMode(MODE_STOPPING);
+            ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    onFinishedRecording();
+                }
+            }, AUDIO_RECORD_ENDING_BUFFER_MILLIS);
+        } else {
+            setMode(MODE_IDLE);
+        }
+        return true;
+    }
+
+    private Uri stopRecording() {
+        if (mMediaRecorder.isRecording()) {
+            return mMediaRecorder.stopRecording();
+        }
+        return null;
+    }
+
+    @Override   // From MediaRecorder.OnInfoListener
+    public void onInfo(final MediaRecorder mr, final int what, final int extra) {
+        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
+            // Max size reached. Finish recording immediately.
+            LogUtil.i(LogUtil.BUGLE_TAG, "Max size reached while recording audio");
+            onFinishedRecording();
+        } else {
+            // These are unknown errors.
+            onErrorWhileRecording(what, extra);
+        }
+    }
+
+    @Override   // From MediaRecorder.OnErrorListener
+    public void onError(final MediaRecorder mr, final int what, final int extra) {
+        onErrorWhileRecording(what, extra);
+    }
+
+    private void onErrorWhileRecording(final int what, final int extra) {
+        LogUtil.e(LogUtil.BUGLE_TAG, "Error occurred during audio recording what=" + what +
+                ", extra=" + extra);
+        UiUtils.showToastAtBottom(R.string.audio_recording_error);
+        setMode(MODE_IDLE);
+        stopRecording();
+    }
+
+    private void onFinishedRecording() {
+        final Uri outputUri = stopRecording();
+        if (outputUri != null) {
+            final Rect startRect = new Rect();
+            mRecordButtonVisual.getGlobalVisibleRect(startRect);
+            final MediaPickerMessagePartData audioItem =
+                    new MediaPickerMessagePartData(startRect,
+                            ContentType.AUDIO_3GPP, outputUri, 0, 0);
+            mHostInterface.onAudioRecorded(audioItem);
+        }
+        playAudioEndSound();
+        setMode(MODE_IDLE);
+    }
+
+    private void playAudioStartSound(final OnCompletionListener completionListener) {
+        MediaUtil.get().playSound(getContext(), R.raw.audio_initiate, completionListener);
+    }
+
+    private void playAudioEndSound() {
+        MediaUtil.get().playSound(getContext(), R.raw.audio_end, null);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/CameraManager.java b/src/com/android/messaging/ui/mediapicker/CameraManager.java
new file mode 100644
index 0000000..fb5c9bf
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/CameraManager.java
@@ -0,0 +1,1201 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
+import android.media.MediaRecorder;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Looper;
+import androidx.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.OrientationEventListener;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.ui.mediapicker.camerafocus.FocusOverlayManager;
+import com.android.messaging.ui.mediapicker.camerafocus.RenderOverlay;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Class which manages interactions with the camera, but does not do any UI.  This class is
+ * designed to be a singleton to ensure there is one component managing the camera and releasing
+ * the native resources.
+ * In order to acquire a camera, a caller must:
+ * <ul>
+ *     <li>Call selectCamera to select front or back camera
+ *     <li>Call setSurface to control where the preview is shown
+ *     <li>Call openCamera to request the camera start preview
+ * </ul>
+ * Callers should call onPause and onResume to ensure that the camera is release while the activity
+ * is not active.
+ * This class is not thread safe.  It should only be called from one thread (the UI thread or test
+ * thread)
+ */
+class CameraManager implements FocusOverlayManager.Listener {
+    /**
+     * Wrapper around the framework camera API to allow mocking different hardware scenarios while
+     * unit testing
+     */
+    interface CameraWrapper {
+        int getNumberOfCameras();
+        void getCameraInfo(int index, CameraInfo cameraInfo);
+        Camera open(int cameraId);
+        /** Add a wrapper for release because a final method cannot be mocked */
+        void release(Camera camera);
+    }
+
+    /**
+     * Callbacks for the camera manager listener
+     */
+    interface CameraManagerListener {
+        void onCameraError(int errorCode, Exception e);
+        void onCameraChanged();
+    }
+
+    /**
+     * Callback when taking image or video
+     */
+    interface MediaCallback {
+        static final int MEDIA_CAMERA_CHANGED = 1;
+        static final int MEDIA_NO_DATA = 2;
+
+        void onMediaReady(Uri uriToMedia, String contentType, int width, int height);
+        void onMediaFailed(Exception exception);
+        void onMediaInfo(int what);
+    }
+
+    // Error codes
+    static final int ERROR_OPENING_CAMERA = 1;
+    static final int ERROR_SHOWING_PREVIEW = 2;
+    static final int ERROR_INITIALIZING_VIDEO = 3;
+    static final int ERROR_STORAGE_FAILURE = 4;
+    static final int ERROR_RECORDING_VIDEO = 5;
+    static final int ERROR_HARDWARE_ACCELERATION_DISABLED = 6;
+    static final int ERROR_TAKING_PICTURE = 7;
+
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final int NO_CAMERA_SELECTED = -1;
+
+    private static CameraManager sInstance;
+
+    /** Default camera wrapper which directs calls to the framework APIs */
+    private static CameraWrapper sCameraWrapper = new CameraWrapper() {
+        @Override
+        public int getNumberOfCameras() {
+            return Camera.getNumberOfCameras();
+        }
+
+        @Override
+        public void getCameraInfo(final int index, final CameraInfo cameraInfo) {
+            Camera.getCameraInfo(index, cameraInfo);
+        }
+
+        @Override
+        public Camera open(final int cameraId) {
+            return Camera.open(cameraId);
+        }
+
+        @Override
+        public void release(final Camera camera) {
+            camera.release();
+        }
+    };
+
+    /** The CameraInfo for the currently selected camera */
+    private final CameraInfo mCameraInfo;
+
+    /**
+     * The index of the selected camera or NO_CAMERA_SELECTED if a camera hasn't been selected yet
+     */
+    private int mCameraIndex;
+
+    /** True if the device has front and back cameras */
+    private final boolean mHasFrontAndBackCamera;
+
+    /** True if the camera should be open (may not yet be actually open) */
+    private boolean mOpenRequested;
+
+    /** True if the camera is requested to be in video mode */
+    private boolean mVideoModeRequested;
+
+    /** The media recorder for video mode */
+    private MmsVideoRecorder mMediaRecorder;
+
+    /** Callback to call with video recording updates */
+    private MediaCallback mVideoCallback;
+
+    /** The preview view to show the preview on */
+    private CameraPreview mCameraPreview;
+
+    /** The helper classs to handle orientation changes */
+    private OrientationHandler mOrientationHandler;
+
+    /** Tracks whether the preview has hardware acceleration */
+    private boolean mIsHardwareAccelerationSupported;
+
+    /**
+     * The task for opening the camera, so it doesn't block the UI thread
+     * Using AsyncTask rather than SafeAsyncTask because the tasks need to be serialized, but don't
+     * need to be on the UI thread
+     * TODO: If we have other AyncTasks (not SafeAsyncTasks) this may contend and we may
+     * need to create a dedicated thread, or synchronize the threads in the thread pool
+     */
+    private AsyncTask<Integer, Void, Camera> mOpenCameraTask;
+
+    /**
+     * The camera index that is queued to be opened, but not completed yet, or NO_CAMERA_SELECTED if
+     * no open task is pending
+     */
+    private int mPendingOpenCameraIndex = NO_CAMERA_SELECTED;
+
+    /** The instance of the currently opened camera */
+    private Camera mCamera;
+
+    /** The rotation of the screen relative to the camera's natural orientation */
+    private int mRotation;
+
+    /** The callback to notify when errors or other events occur */
+    private CameraManagerListener mListener;
+
+    /** True if the camera is currently in the process of taking an image */
+    private boolean mTakingPicture;
+
+    /** Provides subscription-related data to access per-subscription configurations. */
+    private DraftMessageSubscriptionDataProvider mSubscriptionDataProvider;
+
+    /** Manages auto focus visual and behavior */
+    private final FocusOverlayManager mFocusOverlayManager;
+
+    private CameraManager() {
+        mCameraInfo = new CameraInfo();
+        mCameraIndex = NO_CAMERA_SELECTED;
+
+        // Check to see if a front and back camera exist
+        boolean hasFrontCamera = false;
+        boolean hasBackCamera = false;
+        final CameraInfo cameraInfo = new CameraInfo();
+        final int cameraCount = sCameraWrapper.getNumberOfCameras();
+        try {
+            for (int i = 0; i < cameraCount; i++) {
+                sCameraWrapper.getCameraInfo(i, cameraInfo);
+                if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
+                    hasFrontCamera = true;
+                } else if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
+                    hasBackCamera = true;
+                }
+                if (hasFrontCamera && hasBackCamera) {
+                    break;
+                }
+            }
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "Unable to load camera info", e);
+        }
+        mHasFrontAndBackCamera = hasFrontCamera && hasBackCamera;
+        mFocusOverlayManager = new FocusOverlayManager(this, Looper.getMainLooper());
+
+        // Assume the best until we are proven otherwise
+        mIsHardwareAccelerationSupported = true;
+    }
+
+    /** Gets the singleton instance */
+    static CameraManager get() {
+        if (sInstance == null) {
+            sInstance = new CameraManager();
+        }
+        return sInstance;
+    }
+
+    /** Allows tests to inject a custom camera wrapper */
+    @VisibleForTesting
+    static void setCameraWrapper(final CameraWrapper cameraWrapper) {
+        sCameraWrapper = cameraWrapper;
+        sInstance = null;
+    }
+
+    /**
+     * Sets the surface to use to display the preview
+     * This must only be called AFTER the CameraPreview has a texture ready
+     * @param preview The preview surface view
+     */
+    void setSurface(final CameraPreview preview) {
+        if (preview == mCameraPreview) {
+            return;
+        }
+
+        if (preview != null) {
+            Assert.isTrue(preview.isValid());
+            preview.setOnTouchListener(new View.OnTouchListener() {
+                @Override
+                public boolean onTouch(final View view, final MotionEvent motionEvent) {
+                    if ((motionEvent.getActionMasked() & MotionEvent.ACTION_UP) ==
+                            MotionEvent.ACTION_UP) {
+                        mFocusOverlayManager.setPreviewSize(view.getWidth(), view.getHeight());
+                        mFocusOverlayManager.onSingleTapUp(
+                                (int) motionEvent.getX() + view.getLeft(),
+                                (int) motionEvent.getY() + view.getTop());
+                    }
+                    return true;
+                }
+            });
+        }
+        mCameraPreview = preview;
+        tryShowPreview();
+    }
+
+    void setRenderOverlay(final RenderOverlay renderOverlay) {
+        mFocusOverlayManager.setFocusRenderer(renderOverlay != null ?
+                renderOverlay.getPieRenderer() : null);
+    }
+
+    /** Convenience function to swap between front and back facing cameras */
+    void swapCamera() {
+        Assert.isTrue(mCameraIndex >= 0);
+        selectCamera(mCameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT ?
+                CameraInfo.CAMERA_FACING_BACK :
+                CameraInfo.CAMERA_FACING_FRONT);
+    }
+
+    /**
+     * Selects the first camera facing the desired direction, or the first camera if there is no
+     * camera in the desired direction
+     * @param desiredFacing One of the CameraInfo.CAMERA_FACING_* constants
+     * @return True if a camera was selected, or false if selecting a camera failed
+     */
+    boolean selectCamera(final int desiredFacing) {
+        try {
+            // We already selected a camera facing that direction
+            if (mCameraIndex >= 0 && mCameraInfo.facing == desiredFacing) {
+                return true;
+            }
+
+            final int cameraCount = sCameraWrapper.getNumberOfCameras();
+            Assert.isTrue(cameraCount > 0);
+
+            mCameraIndex = NO_CAMERA_SELECTED;
+            setCamera(null);
+            final CameraInfo cameraInfo = new CameraInfo();
+            for (int i = 0; i < cameraCount; i++) {
+                sCameraWrapper.getCameraInfo(i, cameraInfo);
+                if (cameraInfo.facing == desiredFacing) {
+                    mCameraIndex = i;
+                    sCameraWrapper.getCameraInfo(i, mCameraInfo);
+                    break;
+                }
+            }
+
+            // There's no camera in the desired facing direction, just select the first camera
+            // regardless of direction
+            if (mCameraIndex < 0) {
+                mCameraIndex = 0;
+                sCameraWrapper.getCameraInfo(0, mCameraInfo);
+            }
+
+            if (mOpenRequested) {
+                // The camera is open, so reopen with the newly selected camera
+                openCamera();
+            }
+            return true;
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.selectCamera", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_OPENING_CAMERA, e);
+            }
+            return false;
+        }
+    }
+
+    int getCameraIndex() {
+        return mCameraIndex;
+    }
+
+    void selectCameraByIndex(final int cameraIndex) {
+        if (mCameraIndex == cameraIndex) {
+            return;
+        }
+
+        try {
+            mCameraIndex = cameraIndex;
+            sCameraWrapper.getCameraInfo(mCameraIndex, mCameraInfo);
+            if (mOpenRequested) {
+                openCamera();
+            }
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.selectCameraByIndex", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_OPENING_CAMERA, e);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    CameraInfo getCameraInfo() {
+        if (mCameraIndex == NO_CAMERA_SELECTED) {
+            return null;
+        }
+        return mCameraInfo;
+    }
+
+    /** @return True if this device has camera capabilities */
+    boolean hasAnyCamera() {
+        return sCameraWrapper.getNumberOfCameras() > 0;
+    }
+
+    /** @return True if the device has both a front and back camera */
+    boolean hasFrontAndBackCamera() {
+        return mHasFrontAndBackCamera;
+    }
+
+    /**
+     * Opens the camera on a separate thread and initiates the preview if one is available
+     */
+    void openCamera() {
+        if (mCameraIndex == NO_CAMERA_SELECTED) {
+            // Ensure a selected camera if none is currently selected. This may happen if the
+            // camera chooser is not the default media chooser.
+            selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        }
+        mOpenRequested = true;
+        // We're already opening the camera or already have the camera handle, nothing more to do
+        if (mPendingOpenCameraIndex == mCameraIndex || mCamera != null) {
+            return;
+        }
+
+        // True if the task to open the camera has to be delayed until the current one completes
+        boolean delayTask = false;
+
+        // Cancel any previous open camera tasks
+        if (mOpenCameraTask != null) {
+            mPendingOpenCameraIndex = NO_CAMERA_SELECTED;
+            delayTask = true;
+        }
+
+        mPendingOpenCameraIndex = mCameraIndex;
+        mOpenCameraTask = new AsyncTask<Integer, Void, Camera>() {
+            private Exception mException;
+
+            @Override
+            protected Camera doInBackground(final Integer... params) {
+                try {
+                    final int cameraIndex = params[0];
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "Opening camera " + mCameraIndex);
+                    }
+                    return sCameraWrapper.open(cameraIndex);
+                } catch (final Exception e) {
+                    LogUtil.e(TAG, "Exception while opening camera", e);
+                    mException = e;
+                    return null;
+                }
+            }
+
+            @Override
+            protected void onPostExecute(final Camera camera) {
+                // If we completed, but no longer want this camera, then release the camera
+                if (mOpenCameraTask != this || !mOpenRequested) {
+                    releaseCamera(camera);
+                    cleanup();
+                    return;
+                }
+
+                cleanup();
+
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "Opened camera " + mCameraIndex + " " + (camera != null));
+                }
+
+                setCamera(camera);
+                if (camera == null) {
+                    if (mListener != null) {
+                        mListener.onCameraError(ERROR_OPENING_CAMERA, mException);
+                    }
+                    LogUtil.e(TAG, "Error opening camera");
+                }
+            }
+
+            @Override
+            protected void onCancelled() {
+                super.onCancelled();
+                cleanup();
+            }
+
+            private void cleanup() {
+                mPendingOpenCameraIndex = NO_CAMERA_SELECTED;
+                if (mOpenCameraTask != null && mOpenCameraTask.getStatus() == Status.PENDING) {
+                    // If there's another task waiting on this one to complete, start it now
+                    mOpenCameraTask.execute(mCameraIndex);
+                } else {
+                    mOpenCameraTask = null;
+                }
+
+            }
+        };
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "Start opening camera " + mCameraIndex);
+        }
+
+        if (!delayTask) {
+            mOpenCameraTask.execute(mCameraIndex);
+        }
+    }
+
+    boolean isVideoMode() {
+        return mVideoModeRequested;
+    }
+
+    boolean isRecording() {
+        return mVideoModeRequested && mVideoCallback != null;
+    }
+
+    void setVideoMode(final boolean videoMode) {
+        if (mVideoModeRequested == videoMode) {
+            return;
+        }
+        mVideoModeRequested = videoMode;
+        tryInitOrCleanupVideoMode();
+    }
+
+    /** Closes the camera releasing the resources it uses */
+    void closeCamera() {
+        mOpenRequested = false;
+        setCamera(null);
+    }
+
+    /** Temporarily closes the camera if it is open */
+    void onPause() {
+        setCamera(null);
+    }
+
+    /** Reopens the camera if it was opened when onPause was called */
+    void onResume() {
+        if (mOpenRequested) {
+            openCamera();
+        }
+    }
+
+    /**
+     * Sets the listener which will be notified of errors or other events in the camera
+     * @param listener The listener to notify
+     */
+    void setListener(final CameraManagerListener listener) {
+        Assert.isMainThread();
+        mListener = listener;
+        if (!mIsHardwareAccelerationSupported && mListener != null) {
+            mListener.onCameraError(ERROR_HARDWARE_ACCELERATION_DISABLED, null);
+        }
+    }
+
+    void setSubscriptionDataProvider(final DraftMessageSubscriptionDataProvider provider) {
+        mSubscriptionDataProvider = provider;
+    }
+
+    void takePicture(final float heightPercent, @NonNull final MediaCallback callback) {
+        Assert.isTrue(!mVideoModeRequested);
+        Assert.isTrue(!mTakingPicture);
+        Assert.notNull(callback);
+        if (mCamera == null) {
+            // The caller should have checked isCameraAvailable first, but just in case, protect
+            // against a null camera by notifying the callback that taking the picture didn't work
+            callback.onMediaFailed(null);
+            return;
+        }
+        final Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
+            @Override
+            public void onPictureTaken(final byte[] bytes, final Camera camera) {
+                mTakingPicture = false;
+                if (mCamera != camera) {
+                    // This may happen if the camera was changed between front/back while the
+                    // picture is being taken.
+                    callback.onMediaInfo(MediaCallback.MEDIA_CAMERA_CHANGED);
+                    return;
+                }
+
+                if (bytes == null) {
+                    callback.onMediaInfo(MediaCallback.MEDIA_NO_DATA);
+                    return;
+                }
+
+                final Camera.Size size = camera.getParameters().getPictureSize();
+                int width;
+                int height;
+                if (mRotation == 90 || mRotation == 270) {
+                    width = size.height;
+                    height = size.width;
+                } else {
+                    width = size.width;
+                    height = size.height;
+                }
+                new ImagePersistTask(
+                        width, height, heightPercent, bytes, mCameraPreview.getContext(), callback)
+                        .executeOnThreadPool();
+            }
+        };
+
+        mTakingPicture = true;
+        try {
+            mCamera.takePicture(
+                    null /* shutter */,
+                    null /* raw */,
+                    null /* postView */,
+                    jpegCallback);
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.takePicture", e);
+            mTakingPicture = false;
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_TAKING_PICTURE, e);
+            }
+        }
+    }
+
+    void startVideo(final MediaCallback callback) {
+        Assert.notNull(callback);
+        Assert.isTrue(!isRecording());
+        mVideoCallback = callback;
+        tryStartVideoCapture();
+    }
+
+    /**
+     * Asynchronously releases a camera
+     * @param camera The camera to release
+     */
+    private void releaseCamera(final Camera camera) {
+        if (camera == null) {
+            return;
+        }
+
+        mFocusOverlayManager.onCameraReleased();
+
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(final Void... params) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "Releasing camera " + mCameraIndex);
+                }
+                sCameraWrapper.release(camera);
+                return null;
+            }
+        }.execute();
+    }
+
+    private void releaseMediaRecorder(final boolean cleanupFile) {
+        if (mMediaRecorder == null) {
+            return;
+        }
+        mVideoModeRequested = false;
+
+        if (cleanupFile) {
+            mMediaRecorder.cleanupTempFile();
+            if (mVideoCallback != null) {
+                final MediaCallback callback = mVideoCallback;
+                mVideoCallback = null;
+                // Notify the callback that we've stopped recording
+                callback.onMediaReady(null /*uri*/, null /*contentType*/, 0 /*width*/,
+                        0 /*height*/);
+            }
+        }
+
+        mMediaRecorder.closeVideoFileDescriptor();
+        mMediaRecorder.release();
+        mMediaRecorder = null;
+
+        if (mCamera != null) {
+            try {
+                mCamera.reconnect();
+            } catch (final IOException e) {
+                LogUtil.e(TAG, "IOException in CameraManager.releaseMediaRecorder", e);
+                if (mListener != null) {
+                    mListener.onCameraError(ERROR_OPENING_CAMERA, e);
+                }
+            } catch (final RuntimeException e) {
+                LogUtil.e(TAG, "RuntimeException in CameraManager.releaseMediaRecorder", e);
+                if (mListener != null) {
+                    mListener.onCameraError(ERROR_OPENING_CAMERA, e);
+                }
+            }
+        }
+        restoreRequestedOrientation();
+    }
+
+    /** Updates the orientation of the camera to match the orientation of the device */
+    private void updateCameraOrientation() {
+        if (mCamera == null || mCameraPreview == null || mTakingPicture) {
+            return;
+        }
+
+        final WindowManager windowManager =
+                (WindowManager) mCameraPreview.getContext().getSystemService(
+                        Context.WINDOW_SERVICE);
+
+        int degrees = 0;
+        switch (windowManager.getDefaultDisplay().getRotation()) {
+            case Surface.ROTATION_0: degrees = 0; break;
+            case Surface.ROTATION_90: degrees = 90; break;
+            case Surface.ROTATION_180: degrees = 180; break;
+            case Surface.ROTATION_270: degrees = 270; break;
+        }
+
+        // The display orientation of the camera (this controls the preview image).
+        int orientation;
+
+        // The clockwise rotation angle relative to the orientation of the camera. This affects
+        // pictures returned by the camera in Camera.PictureCallback.
+        int rotation;
+        if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            orientation = (mCameraInfo.orientation + degrees) % 360;
+            rotation = orientation;
+            // compensate the mirror but only for orientation
+            orientation = (360 - orientation) % 360;
+        } else {  // back-facing
+            orientation = (mCameraInfo.orientation - degrees + 360) % 360;
+            rotation = orientation;
+        }
+        mRotation = rotation;
+        if (mMediaRecorder == null) {
+            try {
+                mCamera.setDisplayOrientation(orientation);
+                final Camera.Parameters params = mCamera.getParameters();
+                params.setRotation(rotation);
+                mCamera.setParameters(params);
+            } catch (final RuntimeException e) {
+                LogUtil.e(TAG, "RuntimeException in CameraManager.updateCameraOrientation", e);
+                if (mListener != null) {
+                    mListener.onCameraError(ERROR_OPENING_CAMERA, e);
+                }
+            }
+        }
+    }
+
+    /** Sets the current camera, releasing any previously opened camera */
+    private void setCamera(final Camera camera) {
+        if (mCamera == camera) {
+            return;
+        }
+
+        releaseMediaRecorder(true /* cleanupFile */);
+        releaseCamera(mCamera);
+        mCamera = camera;
+        tryShowPreview();
+        if (mListener != null) {
+            mListener.onCameraChanged();
+        }
+    }
+
+    /** Shows the preview if the camera is open and the preview is loaded */
+    private void tryShowPreview() {
+        if (mCameraPreview == null || mCamera == null) {
+            if (mOrientationHandler != null) {
+                mOrientationHandler.disable();
+                mOrientationHandler = null;
+            }
+            releaseMediaRecorder(true /* cleanupFile */);
+            mFocusOverlayManager.onPreviewStopped();
+            return;
+        }
+        try {
+            mCamera.stopPreview();
+            updateCameraOrientation();
+
+            final Camera.Parameters params = mCamera.getParameters();
+            final Camera.Size pictureSize = chooseBestPictureSize();
+            final Camera.Size previewSize = chooseBestPreviewSize(pictureSize);
+            params.setPreviewSize(previewSize.width, previewSize.height);
+            params.setPictureSize(pictureSize.width, pictureSize.height);
+            logCameraSize("Setting preview size: ", previewSize);
+            logCameraSize("Setting picture size: ", pictureSize);
+            mCameraPreview.setSize(previewSize, mCameraInfo.orientation);
+            for (final String focusMode : params.getSupportedFocusModes()) {
+                if (TextUtils.equals(focusMode, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
+                    // Use continuous focus if available
+                    params.setFocusMode(focusMode);
+                    break;
+                }
+            }
+
+            mCamera.setParameters(params);
+            mCameraPreview.startPreview(mCamera);
+            mCamera.startPreview();
+            mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
+                @Override
+                public void onAutoFocusMoving(final boolean start, final Camera camera) {
+                    mFocusOverlayManager.onAutoFocusMoving(start);
+                }
+            });
+            mFocusOverlayManager.setParameters(mCamera.getParameters());
+            mFocusOverlayManager.setMirror(mCameraInfo.facing == CameraInfo.CAMERA_FACING_BACK);
+            mFocusOverlayManager.onPreviewStarted();
+            tryInitOrCleanupVideoMode();
+            if (mOrientationHandler == null) {
+                mOrientationHandler = new OrientationHandler(mCameraPreview.getContext());
+                mOrientationHandler.enable();
+            }
+        } catch (final IOException e) {
+            LogUtil.e(TAG, "IOException in CameraManager.tryShowPreview", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_SHOWING_PREVIEW, e);
+            }
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.tryShowPreview", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_SHOWING_PREVIEW, e);
+            }
+        }
+    }
+
+    private void tryInitOrCleanupVideoMode() {
+        if (!mVideoModeRequested || mCamera == null || mCameraPreview == null) {
+            releaseMediaRecorder(true /* cleanupFile */);
+            return;
+        }
+
+        if (mMediaRecorder != null) {
+            return;
+        }
+
+        try {
+            mCamera.unlock();
+            final int maxMessageSize = getMmsConfig().getMaxMessageSize();
+            mMediaRecorder = new MmsVideoRecorder(mCamera, mCameraIndex, mRotation, maxMessageSize);
+            mMediaRecorder.prepare();
+        } catch (final FileNotFoundException e) {
+            LogUtil.e(TAG, "FileNotFoundException in CameraManager.tryInitOrCleanupVideoMode", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_STORAGE_FAILURE, e);
+            }
+            setVideoMode(false);
+            return;
+        } catch (final IOException e) {
+            LogUtil.e(TAG, "IOException in CameraManager.tryInitOrCleanupVideoMode", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_INITIALIZING_VIDEO, e);
+            }
+            setVideoMode(false);
+            return;
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.tryInitOrCleanupVideoMode", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_INITIALIZING_VIDEO, e);
+            }
+            setVideoMode(false);
+            return;
+        }
+
+        tryStartVideoCapture();
+    }
+
+    private void tryStartVideoCapture() {
+        if (mMediaRecorder == null || mVideoCallback == null) {
+            return;
+        }
+
+        mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
+            @Override
+            public void onError(final MediaRecorder mediaRecorder, final int what,
+                    final int extra) {
+                if (mListener != null) {
+                    mListener.onCameraError(ERROR_RECORDING_VIDEO, null);
+                }
+                restoreRequestedOrientation();
+            }
+        });
+
+        mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
+            @Override
+            public void onInfo(final MediaRecorder mediaRecorder, final int what, final int extra) {
+                if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED ||
+                        what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
+                    stopVideo();
+                }
+            }
+        });
+
+        try {
+            mMediaRecorder.start();
+            final Activity activity = UiUtils.getActivity(mCameraPreview.getContext());
+            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+            lockOrientation();
+        } catch (final IllegalStateException e) {
+            LogUtil.e(TAG, "IllegalStateException in CameraManager.tryStartVideoCapture", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_RECORDING_VIDEO, e);
+            }
+            setVideoMode(false);
+            restoreRequestedOrientation();
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.tryStartVideoCapture", e);
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_RECORDING_VIDEO, e);
+            }
+            setVideoMode(false);
+            restoreRequestedOrientation();
+        }
+    }
+
+    void stopVideo() {
+        int width = ImageRequest.UNSPECIFIED_SIZE;
+        int height = ImageRequest.UNSPECIFIED_SIZE;
+        Uri uri = null;
+        String contentType = null;
+        try {
+            final Activity activity = UiUtils.getActivity(mCameraPreview.getContext());
+            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+            mMediaRecorder.stop();
+            width = mMediaRecorder.getVideoWidth();
+            height = mMediaRecorder.getVideoHeight();
+            uri = mMediaRecorder.getVideoUri();
+            contentType = mMediaRecorder.getContentType();
+        } catch (final RuntimeException e) {
+            // MediaRecorder.stop will throw a RuntimeException if the video was too short, let the
+            // finally clause call the callback with null uri and handle cleanup
+            LogUtil.e(TAG, "RuntimeException in CameraManager.stopVideo", e);
+        } finally {
+            final MediaCallback videoCallback = mVideoCallback;
+            mVideoCallback = null;
+            releaseMediaRecorder(false /* cleanupFile */);
+            if (uri == null) {
+                tryInitOrCleanupVideoMode();
+            }
+            videoCallback.onMediaReady(uri, contentType, width, height);
+        }
+    }
+
+    boolean isCameraAvailable() {
+        return mCamera != null && !mTakingPicture && mIsHardwareAccelerationSupported;
+    }
+
+    /**
+     * External components call into this to report if hardware acceleration is supported.  When
+     * hardware acceleration isn't supported, we need to report an error through the listener
+     * interface
+     * @param isHardwareAccelerationSupported True if the preview is rendering in a hardware
+     *                                        accelerated view.
+     */
+    void reportHardwareAccelerationSupported(final boolean isHardwareAccelerationSupported) {
+        Assert.isMainThread();
+        if (mIsHardwareAccelerationSupported == isHardwareAccelerationSupported) {
+            // If the value hasn't changed nothing more to do
+            return;
+        }
+
+        mIsHardwareAccelerationSupported = isHardwareAccelerationSupported;
+        if (!isHardwareAccelerationSupported) {
+            LogUtil.e(TAG, "Software rendering - cannot open camera");
+            if (mListener != null) {
+                mListener.onCameraError(ERROR_HARDWARE_ACCELERATION_DISABLED, null);
+            }
+        }
+    }
+
+    /** Returns the scale factor to scale the width/height to max allowed in MmsConfig */
+    private float getScaleFactorForMaxAllowedSize(final int width, final int height,
+            final int maxWidth, final int maxHeight) {
+        if (maxWidth <= 0 || maxHeight <= 0) {
+            // MmsConfig initialization runs asynchronously on application startup, so there's a
+            // chance (albeit a very slight one) that we don't have it yet.
+            LogUtil.w(LogUtil.BUGLE_TAG, "Max image size not loaded in MmsConfig");
+            return 1.0f;
+        }
+
+        if (width <= maxWidth && height <= maxHeight) {
+            // Already meeting requirements.
+            return 1.0f;
+        }
+
+        return Math.min(maxWidth * 1.0f / width, maxHeight * 1.0f / height);
+    }
+
+    private MmsConfig getMmsConfig() {
+        final int subId = mSubscriptionDataProvider != null ?
+                mSubscriptionDataProvider.getConversationSelfSubId() :
+                ParticipantData.DEFAULT_SELF_SUB_ID;
+        return MmsConfig.get(subId);
+    }
+
+    /**
+     * Choose the best picture size by trying to find a size close to the MmsConfig's max size,
+     * which is closest to the screen aspect ratio
+     */
+    private Camera.Size chooseBestPictureSize() {
+        final Context context = mCameraPreview.getContext();
+        final Resources resources = context.getResources();
+        final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+        final int displayOrientation = resources.getConfiguration().orientation;
+        int cameraOrientation = mCameraInfo.orientation;
+
+        int screenWidth;
+        int screenHeight;
+        if (displayOrientation == Configuration.ORIENTATION_LANDSCAPE) {
+            // Rotate the camera orientation 90 degrees to compensate for the rotated display
+            // metrics. Direction doesn't matter because we're just using it for width/height
+            cameraOrientation += 90;
+        }
+
+        // Check the camera orientation relative to the display.
+        // For 0, 180, 360, the screen width/height are the display width/height
+        // For 90, 270, the screen width/height are inverted from the display
+        if (cameraOrientation % 180 == 0) {
+            screenWidth = displayMetrics.widthPixels;
+            screenHeight = displayMetrics.heightPixels;
+        } else {
+            screenWidth = displayMetrics.heightPixels;
+            screenHeight = displayMetrics.widthPixels;
+        }
+
+        final MmsConfig mmsConfig = getMmsConfig();
+        final int maxWidth = mmsConfig.getMaxImageWidth();
+        final int maxHeight = mmsConfig.getMaxImageHeight();
+
+        // Constrain the size within the max width/height defined by MmsConfig.
+        final float scaleFactor = getScaleFactorForMaxAllowedSize(screenWidth, screenHeight,
+                maxWidth, maxHeight);
+        screenWidth *= scaleFactor;
+        screenHeight *= scaleFactor;
+
+        final float aspectRatio = BugleGservices.get().getFloat(
+                BugleGservicesKeys.CAMERA_ASPECT_RATIO,
+                screenWidth / (float) screenHeight);
+        final List<Camera.Size> sizes = new ArrayList<Camera.Size>(
+                mCamera.getParameters().getSupportedPictureSizes());
+        final int maxPixels = maxWidth * maxHeight;
+
+        // Sort the sizes so the best size is first
+        Collections.sort(sizes, new SizeComparator(maxWidth, maxHeight, aspectRatio, maxPixels));
+
+        return sizes.get(0);
+    }
+
+    /**
+     * Chose the best preview size based on the picture size.  Try to find a size with the same
+     * aspect ratio and size as the picture if possible
+     */
+    private Camera.Size chooseBestPreviewSize(final Camera.Size pictureSize) {
+        final List<Camera.Size> sizes = new ArrayList<Camera.Size>(
+                mCamera.getParameters().getSupportedPreviewSizes());
+        final float aspectRatio = pictureSize.width / (float) pictureSize.height;
+        final int capturePixels = pictureSize.width * pictureSize.height;
+
+        // Sort the sizes so the best size is first
+        Collections.sort(sizes, new SizeComparator(Integer.MAX_VALUE, Integer.MAX_VALUE,
+                aspectRatio, capturePixels));
+
+        return sizes.get(0);
+    }
+
+    private class OrientationHandler extends OrientationEventListener {
+        OrientationHandler(final Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onOrientationChanged(final int orientation) {
+            updateCameraOrientation();
+        }
+    }
+
+    private static class SizeComparator implements Comparator<Camera.Size> {
+        private static final int PREFER_LEFT = -1;
+        private static final int PREFER_RIGHT = 1;
+
+        // The max width/height for the preferred size. Integer.MAX_VALUE if no size limit
+        private final int mMaxWidth;
+        private final int mMaxHeight;
+
+        // The desired aspect ratio
+        private final float mTargetAspectRatio;
+
+        // The desired size (width x height) to try to match
+        private final int mTargetPixels;
+
+        public SizeComparator(final int maxWidth, final int maxHeight,
+                              final float targetAspectRatio, final int targetPixels) {
+            mMaxWidth = maxWidth;
+            mMaxHeight = maxHeight;
+            mTargetAspectRatio = targetAspectRatio;
+            mTargetPixels = targetPixels;
+        }
+
+        /**
+         * Returns a negative value if left is a better choice than right, or a positive value if
+         * right is a better choice is better than left.  0 if they are equal
+         */
+        @Override
+        public int compare(final Camera.Size left, final Camera.Size right) {
+            // If one size is less than the max size prefer it over the other
+            if ((left.width <= mMaxWidth && left.height <= mMaxHeight) !=
+                    (right.width <= mMaxWidth && right.height <= mMaxHeight)) {
+                return left.width <= mMaxWidth ? PREFER_LEFT : PREFER_RIGHT;
+            }
+
+            // If one is closer to the target aspect ratio, prefer it.
+            final float leftAspectRatio = left.width / (float) left.height;
+            final float rightAspectRatio = right.width / (float) right.height;
+            final float leftAspectRatioDiff = Math.abs(leftAspectRatio - mTargetAspectRatio);
+            final float rightAspectRatioDiff = Math.abs(rightAspectRatio - mTargetAspectRatio);
+            if (leftAspectRatioDiff != rightAspectRatioDiff) {
+                return (leftAspectRatioDiff - rightAspectRatioDiff) < 0 ?
+                        PREFER_LEFT : PREFER_RIGHT;
+            }
+
+            // At this point they have the same aspect ratio diff and are either both bigger
+            // than the max size or both smaller than the max size, so prefer the one closest
+            // to target size
+            final int leftDiff = Math.abs((left.width * left.height) - mTargetPixels);
+            final int rightDiff = Math.abs((right.width * right.height) - mTargetPixels);
+            return leftDiff - rightDiff;
+        }
+    }
+
+    @Override // From FocusOverlayManager.Listener
+    public void autoFocus() {
+        if (mCamera == null) {
+            return;
+        }
+
+        try {
+            mCamera.autoFocus(new Camera.AutoFocusCallback() {
+                @Override
+                public void onAutoFocus(final boolean success, final Camera camera) {
+                    mFocusOverlayManager.onAutoFocus(success, false /* shutterDown */);
+                }
+            });
+        } catch (final RuntimeException e) {
+            LogUtil.e(TAG, "RuntimeException in CameraManager.autoFocus", e);
+            // If autofocus fails, the camera should have called the callback with success=false,
+            // but some throw an exception here
+            mFocusOverlayManager.onAutoFocus(false /*success*/, false /*shutterDown*/);
+        }
+    }
+
+    @Override // From FocusOverlayManager.Listener
+    public void cancelAutoFocus() {
+        if (mCamera == null) {
+            return;
+        }
+        try {
+            mCamera.cancelAutoFocus();
+        } catch (final RuntimeException e) {
+            // Ignore
+            LogUtil.e(TAG, "RuntimeException in CameraManager.cancelAutoFocus", e);
+        }
+    }
+
+    @Override // From FocusOverlayManager.Listener
+    public boolean capture() {
+        return false;
+    }
+
+    @Override // From FocusOverlayManager.Listener
+    public void setFocusParameters() {
+        if (mCamera == null) {
+            return;
+        }
+        try {
+            final Camera.Parameters parameters = mCamera.getParameters();
+            parameters.setFocusMode(mFocusOverlayManager.getFocusMode());
+            if (parameters.getMaxNumFocusAreas() > 0) {
+                // Don't set focus areas (even to null) if focus areas aren't supported, camera may
+                // crash
+                parameters.setFocusAreas(mFocusOverlayManager.getFocusAreas());
+            }
+            parameters.setMeteringAreas(mFocusOverlayManager.getMeteringAreas());
+            mCamera.setParameters(parameters);
+        } catch (final RuntimeException e) {
+            // This occurs when the device is out of space or when the camera is locked
+            LogUtil.e(TAG, "RuntimeException in CameraManager setFocusParameters");
+        }
+    }
+
+    private void logCameraSize(final String prefix, final Camera.Size size) {
+        // Log the camera size and aspect ratio for help when examining bug reports for camera
+        // failures
+        LogUtil.i(TAG, prefix + size.width + "x" + size.height +
+                " (" + (size.width / (float) size.height) + ")");
+    }
+
+
+    private Integer mSavedOrientation = null;
+
+    private void lockOrientation() {
+        // when we start recording, lock our orientation
+        final Activity a = UiUtils.getActivity(mCameraPreview.getContext());
+        final WindowManager windowManager =
+                (WindowManager) a.getSystemService(Context.WINDOW_SERVICE);
+        final int rotation = windowManager.getDefaultDisplay().getRotation();
+
+        mSavedOrientation = a.getRequestedOrientation();
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                a.setRequestedOrientation(
+                        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+                break;
+            case Surface.ROTATION_90:
+                a.setRequestedOrientation(
+                        ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+                break;
+            case Surface.ROTATION_180:
+                a.setRequestedOrientation(
+                        ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
+                break;
+            case Surface.ROTATION_270:
+                a.setRequestedOrientation(
+                        ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+                break;
+        }
+
+    }
+
+    private void restoreRequestedOrientation() {
+        if (mSavedOrientation != null) {
+            final Activity a = UiUtils.getActivity(mCameraPreview.getContext());
+            if (a != null) {
+                a.setRequestedOrientation(mSavedOrientation);
+            }
+            mSavedOrientation = null;
+        }
+    }
+
+    static boolean hasCameraPermission() {
+        return OsUtil.hasPermission(Manifest.permission.CAMERA);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/CameraMediaChooser.java b/src/com/android/messaging/ui/mediapicker/CameraMediaChooser.java
new file mode 100644
index 0000000..2c7a7f2
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/CameraMediaChooser.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.widget.Chronometer;
+import android.widget.ImageButton;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MediaPickerMessagePartData;
+import com.android.messaging.ui.mediapicker.CameraManager.MediaCallback;
+import com.android.messaging.ui.mediapicker.camerafocus.RenderOverlay;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Chooser which allows the user to take pictures or video without leaving the current app/activity
+ */
+class CameraMediaChooser extends MediaChooser implements
+        CameraManager.CameraManagerListener {
+    private CameraPreview.CameraPreviewHost mCameraPreviewHost;
+    private ImageButton mFullScreenButton;
+    private ImageButton mSwapCameraButton;
+    private ImageButton mSwapModeButton;
+    private ImageButton mCaptureButton;
+    private ImageButton mCancelVideoButton;
+    private Chronometer mVideoCounter;
+    private boolean mVideoCancelled;
+    private int mErrorToast;
+    private View mEnabledView;
+    private View mMissingPermissionView;
+
+    CameraMediaChooser(final MediaPicker mediaPicker) {
+        super(mediaPicker);
+    }
+
+    @Override
+    public int getSupportedMediaTypes() {
+        if (CameraManager.get().hasAnyCamera()) {
+            return MediaPicker.MEDIA_TYPE_IMAGE | MediaPicker.MEDIA_TYPE_VIDEO;
+        } else {
+            return MediaPicker.MEDIA_TYPE_NONE;
+        }
+    }
+
+    @Override
+    public View destroyView() {
+        CameraManager.get().closeCamera();
+        CameraManager.get().setListener(null);
+        CameraManager.get().setSubscriptionDataProvider(null);
+        return super.destroyView();
+    }
+
+    @Override
+    protected View createView(final ViewGroup container) {
+        CameraManager.get().setListener(this);
+        CameraManager.get().setSubscriptionDataProvider(this);
+        CameraManager.get().setVideoMode(false);
+        final LayoutInflater inflater = getLayoutInflater();
+        final CameraMediaChooserView view = (CameraMediaChooserView) inflater.inflate(
+                R.layout.mediapicker_camera_chooser,
+                container /* root */,
+                false /* attachToRoot */);
+        mCameraPreviewHost = (CameraPreview.CameraPreviewHost) view.findViewById(
+                R.id.camera_preview);
+        mCameraPreviewHost.getView().setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(final View view, final MotionEvent motionEvent) {
+                if (CameraManager.get().isVideoMode()) {
+                    // Prevent the swipe down in video mode because video is always captured in
+                    // full screen
+                    return true;
+                }
+
+                return false;
+            }
+        });
+
+        final View shutterVisual = view.findViewById(R.id.camera_shutter_visual);
+
+        mFullScreenButton = (ImageButton) view.findViewById(R.id.camera_fullScreen_button);
+        mFullScreenButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                mMediaPicker.setFullScreen(true);
+            }
+        });
+
+        mSwapCameraButton = (ImageButton) view.findViewById(R.id.camera_swapCamera_button);
+        mSwapCameraButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                CameraManager.get().swapCamera();
+            }
+        });
+
+        mCaptureButton = (ImageButton) view.findViewById(R.id.camera_capture_button);
+        mCaptureButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                final float heightPercent = Math.min(mMediaPicker.getViewPager().getHeight() /
+                        (float) mCameraPreviewHost.getView().getHeight(), 1);
+
+                if (CameraManager.get().isRecording()) {
+                    CameraManager.get().stopVideo();
+                } else {
+                    final CameraManager.MediaCallback callback = new CameraManager.MediaCallback() {
+                        @Override
+                        public void onMediaReady(
+                                final Uri uriToVideo, final String contentType,
+                                final int width, final int height) {
+                            mVideoCounter.stop();
+                            if (mVideoCancelled || uriToVideo == null) {
+                                mVideoCancelled = false;
+                            } else {
+                                final Rect startRect = new Rect();
+                                // It's possible to throw out the chooser while taking the
+                                // picture/video.  In that case, still use the attachment, just
+                                // skip the startRect
+                                if (mView != null) {
+                                    mView.getGlobalVisibleRect(startRect);
+                                }
+                                mMediaPicker.dispatchItemsSelected(
+                                        new MediaPickerMessagePartData(startRect, contentType,
+                                                uriToVideo, width, height),
+                                        true /* dismissMediaPicker */);
+                            }
+                            updateViewState();
+                        }
+
+                        @Override
+                        public void onMediaFailed(final Exception exception) {
+                            UiUtils.showToastAtBottom(R.string.camera_media_failure);
+                            updateViewState();
+                        }
+
+                        @Override
+                        public void onMediaInfo(final int what) {
+                            if (what == MediaCallback.MEDIA_NO_DATA) {
+                                UiUtils.showToastAtBottom(R.string.camera_media_failure);
+                            }
+                            updateViewState();
+                        }
+                    };
+                    if (CameraManager.get().isVideoMode()) {
+                        CameraManager.get().startVideo(callback);
+                        mVideoCounter.setBase(SystemClock.elapsedRealtime());
+                        mVideoCounter.start();
+                        updateViewState();
+                    } else {
+                        showShutterEffect(shutterVisual);
+                        CameraManager.get().takePicture(heightPercent, callback);
+                        updateViewState();
+                    }
+                }
+            }
+        });
+
+        mSwapModeButton = (ImageButton) view.findViewById(R.id.camera_swap_mode_button);
+        mSwapModeButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                final boolean isSwitchingToVideo = !CameraManager.get().isVideoMode();
+                if (isSwitchingToVideo && !OsUtil.hasRecordAudioPermission()) {
+                    requestRecordAudioPermission();
+                } else {
+                    onSwapMode();
+                }
+            }
+        });
+
+        mCancelVideoButton = (ImageButton) view.findViewById(R.id.camera_cancel_button);
+        mCancelVideoButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                mVideoCancelled = true;
+                CameraManager.get().stopVideo();
+                mMediaPicker.dismiss(true);
+            }
+        });
+
+        mVideoCounter = (Chronometer) view.findViewById(R.id.camera_video_counter);
+
+        CameraManager.get().setRenderOverlay((RenderOverlay) view.findViewById(R.id.focus_visual));
+
+        mEnabledView = view.findViewById(R.id.mediapicker_enabled);
+        mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
+
+        // Must set mView before calling updateViewState because it operates on mView
+        mView = view;
+        updateViewState();
+        updateForPermissionState(CameraManager.hasCameraPermission());
+        return view;
+    }
+
+    @Override
+    public int getIconResource() {
+        return R.drawable.ic_camera_light;
+    }
+
+    @Override
+    public int getIconDescriptionResource() {
+        return R.string.mediapicker_cameraChooserDescription;
+    }
+
+    /**
+     * Updates the view when entering or leaving full-screen camera mode
+     * @param fullScreen
+     */
+    @Override
+    void onFullScreenChanged(final boolean fullScreen) {
+        super.onFullScreenChanged(fullScreen);
+        if (!fullScreen && CameraManager.get().isVideoMode()) {
+            CameraManager.get().setVideoMode(false);
+        }
+        updateViewState();
+    }
+
+    /**
+     * Initializes the control to a default state when it is opened / closed
+     * @param open True if the control is opened
+     */
+    @Override
+    void onOpenedChanged(final boolean open) {
+        super.onOpenedChanged(open);
+        updateViewState();
+    }
+
+    @Override
+    protected void setSelected(final boolean selected) {
+        super.setSelected(selected);
+        if (selected) {
+            if (CameraManager.hasCameraPermission()) {
+                // If an error occurred before the chooser was selected, show it now
+                showErrorToastIfNeeded();
+            } else {
+                requestCameraPermission();
+            }
+        }
+    }
+
+    private void requestCameraPermission() {
+        mMediaPicker.requestPermissions(new String[] { Manifest.permission.CAMERA },
+                MediaPicker.CAMERA_PERMISSION_REQUEST_CODE);
+    }
+
+    private void requestRecordAudioPermission() {
+        mMediaPicker.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO },
+                MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE);
+    }
+
+    @Override
+    protected void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (requestCode == MediaPicker.CAMERA_PERMISSION_REQUEST_CODE) {
+            final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+            updateForPermissionState(permissionGranted);
+            if (permissionGranted) {
+                mCameraPreviewHost.onCameraPermissionGranted();
+            }
+        } else if (requestCode == MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE) {
+            Assert.isFalse(CameraManager.get().isVideoMode());
+            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                // Switch to video mode
+                onSwapMode();
+            } else {
+                // Stay in still-photo mode
+            }
+        }
+    }
+
+    private void updateForPermissionState(final boolean granted) {
+        // onRequestPermissionsResult can sometimes get called before createView().
+        if (mEnabledView == null) {
+            return;
+        }
+
+        mEnabledView.setVisibility(granted ? View.VISIBLE : View.GONE);
+        mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
+    }
+
+    @Override
+    public boolean canSwipeDown() {
+        if (CameraManager.get().isVideoMode()) {
+            return true;
+        }
+        return super.canSwipeDown();
+    }
+
+    /**
+     * Handles an error from the camera manager by showing the appropriate error message to the user
+     * @param errorCode One of the CameraManager.ERROR_* constants
+     * @param e The exception which caused the error, if any
+     */
+    @Override
+    public void onCameraError(final int errorCode, final Exception e) {
+        switch (errorCode) {
+            case CameraManager.ERROR_OPENING_CAMERA:
+            case CameraManager.ERROR_SHOWING_PREVIEW:
+                mErrorToast = R.string.camera_error_opening;
+                break;
+            case CameraManager.ERROR_INITIALIZING_VIDEO:
+                mErrorToast = R.string.camera_error_video_init_fail;
+                updateViewState();
+                break;
+            case CameraManager.ERROR_STORAGE_FAILURE:
+                mErrorToast = R.string.camera_error_storage_fail;
+                updateViewState();
+                break;
+            case CameraManager.ERROR_TAKING_PICTURE:
+                mErrorToast = R.string.camera_error_failure_taking_picture;
+                break;
+            default:
+                mErrorToast = R.string.camera_error_unknown;
+                LogUtil.w(LogUtil.BUGLE_TAG, "Unknown camera error:" + errorCode);
+                break;
+        }
+        showErrorToastIfNeeded();
+    }
+
+    private void showErrorToastIfNeeded() {
+        if (mErrorToast != 0 && mSelected) {
+            UiUtils.showToastAtBottom(mErrorToast);
+            mErrorToast = 0;
+        }
+    }
+
+    @Override
+    public void onCameraChanged() {
+        updateViewState();
+    }
+
+    private void onSwapMode() {
+        CameraManager.get().setVideoMode(!CameraManager.get().isVideoMode());
+        if (CameraManager.get().isVideoMode()) {
+            mMediaPicker.setFullScreen(true);
+
+            // For now we start recording immediately
+            mCaptureButton.performClick();
+        }
+        updateViewState();
+    }
+
+    private void showShutterEffect(final View shutterVisual) {
+        final float maxAlpha = getContext().getResources().getFraction(
+                R.fraction.camera_shutter_max_alpha, 1 /* base */, 1 /* pBase */);
+
+        // Divide by 2 so each half of the animation adds up to the full duration
+        final int animationDuration = getContext().getResources().getInteger(
+                R.integer.camera_shutter_duration) / 2;
+
+        final AnimationSet animation = new AnimationSet(false /* shareInterpolator */);
+        final Animation alphaInAnimation = new AlphaAnimation(0.0f, maxAlpha);
+        alphaInAnimation.setDuration(animationDuration);
+        animation.addAnimation(alphaInAnimation);
+
+        final Animation alphaOutAnimation = new AlphaAnimation(maxAlpha, 0.0f);
+        alphaOutAnimation.setStartOffset(animationDuration);
+        alphaOutAnimation.setDuration(animationDuration);
+        animation.addAnimation(alphaOutAnimation);
+
+        animation.setAnimationListener(new Animation.AnimationListener() {
+            @Override
+            public void onAnimationStart(final Animation animation) {
+                shutterVisual.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            public void onAnimationEnd(final Animation animation) {
+                shutterVisual.setVisibility(View.GONE);
+            }
+
+            @Override
+            public void onAnimationRepeat(final Animation animation) {
+            }
+        });
+        shutterVisual.startAnimation(animation);
+    }
+
+    /** Updates the state of the buttons and overlays based on the current state of the view */
+    private void updateViewState() {
+        if (mView == null) {
+            return;
+        }
+
+        final Context context = getContext();
+        if (context == null) {
+            // Context is null if the fragment was already removed from the activity
+            return;
+        }
+        final boolean fullScreen = mMediaPicker.isFullScreen();
+        final boolean videoMode = CameraManager.get().isVideoMode();
+        final boolean isRecording = CameraManager.get().isRecording();
+        final boolean isCameraAvailable = isCameraAvailable();
+        final Camera.CameraInfo cameraInfo = CameraManager.get().getCameraInfo();
+        final boolean frontCamera = cameraInfo != null && cameraInfo.facing ==
+                Camera.CameraInfo.CAMERA_FACING_FRONT;
+
+        mView.setSystemUiVisibility(
+                fullScreen ? View.SYSTEM_UI_FLAG_LOW_PROFILE :
+                View.SYSTEM_UI_FLAG_VISIBLE);
+
+        mFullScreenButton.setVisibility(!fullScreen ? View.VISIBLE : View.GONE);
+        mFullScreenButton.setEnabled(isCameraAvailable);
+        mSwapCameraButton.setVisibility(
+                fullScreen && !isRecording && CameraManager.get().hasFrontAndBackCamera() ?
+                        View.VISIBLE : View.GONE);
+        mSwapCameraButton.setImageResource(frontCamera ?
+                R.drawable.ic_camera_front_light :
+                R.drawable.ic_camera_rear_light);
+        mSwapCameraButton.setEnabled(isCameraAvailable);
+
+        mCancelVideoButton.setVisibility(isRecording ? View.VISIBLE : View.GONE);
+        mVideoCounter.setVisibility(isRecording ? View.VISIBLE : View.GONE);
+
+        mSwapModeButton.setImageResource(videoMode ?
+                R.drawable.ic_mp_camera_small_light :
+                R.drawable.ic_mp_video_small_light);
+        mSwapModeButton.setContentDescription(context.getString(videoMode ?
+                R.string.camera_switch_to_still_mode : R.string.camera_switch_to_video_mode));
+        mSwapModeButton.setVisibility(isRecording ? View.GONE : View.VISIBLE);
+        mSwapModeButton.setEnabled(isCameraAvailable);
+
+        if (isRecording) {
+            mCaptureButton.setImageResource(R.drawable.ic_mp_capture_stop_large_light);
+            mCaptureButton.setContentDescription(context.getString(
+                    R.string.camera_stop_recording));
+        } else if (videoMode) {
+            mCaptureButton.setImageResource(R.drawable.ic_mp_video_large_light);
+            mCaptureButton.setContentDescription(context.getString(
+                    R.string.camera_start_recording));
+        } else {
+            mCaptureButton.setImageResource(R.drawable.ic_checkmark_large_light);
+            mCaptureButton.setContentDescription(context.getString(
+                    R.string.camera_take_picture));
+        }
+        mCaptureButton.setEnabled(isCameraAvailable);
+    }
+
+    @Override
+    int getActionBarTitleResId() {
+        return 0;
+    }
+
+    /**
+     * Returns if the camera is currently ready camera is loaded and not taking a picture.
+     * otherwise we should avoid taking another picture, swapping camera or recording video.
+     */
+    private boolean isCameraAvailable() {
+        return CameraManager.get().isCameraAvailable();
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/CameraMediaChooserView.java b/src/com/android/messaging/ui/mediapicker/CameraMediaChooserView.java
new file mode 100644
index 0000000..64c07b2
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/CameraMediaChooserView.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import com.android.messaging.R;
+import com.android.messaging.ui.PersistentInstanceState;
+import com.android.messaging.util.ThreadUtil;
+
+public class CameraMediaChooserView extends FrameLayout implements PersistentInstanceState {
+    private static final String KEY_CAMERA_INDEX = "camera_index";
+
+    // True if we have at least queued an update to the view tree to support software rendering
+    // fallback
+    private boolean mIsSoftwareFallbackActive;
+
+    public CameraMediaChooserView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(KEY_CAMERA_INDEX, CameraManager.get().getCameraIndex());
+        return bundle;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(final Parcelable state) {
+        if (!(state instanceof Bundle)) {
+            return;
+        }
+
+        final Bundle bundle = (Bundle) state;
+        CameraManager.get().selectCameraByIndex(bundle.getInt(KEY_CAMERA_INDEX));
+    }
+
+    @Override
+    public Parcelable saveState() {
+        return onSaveInstanceState();
+    }
+
+    @Override
+    public void restoreState(final Parcelable restoredState) {
+        onRestoreInstanceState(restoredState);
+    }
+
+    @Override
+    public void resetState() {
+        CameraManager.get().selectCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
+    }
+
+    @Override
+    protected void onDraw(final Canvas canvas) {
+        super.onDraw(canvas);
+        // If the canvas isn't hardware accelerated, we have to replace the HardwareCameraPreview
+        // with a SoftwareCameraPreview which supports software rendering
+        if (!canvas.isHardwareAccelerated() && !mIsSoftwareFallbackActive) {
+            mIsSoftwareFallbackActive = true;
+            // Post modifying the tree since we can't modify the view tree during a draw pass
+            ThreadUtil.getMainThreadHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    final HardwareCameraPreview cameraPreview =
+                            (HardwareCameraPreview) findViewById(R.id.camera_preview);
+                    if (cameraPreview == null) {
+                        return;
+                    }
+                    final ViewGroup parent = ((ViewGroup) cameraPreview.getParent());
+                    final int index = parent.indexOfChild(cameraPreview);
+                    final SoftwareCameraPreview softwareCameraPreview =
+                            new SoftwareCameraPreview(getContext());
+                    // Be sure to remove the hardware view before adding the software view to
+                    // prevent having 2 camera previews active at the same time
+                    parent.removeView(cameraPreview);
+                    parent.addView(softwareCameraPreview, index);
+                }
+            });
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/CameraPreview.java b/src/com/android/messaging/ui/mediapicker/CameraPreview.java
new file mode 100644
index 0000000..ecac978
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/CameraPreview.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.hardware.Camera;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import com.android.messaging.util.Assert;
+
+import java.io.IOException;
+
+/**
+ * Contains shared code for SoftwareCameraPreview and HardwareCameraPreview, cannot use inheritance
+ * because those classes must inherit from separate Views, so those classes delegate calls to this
+ * helper class.  Specifics for each implementation are in CameraPreviewHost
+ */
+public class CameraPreview {
+    public interface CameraPreviewHost {
+        View getView();
+        boolean isValid();
+        void startPreview(final Camera camera) throws IOException;
+        void onCameraPermissionGranted();
+
+    }
+
+    private int mCameraWidth = -1;
+    private int mCameraHeight = -1;
+
+    private final CameraPreviewHost mHost;
+
+    public CameraPreview(final CameraPreviewHost host) {
+        Assert.notNull(host);
+        Assert.notNull(host.getView());
+        mHost = host;
+    }
+
+    public void setSize(final Camera.Size size, final int orientation) {
+        switch (orientation) {
+            case 0:
+            case 180:
+                mCameraWidth = size.width;
+                mCameraHeight = size.height;
+                break;
+            case 90:
+            case 270:
+            default:
+                mCameraWidth = size.height;
+                mCameraHeight = size.width;
+        }
+        mHost.getView().requestLayout();
+    }
+
+    public int getWidthMeasureSpec(final int widthMeasureSpec, final int heightMeasureSpec) {
+        if (mCameraHeight >= 0) {
+            final int width = View.MeasureSpec.getSize(widthMeasureSpec);
+            return MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+        } else {
+            return widthMeasureSpec;
+        }
+    }
+
+    public int getHeightMeasureSpec(final int widthMeasureSpec, final int heightMeasureSpec) {
+        if (mCameraHeight >= 0) {
+            final int orientation = getContext().getResources().getConfiguration().orientation;
+            final int width = View.MeasureSpec.getSize(widthMeasureSpec);
+            final float aspectRatio = (float) mCameraWidth / (float) mCameraHeight;
+            int height;
+            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                height = (int) (width * aspectRatio);
+            } else {
+                height = (int) (width / aspectRatio);
+            }
+            return View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
+        } else {
+            return heightMeasureSpec;
+        }
+    }
+
+    public void onVisibilityChanged(final int visibility) {
+        if (CameraManager.hasCameraPermission()) {
+            if (visibility == View.VISIBLE) {
+                CameraManager.get().openCamera();
+            } else {
+                CameraManager.get().closeCamera();
+            }
+        }
+    }
+
+    public Context getContext() {
+        return mHost.getView().getContext();
+    }
+
+    public void setOnTouchListener(final View.OnTouchListener listener) {
+        mHost.getView().setOnTouchListener(listener);
+    }
+
+    public int getHeight() {
+        return mHost.getView().getHeight();
+    }
+
+    public void onAttachedToWindow() {
+        if (CameraManager.hasCameraPermission()) {
+            CameraManager.get().openCamera();
+        }
+    }
+
+    public void onDetachedFromWindow() {
+        CameraManager.get().closeCamera();
+    }
+
+    public void onRestoreInstanceState() {
+        if (CameraManager.hasCameraPermission()) {
+            CameraManager.get().openCamera();
+        }
+    }
+
+    public void onCameraPermissionGranted() {
+        CameraManager.get().openCamera();
+    }
+
+    /**
+     * @return True if the view is valid and prepared for the camera to start showing the preview
+     */
+    public boolean isValid() {
+        return mHost.isValid();
+    }
+
+    /**
+     * Starts the camera preview on the current surface.  Abstracts out the differences in API
+     * from the CameraManager
+     * @throws IOException Which is caught by the CameraManager to display an error
+     */
+    public void startPreview(final Camera camera) throws IOException {
+        mHost.startPreview(camera);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/ContactMediaChooser.java b/src/com/android/messaging/ui/mediapicker/ContactMediaChooser.java
new file mode 100644
index 0000000..a81ed08
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/ContactMediaChooser.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.SafeAsyncTask;
+
+/**
+ * Chooser which allows the user to select an existing contact from contacts apps on this device.
+ * Note that this chooser requires the Manifest.permission.READ_CONTACTS which is one of the miminum
+ * set of permissions for this app. Thus no case to request READ_CONTACTS permission on it actually.
+ */
+class ContactMediaChooser extends MediaChooser {
+    private View mEnabledView;
+    private View mMissingPermissionView;
+
+    ContactMediaChooser(final MediaPicker mediaPicker) {
+        super(mediaPicker);
+    }
+
+    @Override
+    public int getSupportedMediaTypes() {
+        return MediaPicker.MEDIA_TYPE_VCARD;
+    }
+
+    @Override
+    public int getIconResource() {
+        return R.drawable.ic_person_light;
+    }
+
+    @Override
+    public int getIconDescriptionResource() {
+        return R.string.mediapicker_contactChooserDescription;
+    }
+
+    @Override
+    int getActionBarTitleResId() {
+        return R.string.mediapicker_contact_title;
+    }
+
+    @Override
+    protected View createView(final ViewGroup container) {
+        final LayoutInflater inflater = getLayoutInflater();
+        final View view =
+                inflater.inflate(
+                        R.layout.mediapicker_contact_chooser,
+                        container /* root */,
+                        false /* attachToRoot */);
+        mEnabledView = view.findViewById(R.id.mediapicker_enabled);
+        mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
+        mEnabledView.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(final View v) {
+                        // Launch an external picker to pick a contact as attachment.
+                        UIIntents.get().launchContactCardPicker(mMediaPicker);
+                    }
+                });
+        return view;
+    }
+
+    @Override
+    protected void setSelected(final boolean selected) {
+        super.setSelected(selected);
+        if (selected && !ContactUtil.hasReadContactsPermission()) {
+            mMediaPicker.requestPermissions(
+                    new String[] {Manifest.permission.READ_CONTACTS},
+                    MediaPicker.READ_CONTACT_PERMISSION_REQUEST_CODE);
+        }
+    }
+
+    @Override
+    protected void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (requestCode == MediaPicker.READ_CONTACT_PERMISSION_REQUEST_CODE) {
+            final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+            mEnabledView.setVisibility(permissionGranted ? View.VISIBLE : View.GONE);
+            mMissingPermissionView.setVisibility(permissionGranted ? View.GONE : View.VISIBLE);
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == UIIntents.REQUEST_PICK_CONTACT_CARD
+                && resultCode == Activity.RESULT_OK) {
+            Uri contactUri = data.getData();
+            if (contactUri != null) {
+                String lookupKey = null;
+                try (final Cursor c = getContext().getContentResolver().query(
+                                        contactUri,
+                                        new String[] {Contacts.LOOKUP_KEY},
+                                        null,
+                                        null,
+                                        null)) {
+                    if (c != null) {
+                        c.moveToFirst();
+                        lookupKey = c.getString(0);
+                    }
+                }
+                final Uri vCardUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);
+                if (vCardUri != null) {
+                    SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                        @Override
+                        public void run() {
+                            final PendingAttachmentData pendingItem =
+                                    PendingAttachmentData.createPendingAttachmentData(
+                                            ContentType.TEXT_VCARD.toLowerCase(), vCardUri);
+                            mMediaPicker.dispatchPendingItemAdded(pendingItem);
+                        }
+                    });
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java b/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java
new file mode 100644
index 0000000..c36467c
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.FileUtil;
+import com.android.messaging.util.ImageUtils;
+import com.android.messaging.util.SafeAsyncTask;
+
+/**
+ * Wraps around the functionalities to allow the user to pick an image/video/audio from the document
+ * picker. Instances of this class must be tied to a Fragment which is able to delegate activity
+ * result callbacks.
+ */
+public class DocumentImagePicker {
+
+    /**
+     * An interface for a listener that listens for when a document has been picked.
+     */
+    public interface SelectionListener {
+        /**
+         * Called when an document is selected from picker. At this point, the file hasn't been
+         * actually loaded and staged in the temp directory, so we are passing in a pending
+         * MessagePartData, which the consumer should use to display a placeholder image.
+         * @param pendingItem a temporary attachment data for showing the placeholder state.
+         */
+        void onDocumentSelected(PendingAttachmentData pendingItem);
+    }
+
+    // The owning fragment.
+    private final Fragment mFragment;
+
+    // The listener on the picker events.
+    private final SelectionListener mListener;
+
+    private static final String EXTRA_PHOTO_URL = "photo_url";
+
+    /**
+     * Creates a new instance of DocumentImagePicker.
+     * @param activity The activity that owns the picker, or the activity that hosts the owning
+     *        fragment.
+     */
+    public DocumentImagePicker(final Fragment fragment,
+            final SelectionListener listener) {
+        mFragment = fragment;
+        mListener = listener;
+    }
+
+    /**
+     * Intent out to open an image/video from document picker.
+     */
+    public void launchPicker() {
+        UIIntents.get().launchDocumentImagePicker(mFragment);
+    }
+
+    /**
+     * Must be called from the fragment/activity's onActivityResult().
+     */
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        // Sometimes called after media item has been picked from the document picker.
+        String url = data.getStringExtra(EXTRA_PHOTO_URL);
+        if (url == null) {
+            // we're using the builtin photo picker which supplies the return
+            // url as it's "data"
+            url = data.getDataString();
+            if (url == null) {
+                final Bundle extras = data.getExtras();
+                if (extras != null) {
+                    final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
+                    if (uri != null) {
+                        url = uri.toString();
+                    }
+                }
+            }
+        }
+
+        // Guard against null uri cases for when the activity returns a null/invalid intent.
+        if (url != null) {
+            final Uri uri = Uri.parse(url);
+            prepareDocumentForAttachment(uri);
+        }
+    }
+
+    private void prepareDocumentForAttachment(final Uri documentUri) {
+        // Notify our listener with a PendingAttachmentData containing the metadata.
+        // Asynchronously get the content type for the picked image since
+        // ImageUtils.getContentType() potentially involves I/O and can be expensive.
+        new SafeAsyncTask<Void, Void, String>() {
+            @Override
+            protected String doInBackgroundTimed(final Void... params) {
+                if (FileUtil.isInPrivateDir(documentUri)) {
+                    // hacker sending private app data. Bail out
+                    if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.ERROR)) {
+                        LogUtil.e(LogUtil.BUGLE_TAG, "Aborting attach of private app data ("
+                                + documentUri + ")");
+                    }
+                    return null;
+                }
+                return ImageUtils.getContentType(
+                        Factory.get().getApplicationContext().getContentResolver(), documentUri);
+            }
+
+            @Override
+            protected void onPostExecute(final String contentType) {
+                if (contentType == null) {
+                    return;     // bad uri on input
+                }
+                // Ask the listener to create a temporary placeholder item to show the progress.
+                final PendingAttachmentData pendingItem =
+                        PendingAttachmentData.createPendingAttachmentData(contentType,
+                                documentUri);
+                mListener.onDocumentSelected(pendingItem);
+            }
+        }.executeOnThreadPool();
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/GalleryGridAdapter.java b/src/com/android/messaging/ui/mediapicker/GalleryGridAdapter.java
new file mode 100644
index 0000000..fda3b19
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/GalleryGridAdapter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.mediapicker.GalleryGridItemView.HostInterface;
+import com.android.messaging.util.Assert;
+
+/**
+ * Bridges between the image cursor loaded by GalleryBoundCursorLoader and the GalleryGridView.
+ */
+public class GalleryGridAdapter extends CursorAdapter {
+    private GalleryGridItemView.HostInterface mGgivHostInterface;
+
+    public GalleryGridAdapter(final Context context, final Cursor cursor) {
+        super(context, cursor, 0);
+    }
+
+    public void setHostInterface(final HostInterface ggivHostInterface) {
+        mGgivHostInterface = ggivHostInterface;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void bindView(final View view, final Context context, final Cursor cursor) {
+        Assert.isTrue(view instanceof GalleryGridItemView);
+        final GalleryGridItemView galleryImageView = (GalleryGridItemView) view;
+        galleryImageView.bind(cursor, mGgivHostInterface);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
+        final LayoutInflater layoutInflater = LayoutInflater.from(context);
+        return layoutInflater.inflate(R.layout.gallery_grid_item_view, parent, false);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java b/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java
new file mode 100644
index 0000000..6cf509b
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.util.ContentType;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Shows an item in the gallery picker grid view. Hosts an FileImageView with a checkbox.
+ */
+public class GalleryGridItemView extends FrameLayout {
+    /**
+     * Implemented by the owner of this GalleryGridItemView instance to communicate on media
+     * picking and selection events.
+     */
+    public interface HostInterface {
+        void onItemClicked(View view, GalleryGridItemData data, boolean longClick);
+        boolean isItemSelected(GalleryGridItemData data);
+        boolean isMultiSelectEnabled();
+    }
+
+    @VisibleForTesting
+    GalleryGridItemData mData;
+    private AsyncImageView mImageView;
+    private CheckBox mCheckBox;
+    private RelativeLayout mAdditionalInfo;
+    private ImageView mIcon;
+    private LinearLayout mFileInfo;
+    private TextView mFileName;
+    private TextView mFileType;
+    private HostInterface mHostInterface;
+    private final OnClickListener mOnClickListener = new OnClickListener() {
+        @Override
+        public void onClick(final View v) {
+            mHostInterface.onItemClicked(GalleryGridItemView.this, mData, false /*longClick*/);
+        }
+    };
+
+    public GalleryGridItemView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mData = DataModel.get().createGalleryGridItemData();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mImageView = (AsyncImageView) findViewById(R.id.thumbnail);
+        mCheckBox = (CheckBox) findViewById(R.id.checkbox);
+        mCheckBox.setOnClickListener(mOnClickListener);
+        mAdditionalInfo = (RelativeLayout) findViewById(R.id.additional_info);
+        mIcon = (ImageView) findViewById(R.id.icon);
+        mFileInfo = (LinearLayout) findViewById(R.id.file_info);
+        mFileName = (TextView) findViewById(R.id.file_name);
+        mFileType = (TextView) findViewById(R.id.file_type);
+        setOnClickListener(mOnClickListener);
+        final OnLongClickListener longClickListener = new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(final View v) {
+                mHostInterface.onItemClicked(v, mData, true /* longClick */);
+                return true;
+            }
+        };
+        setOnLongClickListener(longClickListener);
+        mCheckBox.setOnLongClickListener(longClickListener);
+        addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                // Enlarge the clickable region for the checkbox to fill the entire view.
+                final Rect region = new Rect(0, 0, getWidth(), getHeight());
+                setTouchDelegate(new TouchDelegate(region, mCheckBox) {
+                    @Override
+                    public boolean onTouchEvent(MotionEvent event) {
+                        switch (event.getAction()) {
+                            case MotionEvent.ACTION_DOWN:
+                                setPressed(true);
+                                break;
+                            case MotionEvent.ACTION_UP:
+                            case MotionEvent.ACTION_CANCEL:
+                                setPressed(false);
+                                break;
+                        }
+                        return super.onTouchEvent(event);
+                    }
+                });
+            }
+        });
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        // The grid view auto-fit the columns, so we want to let the height match the width
+        // to make the image square.
+        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
+    }
+
+    public void bind(final Cursor cursor, final HostInterface hostInterface) {
+        final int desiredSize = getResources()
+                .getDimensionPixelSize(R.dimen.gallery_image_cell_size);
+        mData.bind(cursor, desiredSize, desiredSize);
+        mHostInterface = hostInterface;
+        updateViewState();
+    }
+
+    private void updateViewState() {
+        updateImageView();
+        if (mHostInterface.isMultiSelectEnabled() && !mData.isDocumentPickerItem()) {
+            mCheckBox.setVisibility(VISIBLE);
+            mCheckBox.setClickable(true);
+            mCheckBox.setChecked(mHostInterface.isItemSelected(mData));
+        } else {
+            mCheckBox.setVisibility(GONE);
+            mCheckBox.setClickable(false);
+        }
+    }
+
+    private void updateImageView() {
+        if (mData.isDocumentPickerItem()) {
+            setBackgroundColor(ConversationDrawables.get().getConversationThemeColor());
+            mIcon.setImageResource(R.drawable.ic_photo_library_light);
+            mIcon.clearColorFilter();
+            mImageView.setVisibility(GONE);
+            mIcon.setVisibility(VISIBLE);
+            mFileInfo.setVisibility(GONE);
+            mAdditionalInfo.setVisibility(VISIBLE);
+        } else {
+            final String contentType = mData.getContentType();
+            if (ContentType.isAudioType(contentType)) {
+                setBackgroundColor(
+                        getResources().getColor(R.color.gallery_image_default_background));
+                mIcon.setImageResource(R.drawable.ic_music);
+                mIcon.setColorFilter(
+                        ConversationDrawables.get().getConversationThemeColor(),
+                        PorterDuff.Mode.SRC_IN);
+                mFileName.setText(mData.getFileName());
+                String[] type = contentType.split("/");
+                mFileType.setText(type[1].toUpperCase() + " " + type[0]);
+                mImageView.setVisibility(GONE);
+                mIcon.setVisibility(VISIBLE);
+                mFileInfo.setVisibility(VISIBLE);
+                mAdditionalInfo.setVisibility(VISIBLE);
+            } else { // For image and video types
+                mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+                setBackgroundColor(
+                        getResources().getColor(R.color.gallery_image_default_background));
+                mImageView.setImageResourceId(mData.getImageRequestDescriptor());
+                mImageView.setVisibility(VISIBLE);
+                if (ContentType.isVideoType(mData.getContentType())) {
+                    mIcon.setImageResource(R.drawable.ic_video_play_light);
+                    mIcon.clearColorFilter();
+                    mIcon.setVisibility(VISIBLE);
+                } else {
+                    mIcon.setVisibility(GONE);
+                }
+                mFileInfo.setVisibility(GONE);
+                mAdditionalInfo.setVisibility(VISIBLE);
+                final long dateSeconds = mData.getDateSeconds();
+                final boolean isValidDate = (dateSeconds > 0);
+                final int templateId = isValidDate ?
+                        R.string.mediapicker_gallery_image_item_description :
+                        R.string.mediapicker_gallery_image_item_description_no_date;
+                String contentDescription = String.format(getResources().getString(templateId),
+                        dateSeconds * TimeUnit.SECONDS.toMillis(1));
+                mImageView.setContentDescription(contentDescription);
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/GalleryGridView.java b/src/com/android/messaging/ui/mediapicker/GalleryGridView.java
new file mode 100644
index 0000000..39912f9
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/GalleryGridView.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import androidx.collection.ArrayMap;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageDataListener;
+import com.android.messaging.ui.PersistentInstanceState;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Shows a list of galley mediae from external storage in a GridView with multi-select capabilities,
+ * and with the option to intent out to a standalone media picker.
+ */
+public class GalleryGridView extends MediaPickerGridView implements
+        GalleryGridItemView.HostInterface,
+        PersistentInstanceState,
+        DraftMessageDataListener {
+    /**
+     * Implemented by the owner of this GalleryGridView instance to communicate on media picking and
+     * multi-media selection events.
+     */
+    public interface GalleryGridViewListener {
+        void onDocumentPickerItemClicked();
+        void onItemSelected(MessagePartData item);
+        void onItemUnselected(MessagePartData item);
+        void onConfirmSelection();
+        void onUpdate();
+    }
+
+    private GalleryGridViewListener mListener;
+
+    // TODO: Consider putting this into the data model object if we add more states.
+    private final ArrayMap<Uri, MessagePartData> mSelectedImages;
+    private boolean mIsMultiSelectMode = false;
+    private ImmutableBindingRef<DraftMessageData> mDraftMessageDataModel;
+
+    public GalleryGridView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mSelectedImages = new ArrayMap<Uri, MessagePartData>();
+    }
+
+    public void setHostInterface(final GalleryGridViewListener hostInterface) {
+        mListener = hostInterface;
+    }
+
+    public void setDraftMessageDataModel(final BindingBase<DraftMessageData> dataModel) {
+        mDraftMessageDataModel = BindingBase.createBindingReference(dataModel);
+        mDraftMessageDataModel.getData().addListener(this);
+    }
+
+    @Override
+    public void onItemClicked(final View view, final GalleryGridItemData data,
+            final boolean longClick) {
+        if (data.isDocumentPickerItem()) {
+            mListener.onDocumentPickerItemClicked();
+        } else if (ContentType.isMediaType(data.getContentType())) {
+            if (longClick) {
+                // Turn on multi-select mode when an item is long-pressed.
+                setMultiSelectEnabled(true);
+            }
+
+            final Rect startRect = new Rect();
+            view.getGlobalVisibleRect(startRect);
+            if (isMultiSelectEnabled()) {
+                toggleItemSelection(startRect, data);
+            } else {
+                mListener.onItemSelected(data.constructMessagePartData(startRect));
+            }
+        } else {
+            LogUtil.w(LogUtil.BUGLE_TAG,
+                    "Selected item has invalid contentType " + data.getContentType());
+        }
+    }
+
+    @Override
+    public boolean isItemSelected(final GalleryGridItemData data) {
+        return mSelectedImages.containsKey(data.getImageUri());
+    }
+
+    int getSelectionCount() {
+        return mSelectedImages.size();
+    }
+
+    @Override
+    public boolean isMultiSelectEnabled() {
+        return mIsMultiSelectMode;
+    }
+
+    private void toggleItemSelection(final Rect startRect, final GalleryGridItemData data) {
+        Assert.isTrue(isMultiSelectEnabled());
+        if (isItemSelected(data)) {
+            final MessagePartData item = mSelectedImages.remove(data.getImageUri());
+            mListener.onItemUnselected(item);
+            if (mSelectedImages.size() == 0) {
+                // No media is selected any more, turn off multi-select mode.
+                setMultiSelectEnabled(false);
+            }
+        } else {
+            final MessagePartData item = data.constructMessagePartData(startRect);
+            mSelectedImages.put(data.getImageUri(), item);
+            mListener.onItemSelected(item);
+        }
+        invalidateViews();
+    }
+
+    private void toggleMultiSelect() {
+        mIsMultiSelectMode = !mIsMultiSelectMode;
+        invalidateViews();
+    }
+
+    private void setMultiSelectEnabled(final boolean enabled) {
+        if (mIsMultiSelectMode != enabled) {
+            toggleMultiSelect();
+        }
+    }
+
+    private boolean canToggleMultiSelect() {
+        // We allow the user to toggle multi-select mode only when nothing has selected. If
+        // something has been selected, we show a confirm button instead.
+        return mSelectedImages.size() == 0;
+    }
+
+    public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
+        inflater.inflate(R.menu.gallery_picker_menu, menu);
+        final MenuItem toggleMultiSelect = menu.findItem(R.id.action_multiselect);
+        final MenuItem confirmMultiSelect = menu.findItem(R.id.action_confirm_multiselect);
+        final boolean canToggleMultiSelect = canToggleMultiSelect();
+        toggleMultiSelect.setVisible(canToggleMultiSelect);
+        confirmMultiSelect.setVisible(!canToggleMultiSelect);
+    }
+
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_multiselect:
+                Assert.isTrue(canToggleMultiSelect());
+                toggleMultiSelect();
+                return true;
+
+            case R.id.action_confirm_multiselect:
+                Assert.isTrue(!canToggleMultiSelect());
+                mListener.onConfirmSelection();
+                return true;
+        }
+        return false;
+    }
+
+
+    @Override
+    public void onDraftChanged(final DraftMessageData data, final int changeFlags) {
+        mDraftMessageDataModel.ensureBound(data);
+        // Whenever attachment changed, refresh selection state to remove those that are not
+        // selected.
+        if ((changeFlags & DraftMessageData.ATTACHMENTS_CHANGED) ==
+                DraftMessageData.ATTACHMENTS_CHANGED) {
+            refreshImageSelectionStateOnAttachmentChange();
+        }
+    }
+
+    @Override
+    public void onDraftAttachmentLimitReached(final DraftMessageData data) {
+        mDraftMessageDataModel.ensureBound(data);
+        // Whenever draft attachment limit is reach, refresh selection state to remove those
+        // not actually added to draft.
+        refreshImageSelectionStateOnAttachmentChange();
+    }
+
+    @Override
+    public void onDraftAttachmentLoadFailed() {
+        // Nothing to do since the failed attachment gets removed automatically.
+    }
+
+    private void refreshImageSelectionStateOnAttachmentChange() {
+        boolean changed = false;
+        final Iterator<Map.Entry<Uri, MessagePartData>> iterator =
+                mSelectedImages.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<Uri, MessagePartData> entry = iterator.next();
+            if (!mDraftMessageDataModel.getData().containsAttachment(entry.getKey())) {
+                iterator.remove();
+                changed = true;
+            }
+        }
+
+        if (changed) {
+            mListener.onUpdate();
+            invalidateViews();
+        }
+    }
+
+    @Override   // PersistentInstanceState
+    public Parcelable saveState() {
+        return onSaveInstanceState();
+    }
+
+    @Override   // PersistentInstanceState
+    public void restoreState(final Parcelable restoredState) {
+        onRestoreInstanceState(restoredState);
+        invalidateViews();
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        final SavedState savedState = new SavedState(superState);
+        savedState.isMultiSelectMode = mIsMultiSelectMode;
+        savedState.selectedImages = mSelectedImages.values()
+                .toArray(new MessagePartData[mSelectedImages.size()]);
+        return savedState;
+    }
+
+    @Override
+    public void onRestoreInstanceState(final Parcelable state) {
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        final SavedState savedState = (SavedState) state;
+        super.onRestoreInstanceState(savedState.getSuperState());
+        mIsMultiSelectMode = savedState.isMultiSelectMode;
+        mSelectedImages.clear();
+        for (int i = 0; i < savedState.selectedImages.length; i++) {
+            final MessagePartData selectedImage = savedState.selectedImages[i];
+            mSelectedImages.put(selectedImage.getContentUri(), selectedImage);
+        }
+    }
+
+    @Override   // PersistentInstanceState
+    public void resetState() {
+        mSelectedImages.clear();
+        mIsMultiSelectMode = false;
+        invalidateViews();
+    }
+
+    public static class SavedState extends BaseSavedState {
+        boolean isMultiSelectMode;
+        MessagePartData[] selectedImages;
+
+        SavedState(final Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(final Parcel in) {
+            super(in);
+            isMultiSelectMode = in.readInt() == 1 ? true : false;
+
+            // Read parts
+            final int partCount = in.readInt();
+            selectedImages = new MessagePartData[partCount];
+            for (int i = 0; i < partCount; i++) {
+                selectedImages[i] = ((MessagePartData) in.readParcelable(
+                        MessagePartData.class.getClassLoader()));
+            }
+        }
+
+        @Override
+        public void writeToParcel(final Parcel out, final int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(isMultiSelectMode ? 1 : 0);
+
+            // Write parts
+            out.writeInt(selectedImages.length);
+            for (final MessagePartData image : selectedImages) {
+                out.writeParcelable(image, flags);
+            }
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(final Parcel in) {
+                return new SavedState(in);
+            }
+            @Override
+            public SavedState[] newArray(final int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java b/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java
new file mode 100644
index 0000000..6192c4f
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import androidx.appcompat.app.ActionBar;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.mediapicker.DocumentImagePicker.SelectionListener;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Chooser which allows the user to select one or more existing images or videos or audios.
+ */
+class GalleryMediaChooser extends MediaChooser implements
+        GalleryGridView.GalleryGridViewListener, MediaPickerDataListener {
+    private final GalleryGridAdapter mAdapter;
+    private GalleryGridView mGalleryGridView;
+    private View mMissingPermissionView;
+
+    /** Handles picking a media from the document picker. */
+    private DocumentImagePicker mDocumentImagePicker;
+
+    GalleryMediaChooser(final MediaPicker mediaPicker) {
+        super(mediaPicker);
+        mAdapter = new GalleryGridAdapter(Factory.get().getApplicationContext(), null);
+        mDocumentImagePicker = new DocumentImagePicker(mMediaPicker,
+                new SelectionListener() {
+                    @Override
+                    public void onDocumentSelected(final PendingAttachmentData data) {
+                        if (mBindingRef.isBound()) {
+                            mMediaPicker.dispatchPendingItemAdded(data);
+                        }
+                    }
+                });
+    }
+
+    @Override
+    public int getSupportedMediaTypes() {
+        return (MediaPicker.MEDIA_TYPE_IMAGE
+                | MediaPicker.MEDIA_TYPE_VIDEO
+                | MediaPicker.MEDIA_TYPE_AUDIO);
+    }
+
+    @Override
+    public View destroyView() {
+        mGalleryGridView.setAdapter(null);
+        mAdapter.setHostInterface(null);
+        // The loader is started only if startMediaPickerDataLoader() is called
+        if (OsUtil.hasStoragePermission()) {
+            mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_MEDIA_LOADER);
+        }
+        return super.destroyView();
+    }
+
+    @Override
+    public int getIconResource() {
+        return R.drawable.ic_image_light;
+    }
+
+    @Override
+    public int getIconDescriptionResource() {
+        return R.string.mediapicker_galleryChooserDescription;
+    }
+
+    @Override
+    public boolean canSwipeDown() {
+        return mGalleryGridView.canSwipeDown();
+    }
+
+    @Override
+    public void onItemSelected(final MessagePartData item) {
+        mMediaPicker.dispatchItemsSelected(item, !mGalleryGridView.isMultiSelectEnabled());
+    }
+
+    @Override
+    public void onItemUnselected(final MessagePartData item) {
+        mMediaPicker.dispatchItemUnselected(item);
+    }
+
+    @Override
+    public void onConfirmSelection() {
+        // The user may only confirm if multiselect is enabled.
+        Assert.isTrue(mGalleryGridView.isMultiSelectEnabled());
+        mMediaPicker.dispatchConfirmItemSelection();
+    }
+
+    @Override
+    public void onUpdate() {
+        mMediaPicker.invalidateOptionsMenu();
+    }
+
+    @Override
+    public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
+        if (mView != null) {
+            mGalleryGridView.onCreateOptionsMenu(inflater, menu);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        return (mView != null) ? mGalleryGridView.onOptionsItemSelected(item) : false;
+    }
+
+    @Override
+    protected View createView(final ViewGroup container) {
+        final LayoutInflater inflater = getLayoutInflater();
+        final View view = inflater.inflate(
+                R.layout.mediapicker_gallery_chooser,
+                container /* root */,
+                false /* attachToRoot */);
+
+        mGalleryGridView = (GalleryGridView) view.findViewById(R.id.gallery_grid_view);
+        mAdapter.setHostInterface(mGalleryGridView);
+        mGalleryGridView.setAdapter(mAdapter);
+        mGalleryGridView.setHostInterface(this);
+        mGalleryGridView.setDraftMessageDataModel(mMediaPicker.getDraftMessageDataModel());
+        if (OsUtil.hasStoragePermission()) {
+            startMediaPickerDataLoader();
+        }
+
+        mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
+        updateForPermissionState(OsUtil.hasStoragePermission());
+        return view;
+    }
+
+    @Override
+    int getActionBarTitleResId() {
+        return R.string.mediapicker_gallery_title;
+    }
+
+    @Override
+    public void onDocumentPickerItemClicked() {
+        // Launch an external picker to pick item from document picker as attachment.
+        mDocumentImagePicker.launchPicker();
+    }
+
+    @Override
+    void updateActionBar(final ActionBar actionBar) {
+        super.updateActionBar(actionBar);
+        if (mGalleryGridView == null) {
+            return;
+        }
+        final int selectionCount = mGalleryGridView.getSelectionCount();
+        if (selectionCount > 0 && mGalleryGridView.isMultiSelectEnabled()) {
+            actionBar.setTitle(getContext().getResources().getString(
+                    R.string.mediapicker_gallery_title_selection,
+                    selectionCount));
+        }
+    }
+
+    @Override
+    public void onMediaPickerDataUpdated(final MediaPickerData mediaPickerData, final Object data,
+            final int loaderId) {
+        mBindingRef.ensureBound(mediaPickerData);
+        Assert.equals(MediaPickerData.GALLERY_MEDIA_LOADER, loaderId);
+        Cursor rawCursor = null;
+        if (data instanceof Cursor) {
+            rawCursor = (Cursor) data;
+        }
+        // Before delivering the cursor, wrap around the local gallery cursor
+        // with an extra item for document picker integration in the front.
+        final MatrixCursor specialItemsCursor =
+                new MatrixCursor(GalleryGridItemData.SPECIAL_ITEM_COLUMNS);
+        specialItemsCursor.addRow(new Object[] { GalleryGridItemData.ID_DOCUMENT_PICKER_ITEM });
+        final MergeCursor cursor =
+                new MergeCursor(new Cursor[] { specialItemsCursor, rawCursor });
+        mAdapter.swapCursor(cursor);
+    }
+
+    @Override
+    public void onResume() {
+        if (OsUtil.hasStoragePermission()) {
+            // Work around a bug in MediaStore where cursors querying the Files provider don't get
+            // updated for changes to Images.Media or Video.Media.
+            startMediaPickerDataLoader();
+        }
+    }
+
+    @Override
+    protected void setSelected(final boolean selected) {
+        super.setSelected(selected);
+        if (selected && !OsUtil.hasStoragePermission()) {
+            mMediaPicker.requestPermissions(
+                    new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
+                    MediaPicker.GALLERY_PERMISSION_REQUEST_CODE);
+        }
+    }
+
+    private void startMediaPickerDataLoader() {
+        mBindingRef
+                .getData()
+                .startLoader(MediaPickerData.GALLERY_MEDIA_LOADER, mBindingRef, null, this);
+    }
+
+    @Override
+    protected void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (requestCode == MediaPicker.GALLERY_PERMISSION_REQUEST_CODE) {
+            final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+            if (permissionGranted) {
+                startMediaPickerDataLoader();
+            }
+            updateForPermissionState(permissionGranted);
+        }
+    }
+
+    private void updateForPermissionState(final boolean granted) {
+        // onRequestPermissionsResult can sometimes get called before createView().
+        if (mGalleryGridView == null) {
+            return;
+        }
+
+        mGalleryGridView.setVisibility(granted ? View.VISIBLE : View.GONE);
+        mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
+    }
+
+    @Override
+    protected void onActivityResult(
+            final int requestCode, final int resultCode, final Intent data) {
+        if (requestCode == UIIntents.REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER
+                && resultCode == Activity.RESULT_OK) {
+            mDocumentImagePicker.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/HardwareCameraPreview.java b/src/com/android/messaging/ui/mediapicker/HardwareCameraPreview.java
new file mode 100644
index 0000000..45d9579
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/HardwareCameraPreview.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.view.TextureView;
+import android.view.View;
+
+import java.io.IOException;
+
+/**
+ * A hardware accelerated preview texture for the camera.  This is the preferred CameraPreview
+ * because it animates smoother.  When hardware acceleration isn't available, SoftwareCameraPreview
+ * is used.
+ *
+ * There is a significant amount of duplication between HardwareCameraPreview and
+ * SoftwareCameraPreview which we can't easily share due to a lack of multiple inheritance, The
+ * implementations of the shared methods are delegated to CameraPreview
+ */
+public class HardwareCameraPreview extends TextureView implements CameraPreview.CameraPreviewHost {
+    private CameraPreview mPreview;
+
+    public HardwareCameraPreview(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mPreview = new CameraPreview(this);
+        setSurfaceTextureListener(new SurfaceTextureListener() {
+            @Override
+            public void onSurfaceTextureAvailable(final SurfaceTexture surfaceTexture, final int i, final int i2) {
+                CameraManager.get().setSurface(mPreview);
+            }
+
+            @Override
+            public void onSurfaceTextureSizeChanged(final SurfaceTexture surfaceTexture, final int i, final int i2) {
+                CameraManager.get().setSurface(mPreview);
+            }
+
+            @Override
+            public boolean onSurfaceTextureDestroyed(final SurfaceTexture surfaceTexture) {
+                CameraManager.get().setSurface(null);
+                return true;
+            }
+
+            @Override
+            public void onSurfaceTextureUpdated(final SurfaceTexture surfaceTexture) {
+                CameraManager.get().setSurface(mPreview);
+            }
+        });
+    }
+
+    @Override
+    protected void onVisibilityChanged(final View changedView, final int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        mPreview.onVisibilityChanged(visibility);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mPreview.onDetachedFromWindow();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mPreview.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onRestoreInstanceState(final Parcelable state) {
+        super.onRestoreInstanceState(state);
+        mPreview.onRestoreInstanceState();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        widthMeasureSpec = mPreview.getWidthMeasureSpec(widthMeasureSpec, heightMeasureSpec);
+        heightMeasureSpec = mPreview.getHeightMeasureSpec(widthMeasureSpec, heightMeasureSpec);
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public boolean isValid() {
+        return getSurfaceTexture() != null;
+    }
+
+    @Override
+    public void startPreview(final Camera camera) throws IOException {
+        camera.setPreviewTexture(getSurfaceTexture());
+    }
+
+    @Override
+    public void onCameraPermissionGranted() {
+        mPreview.onCameraPermissionGranted();
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/ImagePersistTask.java b/src/com/android/messaging/ui/mediapicker/ImagePersistTask.java
new file mode 100644
index 0000000..637eb84
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/ImagePersistTask.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.net.Uri;
+
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.exif.ExifInterface;
+import com.android.messaging.util.exif.ExifTag;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class ImagePersistTask extends SafeAsyncTask<Void, Void, Void> {
+    private static final String JPEG_EXTENSION = "jpg";
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private int mWidth;
+    private int mHeight;
+    private final float mHeightPercent;
+    private final byte[] mBytes;
+    private final Context mContext;
+    private final CameraManager.MediaCallback mCallback;
+    private Uri mOutputUri;
+    private Exception mException;
+
+    public ImagePersistTask(
+            final int width,
+            final int height,
+            final float heightPercent,
+            final byte[] bytes,
+            final Context context,
+            final CameraManager.MediaCallback callback) {
+        Assert.isTrue(heightPercent >= 0 && heightPercent <= 1);
+        Assert.notNull(bytes);
+        Assert.notNull(context);
+        Assert.notNull(callback);
+        mWidth = width;
+        mHeight = height;
+        mHeightPercent = heightPercent;
+        mBytes = bytes;
+        mContext = context;
+        mCallback = callback;
+        // TODO: We probably want to store directly in MMS storage to prevent this
+        // intermediate step
+        mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri(JPEG_EXTENSION);
+    }
+
+    @Override
+    protected Void doInBackgroundTimed(final Void... params) {
+        OutputStream outputStream = null;
+        Bitmap bitmap = null;
+        Bitmap clippedBitmap = null;
+        try {
+            outputStream =
+                    mContext.getContentResolver().openOutputStream(mOutputUri);
+            if (mHeightPercent != 1.0f) {
+                int orientation = android.media.ExifInterface.ORIENTATION_UNDEFINED;
+                final ExifInterface exifInterface = new ExifInterface();
+                try {
+                    exifInterface.readExif(mBytes);
+                    final Integer orientationValue =
+                            exifInterface.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+                    if (orientationValue != null) {
+                        orientation = orientationValue.intValue();
+                    }
+                    // The thumbnail is of the full image, but we're cropping it, so just clear
+                    // the thumbnail
+                    exifInterface.setCompressedThumbnail((byte[]) null);
+                } catch (IOException e) {
+                    // Couldn't get exif tags, not the end of the world
+                }
+                bitmap = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
+                final int clippedWidth;
+                final int clippedHeight;
+                if (ExifInterface.getOrientationParams(orientation).invertDimensions) {
+                    Assert.equals(mWidth, bitmap.getHeight());
+                    Assert.equals(mHeight, bitmap.getWidth());
+                    clippedWidth = (int) (mHeight * mHeightPercent);
+                    clippedHeight = mWidth;
+                } else {
+                    Assert.equals(mWidth, bitmap.getWidth());
+                    Assert.equals(mHeight, bitmap.getHeight());
+                    clippedWidth = mWidth;
+                    clippedHeight = (int) (mHeight * mHeightPercent);
+                }
+                final int offsetTop = (bitmap.getHeight() - clippedHeight) / 2;
+                final int offsetLeft = (bitmap.getWidth() - clippedWidth) / 2;
+                mWidth = clippedWidth;
+                mHeight = clippedHeight;
+                clippedBitmap = Bitmap.createBitmap(clippedWidth, clippedHeight,
+                        Bitmap.Config.ARGB_8888);
+                clippedBitmap.setDensity(bitmap.getDensity());
+                final Canvas clippedBitmapCanvas = new Canvas(clippedBitmap);
+                final Matrix matrix = new Matrix();
+                matrix.postTranslate(-offsetLeft, -offsetTop);
+                clippedBitmapCanvas.drawBitmap(bitmap, matrix, null /* paint */);
+                clippedBitmapCanvas.save();
+                // EXIF data can take a big chunk of the file size and is often cleared by the
+                // carrier, only store orientation since that's critical
+                ExifTag orientationTag = exifInterface.getTag(ExifInterface.TAG_ORIENTATION);
+                exifInterface.clearExif();
+                exifInterface.setTag(orientationTag);
+                exifInterface.writeExif(clippedBitmap, outputStream);
+            } else {
+                outputStream.write(mBytes);
+            }
+        } catch (final IOException e) {
+            mOutputUri = null;
+            mException = e;
+            LogUtil.e(TAG, "Unable to persist image to temp storage " + e);
+        } finally {
+            if (bitmap != null) {
+                bitmap.recycle();
+            }
+
+            if (clippedBitmap != null) {
+                clippedBitmap.recycle();
+            }
+
+            if (outputStream != null) {
+                try {
+                    outputStream.flush();
+                } catch (final IOException e) {
+                    mOutputUri = null;
+                    mException = e;
+                    LogUtil.e(TAG, "error trying to flush and close the outputStream" + e);
+                } finally {
+                    try {
+                        outputStream.close();
+                    } catch (final IOException e) {
+                        // Do nothing.
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void onPostExecute(final Void aVoid) {
+        if (mOutputUri != null) {
+            mCallback.onMediaReady(mOutputUri, ContentType.IMAGE_JPEG, mWidth, mHeight);
+        } else {
+            Assert.notNull(mException);
+            mCallback.onMediaFailed(mException);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java b/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java
new file mode 100644
index 0000000..06730a3
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.media.MediaRecorder;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UiUtils;
+
+import java.io.IOException;
+
+/**
+ * Wraps around the functionalities of MediaRecorder, performs routine setup for audio recording
+ * and updates the audio level to be displayed in UI.
+ *
+ * During the start and end of a recording session, we kick off a thread that polls for audio
+ * levels, and updates the thread-safe AudioLevelSource instance. Consumers may bind to the
+ * sound level by either polling from the level source, or register for a level change callback
+ * on the level source object. In Bugle, the UI element (SoundLevels) polls for the sound level
+ * on the UI thread by using animation ticks and invalidating itself.
+ *
+ * Aside from tracking sound levels, this also encapsulates the functionality to save the file
+ * to the scratch space. The saved file is returned by calling stopRecording().
+ */
+public class LevelTrackingMediaRecorder {
+    // We refresh sound level every 100ms during a recording session.
+    private static final int REFRESH_INTERVAL_MILLIS = 100;
+
+    // The native amplitude returned from MediaRecorder ranges from 0~32768 (unfortunately, this
+    // is not a constant that's defined anywhere, but the framework's Recorder app is using the
+    // same hard-coded number). Therefore, a constant is needed in order to make it 0~100.
+    private static final int MAX_AMPLITUDE_FACTOR = 32768 / 100;
+
+    // We want to limit the max audio file size by the max message size allowed by MmsConfig,
+    // plus multiplied by this fudge ratio to guarantee that we don't go over limit.
+    private static final float MAX_SIZE_RATIO = 0.8f;
+
+    // Default recorder settings for Bugle.
+    // TODO: Do we want these to be tweakable?
+    private static final int MEDIA_RECORDER_AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
+    private static final int MEDIA_RECORDER_OUTPUT_FORMAT = MediaRecorder.OutputFormat.THREE_GPP;
+    private static final int MEDIA_RECORDER_AUDIO_ENCODER = MediaRecorder.AudioEncoder.AMR_NB;
+
+    private final AudioLevelSource mLevelSource;
+    private Thread mRefreshLevelThread;
+    private MediaRecorder mRecorder;
+    private Uri mOutputUri;
+    private ParcelFileDescriptor mOutputFD;
+
+    public LevelTrackingMediaRecorder() {
+        mLevelSource = new AudioLevelSource();
+    }
+
+    public AudioLevelSource getLevelSource() {
+        return mLevelSource;
+    }
+
+    /**
+     * @return if we are currently in a recording session.
+     */
+    public boolean isRecording() {
+        return mRecorder != null;
+    }
+
+    /**
+     * Start a new recording session.
+     * @return true if a session is successfully started; false if something went wrong or if
+     *         we are already recording.
+     */
+    public boolean startRecording(final MediaRecorder.OnErrorListener errorListener,
+            final MediaRecorder.OnInfoListener infoListener, int maxSize) {
+        synchronized (LevelTrackingMediaRecorder.class) {
+            if (mRecorder == null) {
+                mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri(
+                        ContentType.THREE_GPP_EXTENSION);
+                mRecorder = new MediaRecorder();
+                try {
+                    // The scratch space file is a Uri, however MediaRecorder
+                    // API only accepts absolute FD's. Therefore, get the
+                    // FileDescriptor from the content resolver to ensure the
+                    // directory is created and get the file path to output the
+                    // audio to.
+                    maxSize *= MAX_SIZE_RATIO;
+                    mOutputFD = Factory.get().getApplicationContext()
+                            .getContentResolver().openFileDescriptor(mOutputUri, "w");
+                    mRecorder.setAudioSource(MEDIA_RECORDER_AUDIO_SOURCE);
+                    mRecorder.setOutputFormat(MEDIA_RECORDER_OUTPUT_FORMAT);
+                    mRecorder.setAudioEncoder(MEDIA_RECORDER_AUDIO_ENCODER);
+                    mRecorder.setOutputFile(mOutputFD.getFileDescriptor());
+                    mRecorder.setMaxFileSize(maxSize);
+                    mRecorder.setOnErrorListener(errorListener);
+                    mRecorder.setOnInfoListener(infoListener);
+                    mRecorder.prepare();
+                    mRecorder.start();
+                    startTrackingSoundLevel();
+                    return true;
+                } catch (final Exception e) {
+                    // There may be a device failure or I/O failure, record the error but
+                    // don't fail.
+                    LogUtil.e(LogUtil.BUGLE_TAG, "Something went wrong when starting " +
+                            "media recorder. " + e);
+                    UiUtils.showToastAtBottom(R.string.audio_recording_start_failed);
+                    stopRecording();
+                }
+            } else {
+                Assert.fail("Trying to start a new recording session while already recording!");
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Stop the current recording session.
+     * @return the Uri of the output file, or null if not currently recording.
+     */
+    public Uri stopRecording() {
+        synchronized (LevelTrackingMediaRecorder.class) {
+            if (mRecorder != null) {
+                try {
+                    mRecorder.stop();
+                } catch (final RuntimeException ex) {
+                    // This may happen when the recording is too short, so just drop the recording
+                    // in this case.
+                    LogUtil.w(LogUtil.BUGLE_TAG, "Something went wrong when stopping " +
+                            "media recorder. " + ex);
+                    if (mOutputUri != null) {
+                        final Uri outputUri = mOutputUri;
+                        SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                            @Override
+                            public void run() {
+                                Factory.get().getApplicationContext().getContentResolver().delete(
+                                        outputUri, null, null);
+                            }
+                        });
+                        mOutputUri = null;
+                    }
+                } finally {
+                    mRecorder.release();
+                    mRecorder = null;
+                }
+            } else {
+                Assert.fail("Not currently recording!");
+                return null;
+            }
+        }
+
+        if (mOutputFD != null) {
+            try {
+                mOutputFD.close();
+            } catch (final IOException e) {
+                // Nothing to do
+            }
+            mOutputFD = null;
+        }
+
+        stopTrackingSoundLevel();
+        return mOutputUri;
+    }
+
+    private int getAmplitude() {
+        synchronized (LevelTrackingMediaRecorder.class) {
+            if (mRecorder != null) {
+                final int maxAmplitude = mRecorder.getMaxAmplitude() / MAX_AMPLITUDE_FACTOR;
+                return Math.min(maxAmplitude, 100);
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    private void startTrackingSoundLevel() {
+        stopTrackingSoundLevel();
+        mRefreshLevelThread = new Thread() {
+            @Override
+            public void run() {
+                try {
+                    while (true) {
+                        synchronized (LevelTrackingMediaRecorder.class) {
+                            if (mRecorder != null) {
+                                mLevelSource.setSpeechLevel(getAmplitude());
+                            } else {
+                                // The recording session is over, finish the thread.
+                                return;
+                            }
+                        }
+                        Thread.sleep(REFRESH_INTERVAL_MILLIS);
+                    }
+                } catch (final InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        };
+        mRefreshLevelThread.start();
+    }
+
+    private void stopTrackingSoundLevel() {
+        if (mRefreshLevelThread != null && mRefreshLevelThread.isAlive()) {
+            mRefreshLevelThread.interrupt();
+            mRefreshLevelThread = null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/MediaChooser.java b/src/com/android/messaging/ui/mediapicker/MediaChooser.java
new file mode 100644
index 0000000..0549e5b
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/MediaChooser.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.Intent;
+import androidx.appcompat.app.ActionBar;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
+import com.android.messaging.ui.BasePagerViewHolder;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.OsUtil;
+
+abstract class MediaChooser extends BasePagerViewHolder
+        implements DraftMessageSubscriptionDataProvider {
+    /** The media picker that the chooser is hosted in */
+    protected final MediaPicker mMediaPicker;
+
+    /** Referencing the main media picker binding to perform data loading */
+    protected final ImmutableBindingRef<MediaPickerData> mBindingRef;
+
+    /** True if this is the selected chooser */
+    protected boolean mSelected;
+
+    /** True if this chooser is open */
+    protected boolean mOpen;
+
+    /** The button to show in the tab strip */
+    private ImageButton mTabButton;
+
+    /** Used by subclasses to indicate that no loader is required from the data model in order for
+     * this chooser to function.
+     */
+    public static final int NO_LOADER_REQUIRED = -1;
+
+    /**
+     * Initializes a new instance of the Chooser class
+     * @param mediaPicker The media picker that the chooser is hosted in
+     */
+    MediaChooser(final MediaPicker mediaPicker) {
+        Assert.notNull(mediaPicker);
+        mMediaPicker = mediaPicker;
+        mBindingRef = mediaPicker.getMediaPickerDataBinding();
+        mSelected = false;
+    }
+
+    protected void setSelected(final boolean selected) {
+        mSelected = selected;
+        if (selected) {
+            // If we're selected, it must be open
+            mOpen = true;
+        }
+        if (mTabButton != null) {
+            mTabButton.setSelected(selected);
+            mTabButton.setAlpha(selected ? 1 : 0.5f);
+        }
+    }
+
+    ImageButton getTabButton() {
+        return mTabButton;
+    }
+
+    void onCreateTabButton(final LayoutInflater inflater, final ViewGroup parent) {
+        mTabButton = (ImageButton) inflater.inflate(
+                R.layout.mediapicker_tab_button,
+                parent,
+                false /* addToParent */);
+        mTabButton.setImageResource(getIconResource());
+        mTabButton.setContentDescription(
+                inflater.getContext().getResources().getString(getIconDescriptionResource()));
+        setSelected(mSelected);
+        mTabButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View view) {
+                mMediaPicker.selectChooser(MediaChooser.this);
+            }
+        });
+    }
+
+    protected Context getContext() {
+        return mMediaPicker.getActivity();
+    }
+
+    protected FragmentManager getFragmentManager() {
+        return OsUtil.isAtLeastJB_MR1() ? mMediaPicker.getChildFragmentManager() :
+                mMediaPicker.getFragmentManager();
+    }
+    protected LayoutInflater getLayoutInflater() {
+        return LayoutInflater.from(getContext());
+    }
+
+    /** Allows the chooser to handle full screen change */
+    void onFullScreenChanged(final boolean fullScreen) {}
+
+    /** Allows the chooser to handle the chooser being opened or closed */
+    void onOpenedChanged(final boolean open) {
+        mOpen = open;
+    }
+
+    /** @return The bit field of media types that this chooser can pick */
+    public abstract int getSupportedMediaTypes();
+
+    /** @return The resource id of the icon for the chooser */
+    abstract int getIconResource();
+
+    /** @return The resource id of the string to use for the accessibility text of the icon */
+    abstract int getIconDescriptionResource();
+
+    /**
+     * Sets up the action bar to show the current state of the full-screen chooser
+     * @param actionBar The action bar to populate
+     */
+    void updateActionBar(final ActionBar actionBar) {
+        final int actionBarTitleResId = getActionBarTitleResId();
+        if (actionBarTitleResId == 0) {
+            actionBar.hide();
+        } else {
+            actionBar.setCustomView(null);
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE);
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            actionBar.show();
+            // Use X instead of <- in the action bar
+            actionBar.setHomeAsUpIndicator(R.drawable.ic_remove_small_light);
+            actionBar.setTitle(actionBarTitleResId);
+        }
+    }
+
+    /**
+     * Returns the resource Id used for the action bar title.
+     */
+    abstract int getActionBarTitleResId();
+
+    /**
+     * Throws an exception if the media chooser object doesn't require data support.
+     */
+    public void onDataUpdated(final Object data, final int loaderId) {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Called by the MediaPicker to determine whether this panel can be swiped down further. If
+     * not, then a swipe down gestured will be captured by the MediaPickerPanel to shrink the
+     * entire panel.
+     */
+    public boolean canSwipeDown() {
+        return false;
+    }
+
+    /**
+     * Typically the media picker is closed when the IME is opened, but this allows the chooser to
+     * specify that showing the IME is okay while the chooser is up
+     */
+    public boolean canShowIme() {
+        return false;
+    }
+
+    public boolean onBackPressed() {
+        return false;
+    }
+
+    public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
+    }
+
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        return false;
+    }
+
+    public void setThemeColor(final int color) {
+    }
+
+    /**
+     * Returns true if the chooser is owning any incoming touch events, so that the media picker
+     * panel won't process it and slide the panel.
+     */
+    public boolean isHandlingTouch() {
+        return false;
+    }
+
+    public void stopTouchHandling() {
+    }
+
+    protected void onActivityResult(
+            final int requestCode, final int resultCode, final Intent data) {}
+
+    @Override
+    public int getConversationSelfSubId() {
+        return mMediaPicker.getConversationSelfSubId();
+    }
+
+    /** Optional activity life-cycle methods to be overridden by subclasses */
+    public void onPause() { }
+    public void onResume() { }
+    protected void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) { }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/MediaPicker.java b/src/com/android/messaging/ui/mediapicker/MediaPicker.java
new file mode 100644
index 0000000..c7faa33
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/MediaPicker.java
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import androidx.appcompat.app.ActionBar;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.PendingAttachmentData;
+import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
+import com.android.messaging.ui.BugleActionBarActivity;
+import com.android.messaging.ui.FixedViewPagerAdapter;
+import com.android.messaging.util.AccessibilityUtil;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.UiUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Fragment used to select or capture media to be added to the message
+ */
+public class MediaPicker extends Fragment implements DraftMessageSubscriptionDataProvider {
+    /** The listener interface for events from the media picker */
+    public interface MediaPickerListener {
+        /** Called when the media picker is opened so the host can accommodate the UI */
+        void onOpened();
+
+        /**
+         * Called when the media picker goes into or leaves full screen mode so the host can
+         * accommodate the fullscreen UI
+         */
+        void onFullScreenChanged(boolean fullScreen);
+
+        /**
+         * Called when the user selects one or more items
+         * @param items The list of items which were selected
+         */
+        void onItemsSelected(Collection<MessagePartData> items, boolean dismissMediaPicker);
+
+        /**
+         * Called when the user unselects one item.
+         */
+        void onItemUnselected(MessagePartData item);
+
+        /**
+         * Called when the media picker is closed.  Always called immediately after onItemsSelected
+         */
+        void onDismissed();
+
+        /**
+         * Called when media item selection is confirmed in a multi-select action.
+         */
+        void onConfirmItemSelection();
+
+        /**
+         * Called when a pending attachment is added.
+         * @param pendingItem the pending attachment data being loaded.
+         */
+        void onPendingItemAdded(PendingAttachmentData pendingItem);
+
+        /**
+         * Called when a new media chooser is selected.
+         */
+        void onChooserSelected(final int chooserIndex);
+    }
+
+    /** The tag used when registering and finding this fragment */
+    public static final String FRAGMENT_TAG = "mediapicker";
+
+    // Media type constants that the media picker supports
+    public static final int MEDIA_TYPE_DEFAULT     = 0x0000;
+    public static final int MEDIA_TYPE_NONE        = 0x0000;
+    public static final int MEDIA_TYPE_IMAGE       = 0x0001;
+    public static final int MEDIA_TYPE_VIDEO       = 0x0002;
+    public static final int MEDIA_TYPE_AUDIO       = 0x0004;
+    public static final int MEDIA_TYPE_VCARD       = 0x0008;
+    public static final int MEDIA_TYPE_LOCATION    = 0x0010;
+    private static final int MEDA_TYPE_INVALID     = 0x0020;
+    public static final int MEDIA_TYPE_ALL         = 0xFFFF;
+
+    /** The listener to call when events occur */
+    private MediaPickerListener mListener;
+
+    /** The handler used to dispatch calls to the listener */
+    private Handler mListenerHandler;
+
+    /** The bit flags of media types supported */
+    private int mSupportedMediaTypes;
+
+    /** The list of choosers which could be within the media picker */
+    private final MediaChooser[] mChoosers;
+
+    /** The list of currently enabled choosers */
+    private final ArrayList<MediaChooser> mEnabledChoosers;
+
+    /** The currently selected chooser */
+    private MediaChooser mSelectedChooser;
+
+    /** The main panel that controls the custom layout */
+    private MediaPickerPanel mMediaPickerPanel;
+
+    /** The linear layout that holds the icons to select individual chooser tabs */
+    private LinearLayout mTabStrip;
+
+    /** The view pager to swap between choosers */
+    private ViewPager mViewPager;
+
+    /** The current pager adapter for the view pager */
+    private FixedViewPagerAdapter<MediaChooser> mPagerAdapter;
+
+    /** True if the media picker is visible */
+    private boolean mOpen;
+
+    /** The theme color to use to make the media picker match the rest of the UI */
+    private int mThemeColor;
+
+    @VisibleForTesting
+    final Binding<MediaPickerData> mBinding = BindingBase.createBinding(this);
+
+    /** Provides subscription-related data to access per-subscription configurations. */
+    private DraftMessageSubscriptionDataProvider mSubscriptionDataProvider;
+
+    /** Provides access to DraftMessageData associated with the current conversation */
+    private ImmutableBindingRef<DraftMessageData> mDraftMessageDataModel;
+
+    public MediaPicker() {
+        this(Factory.get().getApplicationContext());
+    }
+
+    public MediaPicker(final Context context) {
+        mBinding.bind(DataModel.get().createMediaPickerData(context));
+        mEnabledChoosers = new ArrayList<MediaChooser>();
+        mChoosers = new MediaChooser[] {
+            new CameraMediaChooser(this),
+            new GalleryMediaChooser(this),
+            new AudioMediaChooser(this),
+            new ContactMediaChooser(this),
+        };
+
+        mOpen = false;
+        setSupportedMediaTypes(MEDIA_TYPE_ALL);
+    }
+
+    private boolean mIsAttached;
+    private int mStartingMediaTypeOnAttach = MEDA_TYPE_INVALID;
+    private boolean mAnimateOnAttach;
+
+    @Override
+    public void onAttach (final Activity activity) {
+        super.onAttach(activity);
+        mIsAttached = true;
+        if (mStartingMediaTypeOnAttach != MEDA_TYPE_INVALID) {
+            // open() was previously called. Do the pending open now.
+            doOpen(mStartingMediaTypeOnAttach, mAnimateOnAttach);
+        }
+    }
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mBinding.getData().init(getLoaderManager());
+    }
+
+    @Override
+    public View onCreateView(
+            final LayoutInflater inflater,
+            final ViewGroup container,
+            final Bundle savedInstanceState) {
+        mMediaPickerPanel = (MediaPickerPanel) inflater.inflate(
+                R.layout.mediapicker_fragment,
+                container,
+                false);
+        mMediaPickerPanel.setMediaPicker(this);
+        mTabStrip = (LinearLayout) mMediaPickerPanel.findViewById(R.id.mediapicker_tabstrip);
+        mTabStrip.setBackgroundColor(mThemeColor);
+        for (final MediaChooser chooser : mChoosers) {
+            chooser.onCreateTabButton(inflater, mTabStrip);
+            final boolean enabled = (chooser.getSupportedMediaTypes() & mSupportedMediaTypes) !=
+                    MEDIA_TYPE_NONE;
+            final ImageButton tabButton = chooser.getTabButton();
+            if (tabButton != null) {
+                tabButton.setVisibility(enabled ? View.VISIBLE : View.GONE);
+                mTabStrip.addView(tabButton);
+            }
+        }
+
+        mViewPager = (ViewPager) mMediaPickerPanel.findViewById(R.id.mediapicker_view_pager);
+        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+            @Override
+            public void onPageScrolled(
+                    final int position,
+                    final float positionOffset,
+                    final int positionOffsetPixels) {
+            }
+
+            @Override
+            public void onPageSelected(int position) {
+                // The position returned is relative to if we are in RtL mode. This class never
+                // switches the indices of the elements if we are in RtL mode so we need to
+                // translate the index back. For example, if the user clicked the item most to the
+                // right in RtL mode we would want the index to appear as 0 here, however the
+                // position returned would the last possible index.
+                if (UiUtils.isRtlMode()) {
+                    position = mEnabledChoosers.size() - 1 - position;
+                }
+                selectChooser(mEnabledChoosers.get(position));
+            }
+
+            @Override
+            public void onPageScrollStateChanged(final int state) {
+            }
+        });
+        // Camera initialization is expensive, so don't realize offscreen pages if not needed.
+        mViewPager.setOffscreenPageLimit(0);
+        mViewPager.setAdapter(mPagerAdapter);
+        final boolean isTouchExplorationEnabled = AccessibilityUtil.isTouchExplorationEnabled(
+                getActivity());
+        mMediaPickerPanel.setFullScreenOnly(isTouchExplorationEnabled);
+        mMediaPickerPanel.setExpanded(mOpen, true, mEnabledChoosers.indexOf(mSelectedChooser));
+        return mMediaPickerPanel;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        CameraManager.get().onPause();
+        for (final MediaChooser chooser : mEnabledChoosers) {
+            chooser.onPause();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        CameraManager.get().onResume();
+
+        for (final MediaChooser chooser : mEnabledChoosers) {
+            chooser.onResume();
+        }
+    }
+
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        mSelectedChooser.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mBinding.unbind();
+    }
+
+    /**
+     * Sets the theme color to make the media picker match the surrounding UI
+     * @param themeColor The new theme color
+     */
+    public void setConversationThemeColor(final int themeColor) {
+        mThemeColor = themeColor;
+        if (mTabStrip != null) {
+            mTabStrip.setBackgroundColor(mThemeColor);
+        }
+
+        for (final MediaChooser chooser : mEnabledChoosers) {
+            chooser.setThemeColor(mThemeColor);
+        }
+    }
+
+    /**
+     * Gets the current conversation theme color.
+     */
+    public int getConversationThemeColor() {
+        return mThemeColor;
+    }
+
+    public void setDraftMessageDataModel(final BindingBase<DraftMessageData> draftBinding) {
+        mDraftMessageDataModel = Binding.createBindingReference(draftBinding);
+    }
+
+    public ImmutableBindingRef<DraftMessageData> getDraftMessageDataModel() {
+        return mDraftMessageDataModel;
+    }
+
+    public void setSubscriptionDataProvider(final DraftMessageSubscriptionDataProvider provider) {
+        mSubscriptionDataProvider = provider;
+    }
+
+    @Override
+    public int getConversationSelfSubId() {
+        return mSubscriptionDataProvider.getConversationSelfSubId();
+    }
+
+    /**
+     * Opens the media picker and optionally shows the chooser for the supplied media type
+     * @param startingMediaType The media type of the chooser to open if {@link #MEDIA_TYPE_DEFAULT}
+     *                          is used, then the default chooser from saved shared prefs is opened
+     */
+    public void open(final int startingMediaType, final boolean animate) {
+        mOpen = true;
+        if (mIsAttached) {
+            doOpen(startingMediaType, animate);
+        } else {
+            // open() can get called immediately after the MediaPicker is created. In that case,
+            // we defer doing work as it may require an attached fragment (eg. calling
+            // Fragment#requestPermission)
+            mStartingMediaTypeOnAttach = startingMediaType;
+            mAnimateOnAttach = animate;
+        }
+    }
+
+    private void doOpen(int startingMediaType, final boolean animate) {
+        final boolean isTouchExplorationEnabled = AccessibilityUtil.isTouchExplorationEnabled(
+                // getActivity() will be null at this point
+                Factory.get().getApplicationContext());
+
+        // If no specific starting type is specified (i.e. MEDIA_TYPE_DEFAULT), try to get the
+        // last opened chooser index from shared prefs.
+        if (startingMediaType == MEDIA_TYPE_DEFAULT) {
+            final int selectedChooserIndex = mBinding.getData().getSelectedChooserIndex();
+            if (selectedChooserIndex >= 0 && selectedChooserIndex < mEnabledChoosers.size()) {
+                selectChooser(mEnabledChoosers.get(selectedChooserIndex));
+            } else {
+                // This is the first time the picker is being used
+                if (isTouchExplorationEnabled) {
+                    // Accessibility defaults to audio attachment mode.
+                    startingMediaType = MEDIA_TYPE_AUDIO;
+                }
+            }
+        }
+
+        if (mSelectedChooser == null) {
+            for (final MediaChooser chooser : mEnabledChoosers) {
+                if (startingMediaType == MEDIA_TYPE_DEFAULT ||
+                        (startingMediaType & chooser.getSupportedMediaTypes()) != MEDIA_TYPE_NONE) {
+                    selectChooser(chooser);
+                    break;
+                }
+            }
+        }
+
+        if (mSelectedChooser == null) {
+            // Fall back to the first chooser.
+            selectChooser(mEnabledChoosers.get(0));
+        }
+
+        if (mMediaPickerPanel != null) {
+            mMediaPickerPanel.setFullScreenOnly(isTouchExplorationEnabled);
+            mMediaPickerPanel.setExpanded(true, animate,
+                    mEnabledChoosers.indexOf(mSelectedChooser));
+        }
+    }
+
+    /** @return True if the media picker is open */
+    public boolean isOpen() {
+        return mOpen;
+    }
+
+    /**
+     * Sets the list of media types to allow the user to select
+     * @param mediaTypes The bit flags of media types to allow.  Can be any combination of the
+     *                   MEDIA_TYPE_* values
+     */
+    void setSupportedMediaTypes(final int mediaTypes) {
+        mSupportedMediaTypes = mediaTypes;
+        mEnabledChoosers.clear();
+        boolean selectNextChooser = false;
+        for (final MediaChooser chooser : mChoosers) {
+            final boolean enabled = (chooser.getSupportedMediaTypes() & mSupportedMediaTypes) !=
+                    MEDIA_TYPE_NONE;
+            if (enabled) {
+                // TODO Add a way to inform the chooser which media types are supported
+                mEnabledChoosers.add(chooser);
+                if (selectNextChooser) {
+                    selectChooser(chooser);
+                    selectNextChooser = false;
+                }
+            } else if (mSelectedChooser == chooser) {
+                selectNextChooser = true;
+            }
+            final ImageButton tabButton = chooser.getTabButton();
+            if (tabButton != null) {
+                tabButton.setVisibility(enabled ? View.VISIBLE : View.GONE);
+            }
+        }
+
+        if (selectNextChooser && mEnabledChoosers.size() > 0) {
+            selectChooser(mEnabledChoosers.get(0));
+        }
+        final MediaChooser[] enabledChoosers = new MediaChooser[mEnabledChoosers.size()];
+        mEnabledChoosers.toArray(enabledChoosers);
+        mPagerAdapter = new FixedViewPagerAdapter<MediaChooser>(enabledChoosers);
+        if (mViewPager != null) {
+            mViewPager.setAdapter(mPagerAdapter);
+        }
+
+        // Only rebind data if we are currently bound. Otherwise, we must have not
+        // bound to any data yet and should wait until onCreate() to bind data.
+        if (mBinding.isBound() && getActivity() != null) {
+            mBinding.unbind();
+            mBinding.bind(DataModel.get().createMediaPickerData(getActivity()));
+            mBinding.getData().init(getLoaderManager());
+        }
+    }
+
+    ViewPager getViewPager() {
+        return mViewPager;
+    }
+
+    /** Hides the media picker, and frees up any resources it’s using */
+    public void dismiss(final boolean animate) {
+        mOpen = false;
+        if (mMediaPickerPanel != null) {
+            mMediaPickerPanel.setExpanded(false, animate, MediaPickerPanel.PAGE_NOT_SET);
+        }
+        mSelectedChooser = null;
+    }
+
+    /**
+     * Sets the listener for the media picker events
+     * @param listener The listener which will receive events
+     */
+    public void setListener(final MediaPickerListener listener) {
+        Assert.isMainThread();
+        mListener = listener;
+        mListenerHandler = listener != null ? new Handler() : null;
+    }
+
+    /** @return True if the media picker is in full-screen mode */
+    public boolean isFullScreen() {
+        return mMediaPickerPanel != null && mMediaPickerPanel.isFullScreen();
+    }
+
+    public void setFullScreen(final boolean fullScreen) {
+        mMediaPickerPanel.setFullScreenView(fullScreen, true);
+    }
+
+    public void updateActionBar(final ActionBar actionBar) {
+        if (getActivity() == null) {
+            return;
+        }
+        if (isFullScreen() && mSelectedChooser != null) {
+            mSelectedChooser.updateActionBar(actionBar);
+        } else {
+            actionBar.hide();
+        }
+    }
+
+    /**
+     * Selects a new chooser
+     * @param newSelectedChooser The newly selected chooser
+     */
+    void selectChooser(final MediaChooser newSelectedChooser) {
+        if (mSelectedChooser == newSelectedChooser) {
+            return;
+        }
+
+        if (mSelectedChooser != null) {
+            mSelectedChooser.setSelected(false);
+        }
+        mSelectedChooser = newSelectedChooser;
+        if (mSelectedChooser != null) {
+            mSelectedChooser.setSelected(true);
+        }
+
+        final int chooserIndex = mEnabledChoosers.indexOf(mSelectedChooser);
+        if (mViewPager != null) {
+            mViewPager.setCurrentItem(chooserIndex, true /* smoothScroll */);
+        }
+
+        if (isFullScreen()) {
+            invalidateOptionsMenu();
+        }
+
+        // Save the newly selected chooser's index so we may directly switch to it the
+        // next time user opens the media picker.
+        mBinding.getData().saveSelectedChooserIndex(chooserIndex);
+        if (mMediaPickerPanel != null) {
+            mMediaPickerPanel.onChooserChanged();
+        }
+        dispatchChooserSelected(chooserIndex);
+    }
+
+    public boolean canShowIme() {
+        if (mSelectedChooser != null) {
+            return mSelectedChooser.canShowIme();
+        }
+        return false;
+    }
+
+    public boolean onBackPressed() {
+        return mSelectedChooser != null && mSelectedChooser.onBackPressed();
+    }
+
+    void invalidateOptionsMenu() {
+        ((BugleActionBarActivity) getActivity()).supportInvalidateOptionsMenu();
+    }
+
+    void dispatchOpened() {
+        setHasOptionsMenu(false);
+        mOpen = true;
+        mPagerAdapter.notifyDataSetChanged();
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onOpened();
+                }
+            });
+        }
+        if (mSelectedChooser != null) {
+            mSelectedChooser.onFullScreenChanged(false);
+            mSelectedChooser.onOpenedChanged(true);
+        }
+    }
+
+    void dispatchDismissed() {
+        setHasOptionsMenu(false);
+        mOpen = false;
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onDismissed();
+                }
+            });
+        }
+        if (mSelectedChooser != null) {
+            mSelectedChooser.onOpenedChanged(false);
+        }
+    }
+
+    void dispatchFullScreen(final boolean fullScreen) {
+        setHasOptionsMenu(fullScreen);
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onFullScreenChanged(fullScreen);
+                }
+            });
+        }
+        if (mSelectedChooser != null) {
+            mSelectedChooser.onFullScreenChanged(fullScreen);
+        }
+    }
+
+    void dispatchItemsSelected(final MessagePartData item, final boolean dismissMediaPicker) {
+        final List<MessagePartData> items = new ArrayList<MessagePartData>(1);
+        items.add(item);
+        dispatchItemsSelected(items, dismissMediaPicker);
+    }
+
+    void dispatchItemsSelected(final Collection<MessagePartData> items,
+            final boolean dismissMediaPicker) {
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onItemsSelected(items, dismissMediaPicker);
+                }
+            });
+        }
+
+        if (isFullScreen() && !dismissMediaPicker) {
+            invalidateOptionsMenu();
+        }
+    }
+
+    void dispatchItemUnselected(final MessagePartData item) {
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onItemUnselected(item);
+                }
+            });
+        }
+
+        if (isFullScreen()) {
+            invalidateOptionsMenu();
+        }
+    }
+
+    void dispatchConfirmItemSelection() {
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onConfirmItemSelection();
+                }
+            });
+        }
+    }
+
+    void dispatchPendingItemAdded(final PendingAttachmentData pendingItem) {
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onPendingItemAdded(pendingItem);
+                }
+            });
+        }
+
+        if (isFullScreen()) {
+            invalidateOptionsMenu();
+        }
+    }
+
+    void dispatchChooserSelected(final int chooserIndex) {
+        if (mListener != null) {
+            mListenerHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onChooserSelected(chooserIndex);
+                }
+            });
+        }
+    }
+
+    public boolean canSwipeDownChooser() {
+        return mSelectedChooser == null ? false : mSelectedChooser.canSwipeDown();
+    }
+
+    public boolean isChooserHandlingTouch() {
+        return mSelectedChooser == null ? false : mSelectedChooser.isHandlingTouch();
+    }
+
+    public void stopChooserTouchHandling() {
+        if (mSelectedChooser != null) {
+            mSelectedChooser.stopTouchHandling();
+        }
+    }
+
+    boolean getChooserShowsActionBarInFullScreen() {
+        return mSelectedChooser == null ? false : mSelectedChooser.getActionBarTitleResId() != 0;
+    }
+
+    @Override
+    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+        if (mSelectedChooser != null) {
+            mSelectedChooser.onCreateOptionsMenu(inflater, menu);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        return (mSelectedChooser != null && mSelectedChooser.onOptionsItemSelected(item)) ||
+                super.onOptionsItemSelected(item);
+    }
+
+    PagerAdapter getPagerAdapter() {
+        return mPagerAdapter;
+    }
+
+    public void resetViewHolderState() {
+        mPagerAdapter.resetState();
+    }
+
+    public ImmutableBindingRef<MediaPickerData> getMediaPickerDataBinding() {
+        return BindingBase.createBindingReference(mBinding);
+    }
+
+    protected static final int CAMERA_PERMISSION_REQUEST_CODE = 1;
+    protected static final int LOCATION_PERMISSION_REQUEST_CODE = 2;
+    protected static final int RECORD_AUDIO_PERMISSION_REQUEST_CODE = 3;
+    protected static final int GALLERY_PERMISSION_REQUEST_CODE = 4;
+    protected static final int READ_CONTACT_PERMISSION_REQUEST_CODE = 5;
+
+    @Override
+    public void onRequestPermissionsResult(
+            final int requestCode, final String permissions[], final int[] grantResults) {
+        if (mSelectedChooser != null) {
+            mSelectedChooser.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/MediaPickerGridView.java b/src/com/android/messaging/ui/mediapicker/MediaPickerGridView.java
new file mode 100644
index 0000000..cc3a4a1
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/MediaPickerGridView.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridView;
+
+public class MediaPickerGridView extends GridView {
+
+    public MediaPickerGridView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Returns if the grid view can be swiped down further. It cannot be swiped down
+     * if there's no item or if we are already at the top.
+     */
+    public boolean canSwipeDown() {
+        if (getAdapter() == null || getAdapter().getCount() == 0 || getChildCount() == 0) {
+            return false;
+        }
+
+        final int firstVisiblePosition = getFirstVisiblePosition();
+        if (firstVisiblePosition == 0 && getChildAt(0).getTop() >= 0) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/MediaPickerPanel.java b/src/com/android/messaging/ui/mediapicker/MediaPickerPanel.java
new file mode 100644
index 0000000..56b0a03
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/MediaPickerPanel.java
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.widget.LinearLayout;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.PagingAwareViewPager;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.UiUtils;
+
+/**
+ * Custom layout panel which makes the MediaPicker animations seamless and synchronized
+ * Designed to be very specific to the MediaPicker's usage
+ */
+public class MediaPickerPanel extends ViewGroup {
+    /**
+     * The window of time in which we might to decide to reinterpret the intent of a gesture.
+     */
+    private static final long TOUCH_RECAPTURE_WINDOW_MS = 500L;
+
+    // The two view components to layout
+    private LinearLayout mTabStrip;
+    private boolean mFullScreenOnly;
+    private PagingAwareViewPager mViewPager;
+
+    /**
+     * True if the MediaPicker is full screen or animating into it
+     */
+    private boolean mFullScreen;
+
+    /**
+     * True if the MediaPicker is open at all
+     */
+    private boolean mExpanded;
+
+    /**
+     * The current desired height of the MediaPicker.  This property may be animated and the
+     * measure pass uses it to determine what size the components are.
+     */
+    private int mCurrentDesiredHeight;
+
+    private final Handler mHandler = new Handler();
+
+    /**
+     * The media picker for dispatching events to the MediaPicker's listener
+     */
+    private MediaPicker mMediaPicker;
+
+    /**
+     * The computed default "half-screen" height of the view pager in px
+     */
+    private final int mDefaultViewPagerHeight;
+
+    /**
+     * The action bar height used to compute the padding on the view pager when it's full screen.
+     */
+    private final int mActionBarHeight;
+
+    private TouchHandler mTouchHandler;
+
+    static final int PAGE_NOT_SET = -1;
+
+    public MediaPickerPanel(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        // Cache the computed dimension
+        mDefaultViewPagerHeight = getResources().getDimensionPixelSize(
+                R.dimen.mediapicker_default_chooser_height);
+        mActionBarHeight = getResources().getDimensionPixelSize(R.dimen.action_bar_height);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTabStrip = (LinearLayout) findViewById(R.id.mediapicker_tabstrip);
+        mViewPager = (PagingAwareViewPager) findViewById(R.id.mediapicker_view_pager);
+        mTouchHandler = new TouchHandler();
+        setOnTouchListener(mTouchHandler);
+        mViewPager.setOnTouchListener(mTouchHandler);
+
+        // Make sure full screen mode is updated in landscape mode change when the panel is open.
+        addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            private boolean mLandscapeMode = UiUtils.isLandscapeMode();
+
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                final boolean newLandscapeMode = UiUtils.isLandscapeMode();
+                if (mLandscapeMode != newLandscapeMode) {
+                    mLandscapeMode = newLandscapeMode;
+                    if (mExpanded) {
+                        setExpanded(mExpanded, false /* animate */, mViewPager.getCurrentItem(),
+                                true /* force */);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+        if (mMediaPicker.getChooserShowsActionBarInFullScreen()) {
+            requestedHeight -= mActionBarHeight;
+        }
+        int desiredHeight = Math.min(mCurrentDesiredHeight, requestedHeight);
+        if (mExpanded && desiredHeight == 0) {
+            // If we want to be shown, we have to have a non-0 height.  Returning a height of 0 will
+            // cause the framework to abort the animation from 0, so we must always have some
+            // height once we start expanding
+            desiredHeight = 1;
+        } else if (!mExpanded && desiredHeight == 0) {
+            mViewPager.setVisibility(View.GONE);
+            mViewPager.setAdapter(null);
+        }
+
+        measureChild(mTabStrip, widthMeasureSpec, heightMeasureSpec);
+
+        int tabStripHeight;
+        if (requiresFullScreen()) {
+            // Ensure that the tab strip is always visible, even in full screen.
+            tabStripHeight = mTabStrip.getMeasuredHeight();
+        } else {
+            // Slide out the tab strip at the end of the animation to full screen.
+            tabStripHeight = Math.min(mTabStrip.getMeasuredHeight(),
+                    requestedHeight - desiredHeight);
+        }
+
+        // If we are animating and have an interim desired height, use the default height. We can't
+        // take the max here as on some devices the mDefaultViewPagerHeight may be too big in
+        // landscape mode after animation.
+        final int tabAdjustedDesiredHeight = desiredHeight - tabStripHeight;
+        final int viewPagerHeight =
+                tabAdjustedDesiredHeight <= 1 ? mDefaultViewPagerHeight : tabAdjustedDesiredHeight;
+
+        int viewPagerHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                viewPagerHeight, MeasureSpec.EXACTLY);
+        measureChild(mViewPager, widthMeasureSpec, viewPagerHeightMeasureSpec);
+        setMeasuredDimension(mViewPager.getMeasuredWidth(), desiredHeight);
+    }
+
+    @Override
+    protected void onLayout(final boolean changed, final int left, final int top, final int right,
+            final int bottom) {
+        int y = top;
+        final int width = right - left;
+
+        final int viewPagerHeight = mViewPager.getMeasuredHeight();
+        mViewPager.layout(0, y, width, y + viewPagerHeight);
+        y += viewPagerHeight;
+
+        mTabStrip.layout(0, y, width, y + mTabStrip.getMeasuredHeight());
+    }
+
+    void onChooserChanged() {
+        if (mFullScreen) {
+            setDesiredHeight(getDesiredHeight(), true);
+        }
+    }
+
+    void setFullScreenOnly(boolean fullScreenOnly) {
+        mFullScreenOnly = fullScreenOnly;
+    }
+
+    boolean isFullScreen() {
+        return mFullScreen;
+    }
+
+    void setMediaPicker(final MediaPicker mediaPicker) {
+        mMediaPicker = mediaPicker;
+    }
+
+    /**
+     * Get the desired height of the media picker panel for when the panel is not in motion (i.e.
+     * not being dragged by the user).
+     */
+    private int getDesiredHeight() {
+        if (mFullScreen) {
+            int fullHeight = getContext().getResources().getDisplayMetrics().heightPixels;
+            if (OsUtil.isAtLeastKLP() && isAttachedToWindow()) {
+                // When we're attached to the window, we can get an accurate height, not necessary
+                // on older API level devices because they don't include the action bar height
+                View composeContainer =
+                        getRootView().findViewById(R.id.conversation_and_compose_container);
+                if (composeContainer != null) {
+                    // protect against composeContainer having been unloaded already
+                    fullHeight -= UiUtils.getMeasuredBoundsOnScreen(composeContainer).top;
+                }
+            }
+            if (mMediaPicker.getChooserShowsActionBarInFullScreen()) {
+                return fullHeight - mActionBarHeight;
+            } else {
+                return fullHeight;
+            }
+        } else if (mExpanded) {
+            return LayoutParams.WRAP_CONTENT;
+        } else {
+            return 0;
+        }
+    }
+
+    private void setupViewPager(final int startingPage) {
+        mViewPager.setVisibility(View.VISIBLE);
+        if (startingPage >= 0 && startingPage < mMediaPicker.getPagerAdapter().getCount()) {
+            mViewPager.setAdapter(mMediaPicker.getPagerAdapter());
+            mViewPager.setCurrentItem(startingPage);
+        }
+        updateViewPager();
+    }
+
+    /**
+     * Expand the media picker panel. Since we always set the pager adapter to null when the panel
+     * is collapsed, we need to restore the adapter and the starting page.
+     * @param expanded expanded or collapsed
+     * @param animate need animation
+     * @param startingPage the desired selected page to start
+     */
+    void setExpanded(final boolean expanded, final boolean animate, final int startingPage) {
+        setExpanded(expanded, animate, startingPage, false /* force */);
+    }
+
+    private void setExpanded(final boolean expanded, final boolean animate, final int startingPage,
+            final boolean force) {
+        if (expanded == mExpanded && !force) {
+            return;
+        }
+        mFullScreen = false;
+        mExpanded = expanded;
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                setDesiredHeight(getDesiredHeight(), animate);
+            }
+        });
+        if (expanded) {
+            setupViewPager(startingPage);
+            mMediaPicker.dispatchOpened();
+        } else {
+            mMediaPicker.dispatchDismissed();
+        }
+
+        // Call setFullScreenView() when we are in landscape mode so it can go full screen as
+        // soon as it is expanded.
+        if (expanded && requiresFullScreen()) {
+            setFullScreenView(true, animate);
+        }
+    }
+
+    private boolean requiresFullScreen() {
+        return mFullScreenOnly || UiUtils.isLandscapeMode();
+    }
+
+    private void setDesiredHeight(int height, final boolean animate) {
+        final int startHeight = mCurrentDesiredHeight;
+        if (height == LayoutParams.WRAP_CONTENT) {
+            height = measureHeight();
+        }
+        clearAnimation();
+        if (animate) {
+            final int deltaHeight = height - startHeight;
+            final Animation animation = new Animation() {
+                @Override
+                protected void applyTransformation(final float interpolatedTime,
+                        final Transformation t) {
+                    mCurrentDesiredHeight = (int) (startHeight + deltaHeight * interpolatedTime);
+                    requestLayout();
+                }
+
+                @Override
+                public boolean willChangeBounds() {
+                    return true;
+                }
+            };
+            animation.setDuration(UiUtils.MEDIAPICKER_TRANSITION_DURATION);
+            animation.setInterpolator(UiUtils.EASE_OUT_INTERPOLATOR);
+            startAnimation(animation);
+        } else {
+            mCurrentDesiredHeight = height;
+        }
+        requestLayout();
+    }
+
+    /**
+     * @return The minimum total height of the view
+     */
+    private int measureHeight() {
+        final int measureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST);
+        measureChild(mTabStrip, measureSpec, measureSpec);
+        return mDefaultViewPagerHeight + mTabStrip.getMeasuredHeight();
+    }
+
+    /**
+     * Enters or leaves full screen view
+     *
+     * @param fullScreen True to enter full screen view, false to leave
+     * @param animate    True to animate the transition
+     */
+    void setFullScreenView(final boolean fullScreen, final boolean animate) {
+        if (fullScreen == mFullScreen) {
+            return;
+        }
+
+        if (requiresFullScreen() && !fullScreen) {
+            setExpanded(false /* expanded */, true /* animate */, PAGE_NOT_SET);
+            return;
+        }
+        mFullScreen = fullScreen;
+        setDesiredHeight(getDesiredHeight(), animate);
+        mMediaPicker.dispatchFullScreen(mFullScreen);
+        updateViewPager();
+    }
+
+    /**
+     * ViewPager should have its paging disabled when in full screen mode.
+     */
+    private void updateViewPager() {
+        mViewPager.setPagingEnabled(!mFullScreen);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(final MotionEvent ev) {
+        return mTouchHandler.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
+    }
+
+    /**
+     * Helper class to handle touch events and swipe gestures
+     */
+    private class TouchHandler implements OnTouchListener {
+        /**
+         * The height of the view when the touch press started
+         */
+        private int mDownHeight = -1;
+
+        /**
+         * True if the panel moved at all (changed height) during the drag
+         */
+        private boolean mMoved = false;
+
+        // The threshold constants converted from DP to px
+        private final float mFlingThresholdPx;
+        private final float mBigFlingThresholdPx;
+
+        // The system defined pixel size to determine when a movement is considered a drag.
+        private final int mTouchSlop;
+
+        /**
+         * A copy of the MotionEvent that started the drag/swipe gesture
+         */
+        private MotionEvent mDownEvent;
+
+        /**
+         * Whether we are currently moving down. We may not be able to move down in full screen
+         * mode when the child view can swipe down (such as a list view).
+         */
+        private boolean mMovedDown = false;
+
+        /**
+         * Indicates whether the child view contained in the panel can swipe down at the beginning
+         * of the drag event (i.e. the initial down). The MediaPanel can contain
+         * scrollable children such as a list view / grid view. If the child view can swipe down,
+         * We want to let the child view handle the scroll first instead of handling it ourselves.
+         */
+        private boolean mCanChildViewSwipeDown = false;
+
+        /**
+         * Necessary direction ratio for a fling to be considered in one direction this prevents
+         * horizontal swipes with small vertical components from triggering vertical swipe actions
+         */
+        private static final float DIRECTION_RATIO = 1.1f;
+
+        TouchHandler() {
+            final Resources resources = getContext().getResources();
+            final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+            mFlingThresholdPx = resources.getDimensionPixelSize(
+                    R.dimen.mediapicker_fling_threshold);
+            mBigFlingThresholdPx = resources.getDimensionPixelSize(
+                    R.dimen.mediapicker_big_fling_threshold);
+            mTouchSlop = configuration.getScaledTouchSlop();
+        }
+
+        /**
+         * The media picker panel may contain scrollable children such as a GridView, which eats
+         * all touch events before we get to it. Therefore, we'd like to intercept these events
+         * before the children to determine if we should handle swiping down in full screen mode.
+         * In non-full screen mode, we should handle all vertical scrolling events and leave
+         * horizontal scrolling to the view pager.
+         */
+        public boolean onInterceptTouchEvent(final MotionEvent ev) {
+            switch (ev.getActionMasked()) {
+                case MotionEvent.ACTION_DOWN:
+                    // Never capture the initial down, so that the children may handle it
+                    // as well. Let the touch handler know about the down event as well.
+                    mTouchHandler.onTouch(MediaPickerPanel.this, ev);
+
+                    // Ask the MediaPicker whether the contained view can be swiped down.
+                    // We record the value at the start of the drag to decide the swiping mode
+                    // for the entire motion.
+                    mCanChildViewSwipeDown = mMediaPicker.canSwipeDownChooser();
+                    return false;
+
+                case MotionEvent.ACTION_MOVE: {
+                    if (mMediaPicker.isChooserHandlingTouch()) {
+                        if (shouldAllowRecaptureTouch(ev)) {
+                            mMediaPicker.stopChooserTouchHandling();
+                            mViewPager.setPagingEnabled(true);
+                            return false;
+                        }
+                        // If the chooser is claiming ownership on all touch events, then we
+                        // shouldn't try to handle them (neither should the view pager).
+                        mViewPager.setPagingEnabled(false);
+                        return false;
+                    } else if (mCanChildViewSwipeDown) {
+                        // Never capture event if the child view can swipe down.
+                        return false;
+                    } else if (!mFullScreen && mMoved) {
+                        // When we are not fullscreen, we own any vertical drag motion.
+                        return true;
+                    } else if (mMovedDown) {
+                        // We are currently handling the down swipe ourselves, so always
+                        // capture this event.
+                        return true;
+                    } else {
+                        // The current interaction mode is undetermined, so always let the
+                        // touch handler know about this event. However, don't capture this
+                        // event so the child may handle it as well.
+                        mTouchHandler.onTouch(MediaPickerPanel.this, ev);
+
+                        // Capture the touch event from now on if we are handling the drag.
+                        return mFullScreen ? mMovedDown : mMoved;
+                    }
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Determine whether we think the user is actually trying to expand or slide despite the
+         * fact that they touched first on a chooser that captured the input.
+         */
+        private boolean shouldAllowRecaptureTouch(MotionEvent ev) {
+            final long elapsedMs = ev.getEventTime() - ev.getDownTime();
+            if (mDownEvent == null || elapsedMs == 0 || elapsedMs > TOUCH_RECAPTURE_WINDOW_MS) {
+                // Either we don't have info to decide or it's been long enough that we no longer
+                // want to reinterpret user intent.
+                return false;
+            }
+            final float dx = ev.getRawX() - mDownEvent.getRawX();
+            final float dy = ev.getRawY() - mDownEvent.getRawY();
+            final float dt = elapsedMs / 1000.0f;
+            final float maxAbsDelta = Math.max(Math.abs(dx), Math.abs(dy));
+            final float velocity = maxAbsDelta / dt;
+            return velocity > mFlingThresholdPx;
+        }
+
+        @Override
+        public boolean onTouch(final View view, final MotionEvent motionEvent) {
+            switch (motionEvent.getAction()) {
+                case MotionEvent.ACTION_UP: {
+                    if (!mMoved || mDownEvent == null) {
+                        return false;
+                    }
+                    final float dx = motionEvent.getRawX() - mDownEvent.getRawX();
+                    final float dy = motionEvent.getRawY() - mDownEvent.getRawY();
+
+                    final float dt =
+                            (motionEvent.getEventTime() - mDownEvent.getEventTime()) / 1000.0f;
+                    final float yVelocity = dy / dt;
+
+                    boolean handled = false;
+
+                    // Vertical swipe occurred if the direction is as least mostly in the y
+                    // component and has the required velocity (px/sec)
+                    if ((dx == 0 || (Math.abs(dy) / Math.abs(dx)) > DIRECTION_RATIO) &&
+                            Math.abs(yVelocity) > mFlingThresholdPx) {
+                        if (yVelocity < 0 && mExpanded) {
+                            setFullScreenView(true, true);
+                            handled = true;
+                        } else if (yVelocity > 0) {
+                            if (mFullScreen && yVelocity < mBigFlingThresholdPx) {
+                                setFullScreenView(false, true);
+                            } else {
+                                setExpanded(false, true, PAGE_NOT_SET);
+                            }
+                            handled = true;
+                        }
+                    }
+
+                    if (!handled) {
+                        // If they didn't swipe enough, animate back to resting state
+                        setDesiredHeight(getDesiredHeight(), true);
+                    }
+                    resetState();
+                    break;
+                }
+                case MotionEvent.ACTION_DOWN: {
+                    mDownHeight = getHeight();
+                    mDownEvent = MotionEvent.obtain(motionEvent);
+                    // If we are here and care about the return value (i.e. this is not called
+                    // from onInterceptTouchEvent), then presumably no children view in the panel
+                    // handles the down event. We'd like to handle future ACTION_MOVE events, so
+                    // always claim ownership on this event so it doesn't fall through and gets
+                    // cancelled by the framework.
+                    return true;
+                }
+                case MotionEvent.ACTION_MOVE: {
+                    if (mDownEvent == null) {
+                        return mMoved;
+                    }
+
+                    final float dx = mDownEvent.getRawX() - motionEvent.getRawX();
+                    final float dy = mDownEvent.getRawY() - motionEvent.getRawY();
+                    // Don't act if the move is mostly horizontal
+                    if (Math.abs(dy) > mTouchSlop &&
+                            (Math.abs(dy) / Math.abs(dx)) > DIRECTION_RATIO) {
+                        setDesiredHeight((int) (mDownHeight + dy), false);
+                        mMoved = true;
+                        if (dy < -mTouchSlop) {
+                            mMovedDown = true;
+                        }
+                    }
+                    return mMoved;
+                }
+
+            }
+            return mMoved;
+        }
+
+        private void resetState() {
+            mDownEvent = null;
+            mDownHeight = -1;
+            mMoved = false;
+            mMovedDown = false;
+            mCanChildViewSwipeDown = false;
+            updateViewPager();
+        }
+    }
+}
+
diff --git a/src/com/android/messaging/ui/mediapicker/MmsVideoRecorder.java b/src/com/android/messaging/ui/mediapicker/MmsVideoRecorder.java
new file mode 100644
index 0000000..89241b7
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/MmsVideoRecorder.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.hardware.Camera;
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.SafeAsyncTask;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+class MmsVideoRecorder extends MediaRecorder {
+    private static final float VIDEO_OVERSHOOT_SLOP = .85F;
+
+    private static final int BITS_PER_BYTE = 8;
+
+    // We think user will expect to be able to record videos at least this long
+    private static final long MIN_DURATION_LIMIT_SECONDS = 25;
+
+    /** The uri where video is being recorded to */
+    private Uri mTempVideoUri;
+
+    private ParcelFileDescriptor mVideoFD;
+
+    /** The settings used for video recording */
+    private final CamcorderProfile mCamcorderProfile;
+
+    public MmsVideoRecorder(final Camera camera, final int cameraIndex, final int orientation,
+            final int maxMessageSize)
+            throws FileNotFoundException {
+        mCamcorderProfile =
+                CamcorderProfile.get(cameraIndex, CamcorderProfile.QUALITY_LOW);
+        mTempVideoUri = MediaScratchFileProvider.buildMediaScratchSpaceUri(
+                ContentType.getExtension(getContentType()));
+
+        // The video recorder can sometimes return a file that's larger than the max we
+        // say we can handle. Try to handle that overshoot by specifying an 85% limit.
+        final long sizeLimit = (long) (maxMessageSize * VIDEO_OVERSHOOT_SLOP);
+
+        // The QUALITY_LOW profile might not be low enough to allow for video of a reasonable
+        // minimum duration.  Adjust a/v bitrates to allow at least MIN_DURATION_LIMIT video
+        // to be recorded.
+        int audioBitRate = mCamcorderProfile.audioBitRate;
+        int videoBitRate = mCamcorderProfile.videoBitRate;
+        final double initialDurationLimit = sizeLimit * BITS_PER_BYTE
+                / (double) (audioBitRate + videoBitRate);
+        if (initialDurationLimit < MIN_DURATION_LIMIT_SECONDS) {
+            // Reduce the suggested bitrates.  These bitrates are only requests, if implementation
+            // can't actually hit these goals it will still record video at higher rate and stop when
+            // it hits the size limit.
+            final double bitRateAdjustmentFactor = initialDurationLimit / MIN_DURATION_LIMIT_SECONDS;
+            audioBitRate *= bitRateAdjustmentFactor;
+            videoBitRate *= bitRateAdjustmentFactor;
+        }
+
+        setCamera(camera);
+        setOrientationHint(orientation);
+        setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+        setVideoSource(MediaRecorder.VideoSource.CAMERA);
+        setOutputFormat(mCamcorderProfile.fileFormat);
+        mVideoFD = Factory.get().getApplicationContext().getContentResolver()
+                .openFileDescriptor(mTempVideoUri, "w");
+        setOutputFile(mVideoFD.getFileDescriptor());
+
+        // Copy settings from CamcorderProfile to MediaRecorder
+        setAudioEncodingBitRate(audioBitRate);
+        setAudioChannels(mCamcorderProfile.audioChannels);
+        setAudioEncoder(mCamcorderProfile.audioCodec);
+        setAudioSamplingRate(mCamcorderProfile.audioSampleRate);
+        setVideoEncodingBitRate(videoBitRate);
+        setVideoEncoder(mCamcorderProfile.videoCodec);
+        setVideoFrameRate(mCamcorderProfile.videoFrameRate);
+        setVideoSize(
+                mCamcorderProfile.videoFrameWidth, mCamcorderProfile.videoFrameHeight);
+        setMaxFileSize(sizeLimit);
+    }
+
+    Uri getVideoUri() {
+        return mTempVideoUri;
+    }
+
+    int getVideoWidth() {
+        return mCamcorderProfile.videoFrameWidth;
+    }
+
+    int getVideoHeight() {
+        return mCamcorderProfile.videoFrameHeight;
+    }
+
+    void cleanupTempFile() {
+        final Uri tempUri = mTempVideoUri;
+        SafeAsyncTask.executeOnThreadPool(new Runnable() {
+            @Override
+            public void run() {
+                Factory.get().getApplicationContext().getContentResolver().delete(
+                        tempUri, null, null);
+            }
+        });
+        mTempVideoUri = null;
+    }
+
+    String getContentType() {
+        if (mCamcorderProfile.fileFormat == OutputFormat.MPEG_4) {
+            return ContentType.VIDEO_MP4;
+        } else {
+            // 3GPP is the only other video format with a constant in OutputFormat
+            return ContentType.VIDEO_3GPP;
+        }
+    }
+
+    public void closeVideoFileDescriptor() {
+        if (mVideoFD != null) {
+            try {
+                mVideoFD.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+            mVideoFD = null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/PausableChronometer.java b/src/com/android/messaging/ui/mediapicker/PausableChronometer.java
new file mode 100644
index 0000000..dc8f90b
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/PausableChronometer.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.widget.Chronometer;
+
+import com.android.messaging.ui.PlaybackStateView;
+
+/**
+ * A pausable Chronometer implementation. The default Chronometer in Android only stops the UI
+ * from updating when you call stop(), but doesn't actually pause it. This implementation adds an
+ * additional timestamp that tracks the timespan for the pause and compensate for that.
+ */
+public class PausableChronometer extends Chronometer implements PlaybackStateView {
+    // Keeps track of how far long the Chronometer has been tracking when it's paused. We'd like
+    // to start from this time the next time it's resumed.
+    private long mTimeWhenPaused = 0;
+
+    public PausableChronometer(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Reset the timer and start counting from zero.
+     */
+    @Override
+    public void restart() {
+        reset();
+        start();
+    }
+
+    /**
+     * Reset the timer to zero, but don't start it.
+     */
+    @Override
+    public void reset() {
+        stop();
+        setBase(SystemClock.elapsedRealtime());
+        mTimeWhenPaused = 0;
+    }
+
+    /**
+     * Resume the timer after a previous pause.
+     */
+    @Override
+    public void resume() {
+        setBase(SystemClock.elapsedRealtime() - mTimeWhenPaused);
+        start();
+    }
+
+    /**
+     * Pause the timer.
+     */
+    @Override
+    public void pause() {
+        stop();
+        mTimeWhenPaused = SystemClock.elapsedRealtime() - getBase();
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/SoftwareCameraPreview.java b/src/com/android/messaging/ui/mediapicker/SoftwareCameraPreview.java
new file mode 100644
index 0000000..5dc3185
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/SoftwareCameraPreview.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.os.Parcelable;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+
+import java.io.IOException;
+
+/**
+ * A software rendered preview surface for the camera.  This renders slower and causes more jank, so
+ * HardwareCameraPreview is preferred if possible.
+ *
+ * There is a significant amount of duplication between HardwareCameraPreview and
+ * SoftwareCameraPreview which we can't easily share due to a lack of multiple inheritance, The
+ * implementations of the shared methods are delegated to CameraPreview
+ */
+public class SoftwareCameraPreview extends SurfaceView implements CameraPreview.CameraPreviewHost {
+    private final CameraPreview mPreview;
+
+    public SoftwareCameraPreview(final Context context) {
+        super(context);
+        mPreview = new CameraPreview(this);
+        getHolder().addCallback(new SurfaceHolder.Callback() {
+            @Override
+            public void surfaceCreated(final SurfaceHolder surfaceHolder) {
+                CameraManager.get().setSurface(mPreview);
+            }
+
+            @Override
+            public void surfaceChanged(final SurfaceHolder surfaceHolder, final int format, final int width,
+                                       final int height) {
+                CameraManager.get().setSurface(mPreview);
+            }
+
+            @Override
+            public void surfaceDestroyed(final SurfaceHolder surfaceHolder) {
+                CameraManager.get().setSurface(null);
+            }
+        });
+    }
+
+
+    @Override
+    protected void onVisibilityChanged(final View changedView, final int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        mPreview.onVisibilityChanged(visibility);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mPreview.onDetachedFromWindow();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mPreview.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onRestoreInstanceState(final Parcelable state) {
+        super.onRestoreInstanceState(state);
+        mPreview.onRestoreInstanceState();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        widthMeasureSpec = mPreview.getWidthMeasureSpec(widthMeasureSpec, heightMeasureSpec);
+        heightMeasureSpec = mPreview.getHeightMeasureSpec(widthMeasureSpec, heightMeasureSpec);
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public boolean isValid() {
+        return getHolder() != null;
+    }
+
+    @Override
+    public void startPreview(final Camera camera) throws IOException {
+        camera.setPreviewDisplay(getHolder());
+    }
+
+    @Override
+    public void onCameraPermissionGranted() {
+        mPreview.onCameraPermissionGranted();
+    }
+}
+
+
diff --git a/src/com/android/messaging/ui/mediapicker/SoundLevels.java b/src/com/android/messaging/ui/mediapicker/SoundLevels.java
new file mode 100644
index 0000000..6f4dca6
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/SoundLevels.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.animation.TimeAnimator.TimeListener;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.messaging.R;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * This view draws circular sound levels. By default the sound levels are black, unless
+ * otherwise defined via {@link #mPrimaryLevelPaint}.
+ */
+public class SoundLevels extends View {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final boolean DEBUG = false;
+
+    private boolean mCenterDefined;
+    private int mCenterX;
+    private int mCenterY;
+
+    // Paint for the main level meter, most closely follows the mic.
+    private final Paint mPrimaryLevelPaint;
+
+    // The minimum size of the levels as a percentage of the max, that is the size when volume is 0.
+    private final float mMinimumLevel;
+
+    // The minimum size of the levels, that is the size when volume is 0.
+    private final float mMinimumLevelSize;
+
+    // The maximum size of the levels, that is the size when volume is 100.
+    private final float mMaximumLevelSize;
+
+    // Generates clock ticks for the animation using the global animation loop.
+    private final TimeAnimator mSpeechLevelsAnimator;
+
+    private float mCurrentVolume;
+
+    // Indicates whether we should be animating the sound level.
+    private boolean mIsEnabled;
+
+    // Input level is pulled from here.
+    private AudioLevelSource mLevelSource;
+
+    public SoundLevels(final Context context) {
+        this(context, null);
+    }
+
+    public SoundLevels(final Context context, final AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SoundLevels(final Context context, final AttributeSet attrs, final int defStyle) {
+        super(context, attrs, defStyle);
+
+        // Safe source, replaced with system one when attached.
+        mLevelSource = new AudioLevelSource();
+        mLevelSource.setSpeechLevel(0);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SoundLevels,
+                defStyle, 0);
+
+        mMaximumLevelSize = a.getDimensionPixelOffset(
+                R.styleable.SoundLevels_maxLevelRadius, 0);
+        mMinimumLevelSize = a.getDimensionPixelOffset(
+                R.styleable.SoundLevels_minLevelRadius, 0);
+        mMinimumLevel = mMinimumLevelSize / mMaximumLevelSize;
+
+        mPrimaryLevelPaint = new Paint();
+        mPrimaryLevelPaint.setColor(
+                a.getColor(R.styleable.SoundLevels_primaryColor, Color.BLACK));
+        mPrimaryLevelPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+
+        a.recycle();
+
+        // This animator generates ticks that invalidate the
+        // view so that the animation is synced with the global animation loop.
+        // TODO: We could probably remove this in favor of using postInvalidateOnAnimation
+        // which might improve things further.
+        mSpeechLevelsAnimator = new TimeAnimator();
+        mSpeechLevelsAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+        mSpeechLevelsAnimator.setTimeListener(new TimeListener() {
+            @Override
+            public void onTimeUpdate(final TimeAnimator animation, final long totalTime,
+                    final long deltaTime) {
+                invalidate();
+            }
+        });
+    }
+
+    @Override
+    protected void onDraw(final Canvas canvas) {
+        if (!mIsEnabled) {
+            return;
+        }
+
+        if (!mCenterDefined) {
+            // One time computation here, because we can't rely on getWidth() to be computed at
+            // constructor time or in onFinishInflate :(.
+            mCenterX = getWidth() / 2;
+            mCenterY = getWidth() / 2;
+            mCenterDefined = true;
+        }
+
+        final int level = mLevelSource.getSpeechLevel();
+        // Either ease towards the target level, or decay away from it depending on whether
+        // its higher or lower than the current.
+        if (level > mCurrentVolume) {
+            mCurrentVolume = mCurrentVolume + ((level - mCurrentVolume) / 4);
+        } else {
+            mCurrentVolume = mCurrentVolume * 0.95f;
+        }
+
+        final float radius = mMinimumLevel + (1f - mMinimumLevel) * mCurrentVolume / 100;
+        mPrimaryLevelPaint.setStyle(Style.FILL);
+        canvas.drawCircle(mCenterX, mCenterY, radius * mMaximumLevelSize, mPrimaryLevelPaint);
+    }
+
+    public void setLevelSource(final AudioLevelSource source) {
+        if (DEBUG) {
+            Log.d(TAG, "Speech source set.");
+        }
+        mLevelSource = source;
+    }
+
+    private void startSpeechLevelsAnimator() {
+        if (DEBUG) {
+            Log.d(TAG, "startAnimator()");
+        }
+        if (!mSpeechLevelsAnimator.isStarted()) {
+            mSpeechLevelsAnimator.start();
+        }
+    }
+
+    private void stopSpeechLevelsAnimator() {
+        if (DEBUG) {
+            Log.d(TAG, "stopAnimator()");
+        }
+        if (mSpeechLevelsAnimator.isStarted()) {
+            mSpeechLevelsAnimator.end();
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        stopSpeechLevelsAnimator();
+    }
+
+    @Override
+    public void setEnabled(final boolean enabled) {
+        if (enabled == mIsEnabled) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d("TAG", "setEnabled: " + enabled);
+        }
+        super.setEnabled(enabled);
+        mIsEnabled = enabled;
+        setKeepScreenOn(enabled);
+        updateSpeechLevelsAnimatorState();
+    }
+
+    private void updateSpeechLevelsAnimatorState() {
+        if (mIsEnabled) {
+            startSpeechLevelsAnimator();
+        } else {
+            stopSpeechLevelsAnimator();
+        }
+    }
+
+    /**
+     * This is required to make the View findable by uiautomator
+     */
+    @Override
+    public void onInitializeAccessibilityNodeInfo(final AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(SoundLevels.class.getCanonicalName());
+    }
+
+    /**
+     * Set the alpha level of the sound circles.
+     */
+    public void setPrimaryColorAlpha(final int alpha) {
+        mPrimaryLevelPaint.setAlpha(alpha);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/FocusIndicator.java b/src/com/android/messaging/ui/mediapicker/camerafocus/FocusIndicator.java
new file mode 100644
index 0000000..92ed3c1
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/FocusIndicator.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+public interface FocusIndicator {
+    public void showStart();
+    public void showSuccess(boolean timeout);
+    public void showFail(boolean timeout);
+    public void clear();
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/FocusOverlayManager.java b/src/com/android/messaging/ui/mediapicker/camerafocus/FocusOverlayManager.java
new file mode 100644
index 0000000..e620fc2
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/FocusOverlayManager.java
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.hardware.Camera.Area;
+import android.hardware.Camera.Parameters;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* A class that handles everything about focus in still picture mode.
+ * This also handles the metering area because it is the same as focus area.
+ *
+ * The test cases:
+ * (1) The camera has continuous autofocus. Move the camera. Take a picture when
+ *     CAF is not in progress.
+ * (2) The camera has continuous autofocus. Move the camera. Take a picture when
+ *     CAF is in progress.
+ * (3) The camera has face detection. Point the camera at some faces. Hold the
+ *     shutter. Release to take a picture.
+ * (4) The camera has face detection. Point the camera at some faces. Single tap
+ *     the shutter to take a picture.
+ * (5) The camera has autofocus. Single tap the shutter to take a picture.
+ * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
+ * (7) The camera has no autofocus. Single tap the shutter and take a picture.
+ * (8) The camera has autofocus and supports focus area. Touch the screen to
+ *     trigger autofocus. Take a picture.
+ * (9) The camera has autofocus and supports focus area. Touch the screen to
+ *     trigger autofocus. Wait until it times out.
+ * (10) The camera has no autofocus and supports metering area. Touch the screen
+ *     to change metering area.
+ */
+public class FocusOverlayManager {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final String TRUE = "true";
+    private static final String AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported";
+    private static final String AUTO_WHITE_BALANCE_LOCK_SUPPORTED =
+            "auto-whitebalance-lock-supported";
+
+    private static final int RESET_TOUCH_FOCUS = 0;
+    private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
+
+    private int mState = STATE_IDLE;
+    private static final int STATE_IDLE = 0; // Focus is not active.
+    private static final int STATE_FOCUSING = 1; // Focus is in progress.
+    // Focus is in progress and the camera should take a picture after focus finishes.
+    private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
+    private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
+    private static final int STATE_FAIL = 4; // Focus finishes and fails.
+
+    private boolean mInitialized;
+    private boolean mFocusAreaSupported;
+    private boolean mMeteringAreaSupported;
+    private boolean mLockAeAwbNeeded;
+    private boolean mAeAwbLock;
+    private Matrix mMatrix;
+
+    private PieRenderer mPieRenderer;
+
+    private int mPreviewWidth; // The width of the preview frame layout.
+    private int mPreviewHeight; // The height of the preview frame layout.
+    private boolean mMirror; // true if the camera is front-facing.
+    private int mDisplayOrientation;
+    private List<Object> mFocusArea; // focus area in driver format
+    private List<Object> mMeteringArea; // metering area in driver format
+    private String mFocusMode;
+    private String mOverrideFocusMode;
+    private Parameters mParameters;
+    private Handler mHandler;
+    Listener mListener;
+
+    public interface Listener {
+        public void autoFocus();
+        public void cancelAutoFocus();
+        public boolean capture();
+        public void setFocusParameters();
+    }
+
+    private class MainHandler extends Handler {
+        public MainHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case RESET_TOUCH_FOCUS: {
+                    cancelAutoFocus();
+                    break;
+                }
+            }
+        }
+    }
+
+    public FocusOverlayManager(Listener listener, Looper looper) {
+        mHandler = new MainHandler(looper);
+        mMatrix = new Matrix();
+        mListener = listener;
+    }
+
+    public void setFocusRenderer(PieRenderer renderer) {
+        mPieRenderer = renderer;
+        mInitialized = (mMatrix != null);
+    }
+
+    public void setParameters(Parameters parameters) {
+        // parameters can only be null when onConfigurationChanged is called
+        // before camera is open. We will just return in this case, because
+        // parameters will be set again later with the right parameters after
+        // camera is open.
+        if (parameters == null) {
+            return;
+        }
+        mParameters = parameters;
+        mFocusAreaSupported = isFocusAreaSupported(parameters);
+        mMeteringAreaSupported = isMeteringAreaSupported(parameters);
+        mLockAeAwbNeeded = (isAutoExposureLockSupported(mParameters) ||
+                isAutoWhiteBalanceLockSupported(mParameters));
+    }
+
+    public void setPreviewSize(int previewWidth, int previewHeight) {
+        if (mPreviewWidth != previewWidth || mPreviewHeight != previewHeight) {
+            mPreviewWidth = previewWidth;
+            mPreviewHeight = previewHeight;
+            setMatrix();
+        }
+    }
+
+    public void setMirror(boolean mirror) {
+        mMirror = mirror;
+        setMatrix();
+    }
+
+    public void setDisplayOrientation(int displayOrientation) {
+        mDisplayOrientation = displayOrientation;
+        setMatrix();
+    }
+
+    private void setMatrix() {
+        if (mPreviewWidth != 0 && mPreviewHeight != 0) {
+            Matrix matrix = new Matrix();
+            prepareMatrix(matrix, mMirror, mDisplayOrientation,
+                    mPreviewWidth, mPreviewHeight);
+            // In face detection, the matrix converts the driver coordinates to UI
+            // coordinates. In tap focus, the inverted matrix converts the UI
+            // coordinates to driver coordinates.
+            matrix.invert(mMatrix);
+            mInitialized = (mPieRenderer != null);
+        }
+    }
+
+    private void lockAeAwbIfNeeded() {
+        if (mLockAeAwbNeeded && !mAeAwbLock) {
+            mAeAwbLock = true;
+            mListener.setFocusParameters();
+        }
+    }
+
+    private void unlockAeAwbIfNeeded() {
+        if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
+            mAeAwbLock = false;
+            mListener.setFocusParameters();
+        }
+    }
+
+    public void onShutterDown() {
+        if (!mInitialized) {
+            return;
+        }
+
+        boolean autoFocusCalled = false;
+        if (needAutoFocusCall()) {
+            // Do not focus if touch focus has been triggered.
+            if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
+                autoFocus();
+                autoFocusCalled = true;
+            }
+        }
+
+        if (!autoFocusCalled) {
+            lockAeAwbIfNeeded();
+        }
+    }
+
+    public void onShutterUp() {
+        if (!mInitialized) {
+            return;
+        }
+
+        if (needAutoFocusCall()) {
+            // User releases half-pressed focus key.
+            if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
+                    || mState == STATE_FAIL) {
+                cancelAutoFocus();
+            }
+        }
+
+        // Unlock AE and AWB after cancelAutoFocus. Camera API does not
+        // guarantee setParameters can be called during autofocus.
+        unlockAeAwbIfNeeded();
+    }
+
+    public void doSnap() {
+        if (!mInitialized) {
+            return;
+        }
+
+        // If the user has half-pressed the shutter and focus is completed, we
+        // can take the photo right away. If the focus mode is infinity, we can
+        // also take the photo.
+        if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
+            capture();
+        } else if (mState == STATE_FOCUSING) {
+            // Half pressing the shutter (i.e. the focus button event) will
+            // already have requested AF for us, so just request capture on
+            // focus here.
+            mState = STATE_FOCUSING_SNAP_ON_FINISH;
+        } else if (mState == STATE_IDLE) {
+            // We didn't do focus. This can happen if the user press focus key
+            // while the snapshot is still in progress. The user probably wants
+            // the next snapshot as soon as possible, so we just do a snapshot
+            // without focusing again.
+            capture();
+        }
+    }
+
+    public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
+        if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
+            // Take the picture no matter focus succeeds or fails. No need
+            // to play the AF sound if we're about to play the shutter
+            // sound.
+            if (focused) {
+                mState = STATE_SUCCESS;
+            } else {
+                mState = STATE_FAIL;
+            }
+            updateFocusUI();
+            capture();
+        } else if (mState == STATE_FOCUSING) {
+            // This happens when (1) user is half-pressing the focus key or
+            // (2) touch focus is triggered. Play the focus tone. Do not
+            // take the picture now.
+            if (focused) {
+                mState = STATE_SUCCESS;
+            } else {
+                mState = STATE_FAIL;
+            }
+            updateFocusUI();
+            // If this is triggered by touch focus, cancel focus after a
+            // while.
+            if (mFocusArea != null) {
+                mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
+            }
+            if (shutterButtonPressed) {
+                // Lock AE & AWB so users can half-press shutter and recompose.
+                lockAeAwbIfNeeded();
+            }
+        } else if (mState == STATE_IDLE) {
+            // User has released the focus key before focus completes.
+            // Do nothing.
+        }
+    }
+
+    public void onAutoFocusMoving(boolean moving) {
+        if (!mInitialized) {
+            return;
+        }
+
+        // Ignore if we have requested autofocus. This method only handles
+        // continuous autofocus.
+        if (mState != STATE_IDLE) {
+            return;
+        }
+
+        if (moving) {
+            mPieRenderer.showStart();
+        } else {
+            mPieRenderer.showSuccess(true);
+        }
+    }
+
+    private void initializeFocusAreas(int focusWidth, int focusHeight,
+            int x, int y, int previewWidth, int previewHeight) {
+        if (mFocusArea == null) {
+            mFocusArea = new ArrayList<Object>();
+            mFocusArea.add(new Area(new Rect(), 1));
+        }
+
+        // Convert the coordinates to driver format.
+        calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth, previewHeight,
+                ((Area) mFocusArea.get(0)).rect);
+    }
+
+    private void initializeMeteringAreas(int focusWidth, int focusHeight,
+            int x, int y, int previewWidth, int previewHeight) {
+        if (mMeteringArea == null) {
+            mMeteringArea = new ArrayList<Object>();
+            mMeteringArea.add(new Area(new Rect(), 1));
+        }
+
+        // Convert the coordinates to driver format.
+        // AE area is bigger because exposure is sensitive and
+        // easy to over- or underexposure if area is too small.
+        calculateTapArea(focusWidth, focusHeight, 1.5f, x, y, previewWidth, previewHeight,
+                ((Area) mMeteringArea.get(0)).rect);
+    }
+
+    public void onSingleTapUp(int x, int y) {
+        if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
+            return;
+        }
+
+        // Let users be able to cancel previous touch focus.
+        if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
+                    mState == STATE_SUCCESS || mState == STATE_FAIL)) {
+            cancelAutoFocus();
+        }
+        // Initialize variables.
+        int focusWidth = mPieRenderer.getSize();
+        int focusHeight = mPieRenderer.getSize();
+        if (focusWidth == 0 || mPieRenderer.getWidth() == 0 || mPieRenderer.getHeight() == 0) {
+            return;
+        }
+        int previewWidth = mPreviewWidth;
+        int previewHeight = mPreviewHeight;
+        // Initialize mFocusArea.
+        if (mFocusAreaSupported) {
+            initializeFocusAreas(focusWidth, focusHeight, x, y, previewWidth, previewHeight);
+        }
+        // Initialize mMeteringArea.
+        if (mMeteringAreaSupported) {
+            initializeMeteringAreas(focusWidth, focusHeight, x, y, previewWidth, previewHeight);
+        }
+
+        // Use margin to set the focus indicator to the touched area.
+        mPieRenderer.setFocus(x, y);
+
+        // Set the focus area and metering area.
+        mListener.setFocusParameters();
+        if (mFocusAreaSupported) {
+            autoFocus();
+        } else {  // Just show the indicator in all other cases.
+            updateFocusUI();
+            // Reset the metering area in 3 seconds.
+            mHandler.removeMessages(RESET_TOUCH_FOCUS);
+            mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
+        }
+    }
+
+    public void onPreviewStarted() {
+        mState = STATE_IDLE;
+    }
+
+    public void onPreviewStopped() {
+        // If auto focus was in progress, it would have been stopped.
+        mState = STATE_IDLE;
+        resetTouchFocus();
+        updateFocusUI();
+    }
+
+    public void onCameraReleased() {
+        onPreviewStopped();
+    }
+
+    private void autoFocus() {
+        LogUtil.v(TAG, "Start autofocus.");
+        mListener.autoFocus();
+        mState = STATE_FOCUSING;
+        updateFocusUI();
+        mHandler.removeMessages(RESET_TOUCH_FOCUS);
+    }
+
+    private void cancelAutoFocus() {
+        LogUtil.v(TAG, "Cancel autofocus.");
+
+        // Reset the tap area before calling mListener.cancelAutofocus.
+        // Otherwise, focus mode stays at auto and the tap area passed to the
+        // driver is not reset.
+        resetTouchFocus();
+        mListener.cancelAutoFocus();
+        mState = STATE_IDLE;
+        updateFocusUI();
+        mHandler.removeMessages(RESET_TOUCH_FOCUS);
+    }
+
+    private void capture() {
+        if (mListener.capture()) {
+            mState = STATE_IDLE;
+            mHandler.removeMessages(RESET_TOUCH_FOCUS);
+        }
+    }
+
+    public String getFocusMode() {
+        if (mOverrideFocusMode != null) {
+            return mOverrideFocusMode;
+        }
+        List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
+
+        if (mFocusAreaSupported && mFocusArea != null) {
+            // Always use autofocus in tap-to-focus.
+            mFocusMode = Parameters.FOCUS_MODE_AUTO;
+        } else {
+            mFocusMode = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
+        }
+
+        if (!isSupported(mFocusMode, supportedFocusModes)) {
+            // For some reasons, the driver does not support the current
+            // focus mode. Fall back to auto.
+            if (isSupported(Parameters.FOCUS_MODE_AUTO,
+                    mParameters.getSupportedFocusModes())) {
+                mFocusMode = Parameters.FOCUS_MODE_AUTO;
+            } else {
+                mFocusMode = mParameters.getFocusMode();
+            }
+        }
+        return mFocusMode;
+    }
+
+    public List getFocusAreas() {
+        return mFocusArea;
+    }
+
+    public List getMeteringAreas() {
+        return mMeteringArea;
+    }
+
+    public void updateFocusUI() {
+        if (!mInitialized) {
+            return;
+        }
+        FocusIndicator focusIndicator = mPieRenderer;
+
+        if (mState == STATE_IDLE) {
+            if (mFocusArea == null) {
+                focusIndicator.clear();
+            } else {
+                // Users touch on the preview and the indicator represents the
+                // metering area. Either focus area is not supported or
+                // autoFocus call is not required.
+                focusIndicator.showStart();
+            }
+        } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
+            focusIndicator.showStart();
+        } else {
+            if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
+                // TODO: check HAL behavior and decide if this can be removed.
+                focusIndicator.showSuccess(false);
+            } else if (mState == STATE_SUCCESS) {
+                focusIndicator.showSuccess(false);
+            } else if (mState == STATE_FAIL) {
+                focusIndicator.showFail(false);
+            }
+        }
+    }
+
+    public void resetTouchFocus() {
+        if (!mInitialized) {
+            return;
+        }
+
+        // Put focus indicator to the center. clear reset position
+        mPieRenderer.clear();
+
+        mFocusArea = null;
+        mMeteringArea = null;
+    }
+
+    private void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
+            int x, int y, int previewWidth, int previewHeight, Rect rect) {
+        int areaWidth = (int) (focusWidth * areaMultiple);
+        int areaHeight = (int) (focusHeight * areaMultiple);
+        int left = clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
+        int top = clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
+
+        RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
+        mMatrix.mapRect(rectF);
+        rectFToRect(rectF, rect);
+    }
+
+    /* package */ int getFocusState() {
+        return mState;
+    }
+
+    public boolean isFocusCompleted() {
+        return mState == STATE_SUCCESS || mState == STATE_FAIL;
+    }
+
+    public boolean isFocusingSnapOnFinish() {
+        return mState == STATE_FOCUSING_SNAP_ON_FINISH;
+    }
+
+    public void removeMessages() {
+        mHandler.removeMessages(RESET_TOUCH_FOCUS);
+    }
+
+    public void overrideFocusMode(String focusMode) {
+        mOverrideFocusMode = focusMode;
+    }
+
+    public void setAeAwbLock(boolean lock) {
+        mAeAwbLock = lock;
+    }
+
+    public boolean getAeAwbLock() {
+        return mAeAwbLock;
+    }
+
+    private boolean needAutoFocusCall() {
+        String focusMode = getFocusMode();
+        return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
+                || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
+                || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
+    }
+
+    public static boolean isAutoExposureLockSupported(Parameters params) {
+        return TRUE.equals(params.get(AUTO_EXPOSURE_LOCK_SUPPORTED));
+    }
+
+    public static boolean isAutoWhiteBalanceLockSupported(Parameters params) {
+        return TRUE.equals(params.get(AUTO_WHITE_BALANCE_LOCK_SUPPORTED));
+    }
+
+    public static boolean isSupported(String value, List<String> supported) {
+        return supported != null && supported.indexOf(value) >= 0;
+    }
+
+    public static boolean isMeteringAreaSupported(Parameters params) {
+        return params.getMaxNumMeteringAreas() > 0;
+    }
+
+    public static boolean isFocusAreaSupported(Parameters params) {
+        return (params.getMaxNumFocusAreas() > 0
+                && isSupported(Parameters.FOCUS_MODE_AUTO,
+                params.getSupportedFocusModes()));
+    }
+
+    public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation,
+                                     int viewWidth, int viewHeight) {
+        // Need mirror for front camera.
+        matrix.setScale(mirror ? -1 : 1, 1);
+        // This is the value for android.hardware.Camera.setDisplayOrientation.
+        matrix.postRotate(displayOrientation);
+        // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
+        // UI coordinates range from (0, 0) to (width, height).
+        matrix.postScale(viewWidth / 2000f, viewHeight / 2000f);
+        matrix.postTranslate(viewWidth / 2f, viewHeight / 2f);
+    }
+
+    public static int clamp(int x, int min, int max) {
+        Assert.isTrue(max >= min);
+        if (x > max) {
+            return max;
+        }
+        if (x < min) {
+            return min;
+        }
+        return x;
+    }
+
+    public static void rectFToRect(RectF rectF, Rect rect) {
+        rect.left = Math.round(rectF.left);
+        rect.top = Math.round(rectF.top);
+        rect.right = Math.round(rectF.right);
+        rect.bottom = Math.round(rectF.bottom);
+    }
+}
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/OverlayRenderer.java b/src/com/android/messaging/ui/mediapicker/camerafocus/OverlayRenderer.java
new file mode 100644
index 0000000..df6734f
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/OverlayRenderer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.MotionEvent;
+
+public abstract class OverlayRenderer implements RenderOverlay.Renderer {
+
+    private static final String TAG = "CAM OverlayRenderer";
+    protected RenderOverlay mOverlay;
+
+    protected int mLeft, mTop, mRight, mBottom;
+
+    protected boolean mVisible;
+
+    public void setVisible(boolean vis) {
+        mVisible = vis;
+        update();
+    }
+
+    public boolean isVisible() {
+        return mVisible;
+    }
+
+    // default does not handle touch
+    @Override
+    public boolean handlesTouch() {
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent evt) {
+        return false;
+    }
+
+    public abstract void onDraw(Canvas canvas);
+
+    public void draw(Canvas canvas) {
+        if (mVisible) {
+            onDraw(canvas);
+        }
+    }
+
+    @Override
+    public void setOverlay(RenderOverlay overlay) {
+        mOverlay = overlay;
+    }
+
+    @Override
+    public void layout(int left, int top, int right, int bottom) {
+        mLeft = left;
+        mRight = right;
+        mTop = top;
+        mBottom = bottom;
+    }
+
+    protected Context getContext() {
+        if (mOverlay != null) {
+            return mOverlay.getContext();
+        } else {
+            return null;
+        }
+    }
+
+    public int getWidth() {
+        return mRight - mLeft;
+    }
+
+    public int getHeight() {
+        return mBottom - mTop;
+    }
+
+    protected void update() {
+        if (mOverlay != null) {
+            mOverlay.update();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/PieItem.java b/src/com/android/messaging/ui/mediapicker/camerafocus/PieItem.java
new file mode 100644
index 0000000..c602852
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/PieItem.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.drawable.Drawable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Pie menu item
+ */
+public class PieItem {
+
+    public static interface OnClickListener {
+        void onClick(PieItem item);
+    }
+
+    private Drawable mDrawable;
+    private int level;
+    private float mCenter;
+    private float start;
+    private float sweep;
+    private float animate;
+    private int inner;
+    private int outer;
+    private boolean mSelected;
+    private boolean mEnabled;
+    private List<PieItem> mItems;
+    private Path mPath;
+    private OnClickListener mOnClickListener;
+    private float mAlpha;
+
+    // Gray out the view when disabled
+    private static final float ENABLED_ALPHA = 1;
+    private static final float DISABLED_ALPHA = (float) 0.3;
+    private boolean mChangeAlphaWhenDisabled = true;
+
+    public PieItem(Drawable drawable, int level) {
+        mDrawable = drawable;
+        this.level = level;
+        setAlpha(1f);
+        mEnabled = true;
+        setAnimationAngle(getAnimationAngle());
+        start = -1;
+        mCenter = -1;
+    }
+
+    public boolean hasItems() {
+        return mItems != null;
+    }
+
+    public List<PieItem> getItems() {
+        return mItems;
+    }
+
+    public void addItem(PieItem item) {
+        if (mItems == null) {
+            mItems = new ArrayList<PieItem>();
+        }
+        mItems.add(item);
+    }
+
+    public void setPath(Path p) {
+        mPath = p;
+    }
+
+    public Path getPath() {
+        return mPath;
+    }
+
+    public void setChangeAlphaWhenDisabled (boolean enable) {
+        mChangeAlphaWhenDisabled = enable;
+    }
+
+    public void setAlpha(float alpha) {
+        mAlpha = alpha;
+        mDrawable.setAlpha((int) (255 * alpha));
+    }
+
+    public void setAnimationAngle(float a) {
+        animate = a;
+    }
+
+    public float getAnimationAngle() {
+        return animate;
+    }
+
+    public void setEnabled(boolean enabled) {
+        mEnabled = enabled;
+        if (mChangeAlphaWhenDisabled) {
+            if (mEnabled) {
+                setAlpha(ENABLED_ALPHA);
+            } else {
+                setAlpha(DISABLED_ALPHA);
+            }
+        }
+    }
+
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    public void setSelected(boolean s) {
+        mSelected = s;
+    }
+
+    public boolean isSelected() {
+        return mSelected;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+    public void setGeometry(float st, float sw, int inside, int outside) {
+        start = st;
+        sweep = sw;
+        inner = inside;
+        outer = outside;
+    }
+
+    public void setFixedSlice(float center, float sweep) {
+        mCenter = center;
+        this.sweep = sweep;
+    }
+
+    public float getCenter() {
+        return mCenter;
+    }
+
+    public float getStart() {
+        return start;
+    }
+
+    public float getStartAngle() {
+        return start + animate;
+    }
+
+    public float getSweep() {
+        return sweep;
+    }
+
+    public int getInnerRadius() {
+        return inner;
+    }
+
+    public int getOuterRadius() {
+        return outer;
+    }
+
+    public void setOnClickListener(OnClickListener listener) {
+        mOnClickListener = listener;
+    }
+
+    public void performClick() {
+        if (mOnClickListener != null) {
+            mOnClickListener.onClick(this);
+        }
+    }
+
+    public int getIntrinsicWidth() {
+        return mDrawable.getIntrinsicWidth();
+    }
+
+    public int getIntrinsicHeight() {
+        return mDrawable.getIntrinsicHeight();
+    }
+
+    public void setBounds(int left, int top, int right, int bottom) {
+        mDrawable.setBounds(left, top, right, bottom);
+    }
+
+    public void draw(Canvas canvas) {
+        mDrawable.draw(canvas);
+    }
+
+    public void setImageResource(Context context, int resId) {
+        Drawable d = context.getResources().getDrawable(resId).mutate();
+        d.setBounds(mDrawable.getBounds());
+        mDrawable = d;
+        setAlpha(mAlpha);
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/PieRenderer.java b/src/com/android/messaging/ui/mediapicker/camerafocus/PieRenderer.java
new file mode 100644
index 0000000..ce8ca00
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/PieRenderer.java
@@ -0,0 +1,825 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.os.Handler;
+import android.os.Message;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.Transformation;
+import com.android.messaging.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PieRenderer extends OverlayRenderer
+        implements FocusIndicator {
+    // Sometimes continuous autofocus starts and stops several times quickly.
+    // These states are used to make sure the animation is run for at least some
+    // time.
+    private volatile int mState;
+    private ScaleAnimation mAnimation = new ScaleAnimation();
+    private static final int STATE_IDLE = 0;
+    private static final int STATE_FOCUSING = 1;
+    private static final int STATE_FINISHING = 2;
+    private static final int STATE_PIE = 8;
+
+    private Runnable mDisappear = new Disappear();
+    private Animation.AnimationListener mEndAction = new EndAction();
+    private static final int SCALING_UP_TIME = 600;
+    private static final int SCALING_DOWN_TIME = 100;
+    private static final int DISAPPEAR_TIMEOUT = 200;
+    private static final int DIAL_HORIZONTAL = 157;
+
+    private static final long PIE_FADE_IN_DURATION = 200;
+    private static final long PIE_XFADE_DURATION = 200;
+    private static final long PIE_SELECT_FADE_DURATION = 300;
+
+    private static final int MSG_OPEN = 0;
+    private static final int MSG_CLOSE = 1;
+    private static final float PIE_SWEEP = (float) (Math.PI * 2 / 3);
+    // geometry
+    private Point mCenter;
+    private int mRadius;
+    private int mRadiusInc;
+
+    // the detection if touch is inside a slice is offset
+    // inbounds by this amount to allow the selection to show before the
+    // finger covers it
+    private int mTouchOffset;
+
+    private List<PieItem> mItems;
+
+    private PieItem mOpenItem;
+
+    private Paint mSelectedPaint;
+    private Paint mSubPaint;
+
+    // touch handling
+    private PieItem mCurrentItem;
+
+    private Paint mFocusPaint;
+    private int mSuccessColor;
+    private int mFailColor;
+    private int mCircleSize;
+    private int mFocusX;
+    private int mFocusY;
+    private int mCenterX;
+    private int mCenterY;
+
+    private int mDialAngle;
+    private RectF mCircle;
+    private RectF mDial;
+    private Point mPoint1;
+    private Point mPoint2;
+    private int mStartAnimationAngle;
+    private boolean mFocused;
+    private int mInnerOffset;
+    private int mOuterStroke;
+    private int mInnerStroke;
+    private boolean mTapMode;
+    private boolean mBlockFocus;
+    private int mTouchSlopSquared;
+    private Point mDown;
+    private boolean mOpening;
+    private LinearAnimation mXFade;
+    private LinearAnimation mFadeIn;
+    private volatile boolean mFocusCancelled;
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_OPEN:
+                    if (mListener != null) {
+                        mListener.onPieOpened(mCenter.x, mCenter.y);
+                    }
+                    break;
+                case MSG_CLOSE:
+                    if (mListener != null) {
+                        mListener.onPieClosed();
+                    }
+                    break;
+            }
+        }
+    };
+
+    private PieListener mListener;
+
+    public static interface PieListener {
+        public void onPieOpened(int centerX, int centerY);
+        public void onPieClosed();
+    }
+
+    public void setPieListener(PieListener pl) {
+        mListener = pl;
+    }
+
+    public PieRenderer(Context context) {
+        init(context);
+    }
+
+    private void init(Context ctx) {
+        setVisible(false);
+        mItems = new ArrayList<PieItem>();
+        Resources res = ctx.getResources();
+        mRadius = (int) res.getDimensionPixelSize(R.dimen.pie_radius_start);
+        mCircleSize = mRadius - res.getDimensionPixelSize(R.dimen.focus_radius_offset);
+        mRadiusInc =  (int) res.getDimensionPixelSize(R.dimen.pie_radius_increment);
+        mTouchOffset = (int) res.getDimensionPixelSize(R.dimen.pie_touch_offset);
+        mCenter = new Point(0, 0);
+        mSelectedPaint = new Paint();
+        mSelectedPaint.setColor(Color.argb(255, 51, 181, 229));
+        mSelectedPaint.setAntiAlias(true);
+        mSubPaint = new Paint();
+        mSubPaint.setAntiAlias(true);
+        mSubPaint.setColor(Color.argb(200, 250, 230, 128));
+        mFocusPaint = new Paint();
+        mFocusPaint.setAntiAlias(true);
+        mFocusPaint.setColor(Color.WHITE);
+        mFocusPaint.setStyle(Paint.Style.STROKE);
+        mSuccessColor = Color.GREEN;
+        mFailColor = Color.RED;
+        mCircle = new RectF();
+        mDial = new RectF();
+        mPoint1 = new Point();
+        mPoint2 = new Point();
+        mInnerOffset = res.getDimensionPixelSize(R.dimen.focus_inner_offset);
+        mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke);
+        mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke);
+        mState = STATE_IDLE;
+        mBlockFocus = false;
+        mTouchSlopSquared = ViewConfiguration.get(ctx).getScaledTouchSlop();
+        mTouchSlopSquared = mTouchSlopSquared * mTouchSlopSquared;
+        mDown = new Point();
+    }
+
+    public boolean showsItems() {
+        return mTapMode;
+    }
+
+    public void addItem(PieItem item) {
+        // add the item to the pie itself
+        mItems.add(item);
+    }
+
+    public void removeItem(PieItem item) {
+        mItems.remove(item);
+    }
+
+    public void clearItems() {
+        mItems.clear();
+    }
+
+    public void showInCenter() {
+        if ((mState == STATE_PIE) && isVisible()) {
+            mTapMode = false;
+            show(false);
+        } else {
+            if (mState != STATE_IDLE) {
+                cancelFocus();
+            }
+            mState = STATE_PIE;
+            setCenter(mCenterX, mCenterY);
+            mTapMode = true;
+            show(true);
+        }
+    }
+
+    public void hide() {
+        show(false);
+    }
+
+    /**
+     * guaranteed has center set
+     * @param show
+     */
+    private void show(boolean show) {
+        if (show) {
+            mState = STATE_PIE;
+            // ensure clean state
+            mCurrentItem = null;
+            mOpenItem = null;
+            for (PieItem item : mItems) {
+                item.setSelected(false);
+            }
+            layoutPie();
+            fadeIn();
+        } else {
+            mState = STATE_IDLE;
+            mTapMode = false;
+            if (mXFade != null) {
+                mXFade.cancel();
+            }
+        }
+        setVisible(show);
+        mHandler.sendEmptyMessage(show ? MSG_OPEN : MSG_CLOSE);
+    }
+
+    private void fadeIn() {
+        mFadeIn = new LinearAnimation(0, 1);
+        mFadeIn.setDuration(PIE_FADE_IN_DURATION);
+        mFadeIn.setAnimationListener(new AnimationListener() {
+            @Override
+            public void onAnimationStart(Animation animation) {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation) {
+                mFadeIn = null;
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation) {
+            }
+        });
+        mFadeIn.startNow();
+        mOverlay.startAnimation(mFadeIn);
+    }
+
+    public void setCenter(int x, int y) {
+        mCenter.x = x;
+        mCenter.y = y;
+        // when using the pie menu, align the focus ring
+        alignFocus(x, y);
+    }
+
+    private void layoutPie() {
+        int rgap = 2;
+        int inner = mRadius + rgap;
+        int outer = mRadius + mRadiusInc - rgap;
+        int gap = 1;
+        layoutItems(mItems, (float) (Math.PI / 2), inner, outer, gap);
+    }
+
+    private void layoutItems(List<PieItem> items, float centerAngle, int inner,
+                             int outer, int gap) {
+        float emptyangle = PIE_SWEEP / 16;
+        float sweep = (float) (PIE_SWEEP - 2 * emptyangle) / items.size();
+        float angle = centerAngle - PIE_SWEEP / 2 + emptyangle + sweep / 2;
+        // check if we have custom geometry
+        // first item we find triggers custom sweep for all
+        // this allows us to re-use the path
+        for (PieItem item : items) {
+            if (item.getCenter() >= 0) {
+                sweep = item.getSweep();
+                break;
+            }
+        }
+        Path path = makeSlice(getDegrees(0) - gap, getDegrees(sweep) + gap,
+                outer, inner, mCenter);
+        for (PieItem item : items) {
+            // shared between items
+            item.setPath(path);
+            if (item.getCenter() >= 0) {
+                angle = item.getCenter();
+            }
+            int w = item.getIntrinsicWidth();
+            int h = item.getIntrinsicHeight();
+            // move views to outer border
+            int r = inner + (outer - inner) * 2 / 3;
+            int x = (int) (r * Math.cos(angle));
+            int y = mCenter.y - (int) (r * Math.sin(angle)) - h / 2;
+            x = mCenter.x + x - w / 2;
+            item.setBounds(x, y, x + w, y + h);
+            float itemstart = angle - sweep / 2;
+            item.setGeometry(itemstart, sweep, inner, outer);
+            if (item.hasItems()) {
+                layoutItems(item.getItems(), angle, inner,
+                        outer + mRadiusInc / 2, gap);
+            }
+            angle += sweep;
+        }
+    }
+
+    private Path makeSlice(float start, float end, int outer, int inner, Point center) {
+        RectF bb =
+                new RectF(center.x - outer, center.y - outer, center.x + outer,
+                        center.y + outer);
+        RectF bbi =
+                new RectF(center.x - inner, center.y - inner, center.x + inner,
+                        center.y + inner);
+        Path path = new Path();
+        path.arcTo(bb, start, end - start, true);
+        path.arcTo(bbi, end, start - end);
+        path.close();
+        return path;
+    }
+
+    /**
+     * converts a
+     * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock)
+     * @return skia angle
+     */
+    private float getDegrees(double angle) {
+        return (float) (360 - 180 * angle / Math.PI);
+    }
+
+    private void startFadeOut() {
+        mOverlay.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                deselect();
+                show(false);
+                mOverlay.setAlpha(1);
+                super.onAnimationEnd(animation);
+            }
+        }).setDuration(PIE_SELECT_FADE_DURATION);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        float alpha = 1;
+        if (mXFade != null) {
+            alpha = mXFade.getValue();
+        } else if (mFadeIn != null) {
+            alpha = mFadeIn.getValue();
+        }
+        int state = canvas.save();
+        if (mFadeIn != null) {
+            float sf = 0.9f + alpha * 0.1f;
+            canvas.scale(sf, sf, mCenter.x, mCenter.y);
+        }
+        drawFocus(canvas);
+        if (mState == STATE_FINISHING) {
+            canvas.restoreToCount(state);
+            return;
+        }
+        if ((mOpenItem == null) || (mXFade != null)) {
+            // draw base menu
+            for (PieItem item : mItems) {
+                drawItem(canvas, item, alpha);
+            }
+        }
+        if (mOpenItem != null) {
+            for (PieItem inner : mOpenItem.getItems()) {
+                drawItem(canvas, inner, (mXFade != null) ? (1 - 0.5f * alpha) : 1);
+            }
+        }
+        canvas.restoreToCount(state);
+    }
+
+    private void drawItem(Canvas canvas, PieItem item, float alpha) {
+        if (mState == STATE_PIE) {
+            if (item.getPath() != null) {
+                if (item.isSelected()) {
+                    Paint p = mSelectedPaint;
+                    int state = canvas.save();
+                    float r = getDegrees(item.getStartAngle());
+                    canvas.rotate(r, mCenter.x, mCenter.y);
+                    canvas.drawPath(item.getPath(), p);
+                    canvas.restoreToCount(state);
+                }
+                alpha = alpha * (item.isEnabled() ? 1 : 0.3f);
+                // draw the item view
+                item.setAlpha(alpha);
+                item.draw(canvas);
+            }
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent evt) {
+        float x = evt.getX();
+        float y = evt.getY();
+        int action = evt.getActionMasked();
+        PointF polar = getPolar(x, y, !(mTapMode));
+        if (MotionEvent.ACTION_DOWN == action) {
+            mDown.x = (int) evt.getX();
+            mDown.y = (int) evt.getY();
+            mOpening = false;
+            if (mTapMode) {
+                PieItem item = findItem(polar);
+                if ((item != null) && (mCurrentItem != item)) {
+                    mState = STATE_PIE;
+                    onEnter(item);
+                }
+            } else {
+                setCenter((int) x, (int) y);
+                show(true);
+            }
+            return true;
+        } else if (MotionEvent.ACTION_UP == action) {
+            if (isVisible()) {
+                PieItem item = mCurrentItem;
+                if (mTapMode) {
+                    item = findItem(polar);
+                    if (item != null && mOpening) {
+                        mOpening = false;
+                        return true;
+                    }
+                }
+                if (item == null) {
+                    mTapMode = false;
+                    show(false);
+                } else if (!mOpening
+                        && !item.hasItems()) {
+                    item.performClick();
+                    startFadeOut();
+                    mTapMode = false;
+                }
+                return true;
+            }
+        } else if (MotionEvent.ACTION_CANCEL == action) {
+            if (isVisible() || mTapMode) {
+                show(false);
+            }
+            deselect();
+            return false;
+        } else if (MotionEvent.ACTION_MOVE == action) {
+            if (polar.y < mRadius) {
+                if (mOpenItem != null) {
+                    mOpenItem = null;
+                } else {
+                    deselect();
+                }
+                return false;
+            }
+            PieItem item = findItem(polar);
+            boolean moved = hasMoved(evt);
+            if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) {
+                // only select if we didn't just open or have moved past slop
+                mOpening = false;
+                if (moved) {
+                    // switch back to swipe mode
+                    mTapMode = false;
+                }
+                onEnter(item);
+            }
+        }
+        return false;
+    }
+
+    private boolean hasMoved(MotionEvent e) {
+        return mTouchSlopSquared < (e.getX() - mDown.x) * (e.getX() - mDown.x)
+                + (e.getY() - mDown.y) * (e.getY() - mDown.y);
+    }
+
+    /**
+     * enter a slice for a view
+     * updates model only
+     * @param item
+     */
+    private void onEnter(PieItem item) {
+        if (mCurrentItem != null) {
+            mCurrentItem.setSelected(false);
+        }
+        if (item != null && item.isEnabled()) {
+            item.setSelected(true);
+            mCurrentItem = item;
+            if ((mCurrentItem != mOpenItem) && mCurrentItem.hasItems()) {
+                openCurrentItem();
+            }
+        } else {
+            mCurrentItem = null;
+        }
+    }
+
+    private void deselect() {
+        if (mCurrentItem != null) {
+            mCurrentItem.setSelected(false);
+        }
+        if (mOpenItem != null) {
+            mOpenItem = null;
+        }
+        mCurrentItem = null;
+    }
+
+    private void openCurrentItem() {
+        if ((mCurrentItem != null) && mCurrentItem.hasItems()) {
+            mCurrentItem.setSelected(false);
+            mOpenItem = mCurrentItem;
+            mOpening = true;
+            mXFade = new LinearAnimation(1, 0);
+            mXFade.setDuration(PIE_XFADE_DURATION);
+            mXFade.setAnimationListener(new AnimationListener() {
+                @Override
+                public void onAnimationStart(Animation animation) {
+                }
+
+                @Override
+                public void onAnimationEnd(Animation animation) {
+                    mXFade = null;
+                }
+
+                @Override
+                public void onAnimationRepeat(Animation animation) {
+                }
+            });
+            mXFade.startNow();
+            mOverlay.startAnimation(mXFade);
+        }
+    }
+
+    private PointF getPolar(float x, float y, boolean useOffset) {
+        PointF res = new PointF();
+        // get angle and radius from x/y
+        res.x = (float) Math.PI / 2;
+        x = x - mCenter.x;
+        y = mCenter.y - y;
+        res.y = (float) Math.sqrt(x * x + y * y);
+        if (x != 0) {
+            res.x = (float) Math.atan2(y,  x);
+            if (res.x < 0) {
+                res.x = (float) (2 * Math.PI + res.x);
+            }
+        }
+        res.y = res.y + (useOffset ? mTouchOffset : 0);
+        return res;
+    }
+
+    /**
+     * @param polar x: angle, y: dist
+     * @return the item at angle/dist or null
+     */
+    private PieItem findItem(PointF polar) {
+        // find the matching item:
+        List<PieItem> items = (mOpenItem != null) ? mOpenItem.getItems() : mItems;
+        for (PieItem item : items) {
+            if (inside(polar, item)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    private boolean inside(PointF polar, PieItem item) {
+        return (item.getInnerRadius() < polar.y)
+                && (item.getStartAngle() < polar.x)
+                && (item.getStartAngle() + item.getSweep() > polar.x)
+                && (!mTapMode || (item.getOuterRadius() > polar.y));
+    }
+
+    @Override
+    public boolean handlesTouch() {
+        return true;
+    }
+
+    // focus specific code
+
+    public void setBlockFocus(boolean blocked) {
+        mBlockFocus = blocked;
+        if (blocked) {
+            clear();
+        }
+    }
+
+    public void setFocus(int x, int y) {
+        mFocusX = x;
+        mFocusY = y;
+        setCircle(mFocusX, mFocusY);
+    }
+
+    public void alignFocus(int x, int y) {
+        mOverlay.removeCallbacks(mDisappear);
+        mAnimation.cancel();
+        mAnimation.reset();
+        mFocusX = x;
+        mFocusY = y;
+        mDialAngle = DIAL_HORIZONTAL;
+        setCircle(x, y);
+        mFocused = false;
+    }
+
+    public int getSize() {
+        return 2 * mCircleSize;
+    }
+
+    private int getRandomRange() {
+        return (int) (-60 + 120 * Math.random());
+    }
+
+    @Override
+    public void layout(int l, int t, int r, int b) {
+        super.layout(l, t, r, b);
+        mCenterX = (r - l) / 2;
+        mCenterY = (b - t) / 2;
+        mFocusX = mCenterX;
+        mFocusY = mCenterY;
+        setCircle(mFocusX, mFocusY);
+        if (isVisible() && mState == STATE_PIE) {
+            setCenter(mCenterX, mCenterY);
+            layoutPie();
+        }
+    }
+
+    private void setCircle(int cx, int cy) {
+        mCircle.set(cx - mCircleSize, cy - mCircleSize,
+                cx + mCircleSize, cy + mCircleSize);
+        mDial.set(cx - mCircleSize + mInnerOffset, cy - mCircleSize + mInnerOffset,
+                cx + mCircleSize - mInnerOffset, cy + mCircleSize - mInnerOffset);
+    }
+
+    public void drawFocus(Canvas canvas) {
+        if (mBlockFocus) {
+            return;
+        }
+        mFocusPaint.setStrokeWidth(mOuterStroke);
+        canvas.drawCircle((float) mFocusX, (float) mFocusY, (float) mCircleSize, mFocusPaint);
+        if (mState == STATE_PIE) {
+            return;
+        }
+        int color = mFocusPaint.getColor();
+        if (mState == STATE_FINISHING) {
+            mFocusPaint.setColor(mFocused ? mSuccessColor : mFailColor);
+        }
+        mFocusPaint.setStrokeWidth(mInnerStroke);
+        drawLine(canvas, mDialAngle, mFocusPaint);
+        drawLine(canvas, mDialAngle + 45, mFocusPaint);
+        drawLine(canvas, mDialAngle + 180, mFocusPaint);
+        drawLine(canvas, mDialAngle + 225, mFocusPaint);
+        canvas.save();
+        // rotate the arc instead of its offset to better use framework's shape caching
+        canvas.rotate(mDialAngle, mFocusX, mFocusY);
+        canvas.drawArc(mDial, 0, 45, false, mFocusPaint);
+        canvas.drawArc(mDial, 180, 45, false, mFocusPaint);
+        canvas.restore();
+        mFocusPaint.setColor(color);
+    }
+
+    private void drawLine(Canvas canvas, int angle, Paint p) {
+        convertCart(angle, mCircleSize - mInnerOffset, mPoint1);
+        convertCart(angle, mCircleSize - mInnerOffset + mInnerOffset / 3, mPoint2);
+        canvas.drawLine(mPoint1.x + mFocusX, mPoint1.y + mFocusY,
+                mPoint2.x + mFocusX, mPoint2.y + mFocusY, p);
+    }
+
+    private static void convertCart(int angle, int radius, Point out) {
+        double a = 2 * Math.PI * (angle % 360) / 360;
+        out.x = (int) (radius * Math.cos(a) + 0.5);
+        out.y = (int) (radius * Math.sin(a) + 0.5);
+    }
+
+    @Override
+    public void showStart() {
+        if (mState == STATE_PIE) {
+            return;
+        }
+        cancelFocus();
+        mStartAnimationAngle = 67;
+        int range = getRandomRange();
+        startAnimation(SCALING_UP_TIME,
+                false, mStartAnimationAngle, mStartAnimationAngle + range);
+        mState = STATE_FOCUSING;
+    }
+
+    @Override
+    public void showSuccess(boolean timeout) {
+        if (mState == STATE_FOCUSING) {
+            startAnimation(SCALING_DOWN_TIME,
+                    timeout, mStartAnimationAngle);
+            mState = STATE_FINISHING;
+            mFocused = true;
+        }
+    }
+
+    @Override
+    public void showFail(boolean timeout) {
+        if (mState == STATE_FOCUSING) {
+            startAnimation(SCALING_DOWN_TIME,
+                    timeout, mStartAnimationAngle);
+            mState = STATE_FINISHING;
+            mFocused = false;
+        }
+    }
+
+    private void cancelFocus() {
+        mFocusCancelled = true;
+        mOverlay.removeCallbacks(mDisappear);
+        if (mAnimation != null) {
+            mAnimation.cancel();
+        }
+        mFocusCancelled = false;
+        mFocused = false;
+        mState = STATE_IDLE;
+    }
+
+    @Override
+    public void clear() {
+        if (mState == STATE_PIE) {
+            return;
+        }
+        cancelFocus();
+        mOverlay.post(mDisappear);
+    }
+
+    private void startAnimation(long duration, boolean timeout,
+                                float toScale) {
+        startAnimation(duration, timeout, mDialAngle,
+                toScale);
+    }
+
+    private void startAnimation(long duration, boolean timeout,
+                                float fromScale, float toScale) {
+        setVisible(true);
+        mAnimation.reset();
+        mAnimation.setDuration(duration);
+        mAnimation.setScale(fromScale, toScale);
+        mAnimation.setAnimationListener(timeout ? mEndAction : null);
+        mOverlay.startAnimation(mAnimation);
+        update();
+    }
+
+    private class EndAction implements Animation.AnimationListener {
+        @Override
+        public void onAnimationEnd(Animation animation) {
+            // Keep the focus indicator for some time.
+            if (!mFocusCancelled) {
+                mOverlay.postDelayed(mDisappear, DISAPPEAR_TIMEOUT);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation) {
+        }
+
+        @Override
+        public void onAnimationStart(Animation animation) {
+        }
+    }
+
+    private class Disappear implements Runnable {
+        @Override
+        public void run() {
+            if (mState == STATE_PIE) {
+                return;
+            }
+            setVisible(false);
+            mFocusX = mCenterX;
+            mFocusY = mCenterY;
+            mState = STATE_IDLE;
+            setCircle(mFocusX, mFocusY);
+            mFocused = false;
+        }
+    }
+
+    private class ScaleAnimation extends Animation {
+        private float mFrom = 1f;
+        private float mTo = 1f;
+
+        public ScaleAnimation() {
+            setFillAfter(true);
+        }
+
+        public void setScale(float from, float to) {
+            mFrom = from;
+            mTo = to;
+        }
+
+        @Override
+        protected void applyTransformation(float interpolatedTime, Transformation t) {
+            mDialAngle = (int) (mFrom + (mTo - mFrom) * interpolatedTime);
+        }
+    }
+
+
+    private class LinearAnimation extends Animation {
+        private float mFrom;
+        private float mTo;
+        private float mValue;
+
+        public LinearAnimation(float from, float to) {
+            setFillAfter(true);
+            setInterpolator(new LinearInterpolator());
+            mFrom = from;
+            mTo = to;
+        }
+
+        public float getValue() {
+            return mValue;
+        }
+
+        @Override
+        protected void applyTransformation(float interpolatedTime, Transformation t) {
+            mValue = (mFrom + (mTo - mFrom) * interpolatedTime);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/README.txt b/src/com/android/messaging/ui/mediapicker/camerafocus/README.txt
new file mode 100644
index 0000000..ed4e783
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/README.txt
@@ -0,0 +1,3 @@
+The files in this package were copied from the android-4.4.4_r1 branch of ASOP from the folders
+com/android/camera/ and com/android/camera/ui from files with the same name.  Some modifications
+have been made to remove unneeded features and adjust to our needs.
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/mediapicker/camerafocus/RenderOverlay.java b/src/com/android/messaging/ui/mediapicker/camerafocus/RenderOverlay.java
new file mode 100644
index 0000000..95cddc4
--- /dev/null
+++ b/src/com/android/messaging/ui/mediapicker/camerafocus/RenderOverlay.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker.camerafocus;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RenderOverlay extends FrameLayout {
+
+    interface Renderer {
+
+        public boolean handlesTouch();
+        public boolean onTouchEvent(MotionEvent evt);
+        public void setOverlay(RenderOverlay overlay);
+        public void layout(int left, int top, int right, int bottom);
+        public void draw(Canvas canvas);
+
+    }
+
+    private RenderView mRenderView;
+    private List<Renderer> mClients;
+
+    // reverse list of touch clients
+    private List<Renderer> mTouchClients;
+    private int[] mPosition = new int[2];
+
+    public RenderOverlay(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mRenderView = new RenderView(context);
+        addView(mRenderView, new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+        mClients = new ArrayList<Renderer>(10);
+        mTouchClients = new ArrayList<Renderer>(10);
+        setWillNotDraw(false);
+
+        addRenderer(new PieRenderer(context));
+    }
+
+    public PieRenderer getPieRenderer() {
+        for (Renderer renderer : mClients) {
+            if (renderer instanceof PieRenderer) {
+                return (PieRenderer) renderer;
+            }
+        }
+        return null;
+    }
+
+    public void addRenderer(Renderer renderer) {
+        mClients.add(renderer);
+        renderer.setOverlay(this);
+        if (renderer.handlesTouch()) {
+            mTouchClients.add(0, renderer);
+        }
+        renderer.layout(getLeft(), getTop(), getRight(), getBottom());
+    }
+
+    public void addRenderer(int pos, Renderer renderer) {
+        mClients.add(pos, renderer);
+        renderer.setOverlay(this);
+        renderer.layout(getLeft(), getTop(), getRight(), getBottom());
+    }
+
+    public void remove(Renderer renderer) {
+        mClients.remove(renderer);
+        renderer.setOverlay(null);
+    }
+
+    public int getClientSize() {
+        return mClients.size();
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent m) {
+        return false;
+    }
+
+    public boolean directDispatchTouch(MotionEvent m, Renderer target) {
+        mRenderView.setTouchTarget(target);
+        boolean res = super.dispatchTouchEvent(m);
+        mRenderView.setTouchTarget(null);
+        return res;
+    }
+
+    private void adjustPosition() {
+        getLocationInWindow(mPosition);
+    }
+
+    public int getWindowPositionX() {
+        return mPosition[0];
+    }
+
+    public int getWindowPositionY() {
+        return mPosition[1];
+    }
+
+    public void update() {
+        mRenderView.invalidate();
+    }
+
+    private class RenderView extends View {
+
+        private Renderer mTouchTarget;
+
+        public RenderView(Context context) {
+            super(context);
+            setWillNotDraw(false);
+        }
+
+        public void setTouchTarget(Renderer target) {
+            mTouchTarget = target;
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent evt) {
+            if (mTouchTarget != null) {
+                return mTouchTarget.onTouchEvent(evt);
+            }
+            if (mTouchClients != null) {
+                boolean res = false;
+                for (Renderer client : mTouchClients) {
+                    res |= client.onTouchEvent(evt);
+                }
+                return res;
+            }
+            return false;
+        }
+
+        @Override
+        public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+            adjustPosition();
+            super.onLayout(changed, left,  top, right, bottom);
+            if (mClients == null) {
+                return;
+            }
+            for (Renderer renderer : mClients) {
+                renderer.layout(left, top, right, bottom);
+            }
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            if (mClients == null) {
+                return;
+            }
+            boolean redraw = false;
+            for (Renderer renderer : mClients) {
+                renderer.draw(canvas);
+                redraw = redraw || ((OverlayRenderer) renderer).isVisible();
+            }
+            if (redraw) {
+                invalidate();
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/photoviewer/BuglePhotoBitmapLoader.java b/src/com/android/messaging/ui/photoviewer/BuglePhotoBitmapLoader.java
new file mode 100644
index 0000000..9911456
--- /dev/null
+++ b/src/com/android/messaging/ui/photoviewer/BuglePhotoBitmapLoader.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.photoviewer;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.support.rastermill.FrameSequenceDrawable;
+import androidx.loader.content.AsyncTaskLoader;
+
+import com.android.ex.photo.PhotoViewController;
+import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface;
+import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.util.ImageUtils;
+
+/**
+ * Loader for the bitmap of a photo.
+ */
+public class BuglePhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
+        implements PhotoBitmapLoaderInterface {
+    private String mPhotoUri;
+    private ImageResource mImageResource;
+    // The drawable that is currently "in use" and being presented to the user. This drawable
+    // should never exist without the image resource backing it.
+    private Drawable mDrawable;
+
+    public BuglePhotoBitmapLoader(Context context, String photoUri) {
+        super(context);
+        mPhotoUri = photoUri;
+    }
+
+    @Override
+    public void setPhotoUri(String photoUri) {
+        mPhotoUri = photoUri;
+    }
+
+    @Override
+    public BitmapResult loadInBackground() {
+        final BitmapResult result = new BitmapResult();
+        final Context context = getContext();
+        if (context != null && mPhotoUri != null) {
+            final ImageRequestDescriptor descriptor =
+                    new UriImageRequestDescriptor(Uri.parse(mPhotoUri),
+                            PhotoViewController.sMaxPhotoSize, PhotoViewController.sMaxPhotoSize,
+                            true /* allowCompression */, false /* isStatic */,
+                            false /* cropToCircle */,
+                            ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                            ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */);
+            final MediaRequest<ImageResource> imageRequest =
+                    descriptor.buildSyncMediaRequest(context);
+            final ImageResource imageResource =
+                    MediaResourceManager.get().requestMediaResourceSync(imageRequest);
+            if (imageResource != null) {
+                setImageResource(imageResource);
+                result.status = BitmapResult.STATUS_SUCCESS;
+                result.drawable = mImageResource.getDrawable(context.getResources());
+            } else {
+                releaseImageResource();
+                result.status = BitmapResult.STATUS_EXCEPTION;
+            }
+        } else {
+            result.status = BitmapResult.STATUS_EXCEPTION;
+        }
+        return result;
+    }
+
+    /**
+     * Called when there is new data to deliver to the client. The super class will take care of
+     * delivering it; the implementation here just adds a little more logic.
+     */
+    @Override
+    public void deliverResult(BitmapResult result) {
+        final Drawable drawable = result != null ? result.drawable : null;
+        if (isReset()) {
+            // An async query came in while the loader is stopped. We don't need the result.
+            releaseDrawable(drawable);
+            return;
+        }
+
+        // We are now going to display this drawable so set to mDrawable
+        mDrawable = drawable;
+
+        if (isStarted()) {
+            // If the Loader is currently started, we can immediately deliver its results.
+            super.deliverResult(result);
+        }
+    }
+
+    /**
+     * Handles a request to start the Loader.
+     */
+    @Override
+    protected void onStartLoading() {
+        if (mDrawable != null) {
+            // If we currently have a result available, deliver it
+            // immediately.
+            final BitmapResult result = new BitmapResult();
+            result.status = BitmapResult.STATUS_SUCCESS;
+            result.drawable = mDrawable;
+            deliverResult(result);
+        }
+
+        if (takeContentChanged() || (mImageResource == null)) {
+            // If the data has changed since the last time it was loaded
+            // or is not currently available, start a load.
+            forceLoad();
+        }
+    }
+
+    /**
+     * Handles a request to stop the Loader.
+     */
+    @Override
+    protected void onStopLoading() {
+        // Attempt to cancel the current load task if possible.
+        cancelLoad();
+    }
+
+    /**
+     * Handles a request to cancel a load.
+     */
+    @Override
+    public void onCanceled(BitmapResult result) {
+        super.onCanceled(result);
+
+        // At this point we can release the resources associated with 'drawable' if needed.
+        if (result != null) {
+            releaseDrawable(result.drawable);
+        }
+    }
+
+    /**
+     * Handles a request to completely reset the Loader.
+     */
+    @Override
+    protected void onReset() {
+        super.onReset();
+
+        // Ensure the loader is stopped
+        onStopLoading();
+
+        releaseImageResource();
+    }
+
+    private void releaseDrawable(Drawable drawable) {
+        if (drawable != null && drawable instanceof FrameSequenceDrawable
+                && !((FrameSequenceDrawable) drawable).isDestroyed()) {
+            ((FrameSequenceDrawable) drawable).destroy();
+        }
+
+    }
+
+    private void setImageResource(final ImageResource resource) {
+        if (mImageResource != resource) {
+            // Clear out any information for what is currently used
+            releaseImageResource();
+            mImageResource = resource;
+            // No need to add ref since a ref is already reserved as a result of
+            // requestMediaResourceSync.
+        }
+    }
+
+    private void releaseImageResource() {
+        // If we are getting rid of the imageResource backing the drawable, we must also
+        // destroy the drawable before releasing it.
+        releaseDrawable(mDrawable);
+        mDrawable = null;
+
+        if (mImageResource != null) {
+            mImageResource.release();
+        }
+        mImageResource = null;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/ui/photoviewer/BuglePhotoPageAdapter.java b/src/com/android/messaging/ui/photoviewer/BuglePhotoPageAdapter.java
new file mode 100644
index 0000000..c19070b
--- /dev/null
+++ b/src/com/android/messaging/ui/photoviewer/BuglePhotoPageAdapter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.photoviewer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.ex.photo.adapters.PhotoPagerAdapter;
+import com.android.ex.photo.fragments.PhotoViewFragment;
+
+public class BuglePhotoPageAdapter extends PhotoPagerAdapter {
+
+    public BuglePhotoPageAdapter(Context context, FragmentManager fm, Cursor c, float maxScale,
+            boolean thumbsFullScreen) {
+        super(context, fm, c, maxScale, thumbsFullScreen);
+    }
+
+    @Override
+    protected PhotoViewFragment createPhotoViewFragment(Intent intent, int position,
+            boolean onlyShowSpinner) {
+        return BuglePhotoViewFragment.newInstance(intent, position, onlyShowSpinner);
+    }
+}
diff --git a/src/com/android/messaging/ui/photoviewer/BuglePhotoViewActivity.java b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewActivity.java
new file mode 100644
index 0000000..1924a96
--- /dev/null
+++ b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.photoviewer;
+
+import com.android.ex.photo.PhotoViewActivity;
+import com.android.ex.photo.PhotoViewController;
+
+/**
+ * Activity to display the conversation images in full-screen. Most of the customization is in
+ * {@link BuglePhotoViewController}.
+ */
+public class BuglePhotoViewActivity extends PhotoViewActivity {
+    @Override
+    public PhotoViewController createController() {
+        return new BuglePhotoViewController(this);
+    }
+}
diff --git a/src/com/android/messaging/ui/photoviewer/BuglePhotoViewController.java b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewController.java
new file mode 100644
index 0000000..0bb8f11
--- /dev/null
+++ b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewController.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.photoviewer;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.fragment.app.FragmentManager;
+import androidx.loader.content.Loader;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ShareActionProvider;
+import android.widget.Toast;
+
+import com.android.ex.photo.PhotoViewController;
+import com.android.ex.photo.adapters.PhotoPagerAdapter;
+import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.ConversationImagePartsView.PhotoViewQuery;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.ui.conversation.ConversationFragment;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+
+/**
+ * Customizations for the photoviewer to display conversation images in full screen.
+ */
+public class BuglePhotoViewController extends PhotoViewController {
+    private ShareActionProvider mShareActionProvider;
+    private MenuItem mShareItem;
+    private MenuItem mSaveItem;
+
+    public BuglePhotoViewController(final ActivityInterface activity) {
+        super(activity);
+    }
+
+    @Override
+    public Loader<BitmapResult> onCreateBitmapLoader(
+            final int id, final Bundle args, final String uri) {
+        switch (id) {
+            case BITMAP_LOADER_AVATAR:
+            case BITMAP_LOADER_THUMBNAIL:
+            case BITMAP_LOADER_PHOTO:
+                return new BuglePhotoBitmapLoader(getActivity().getContext(), uri);
+            default:
+                LogUtil.e(LogUtil.BUGLE_TAG,
+                        "Photoviewer unable to open bitmap loader with unknown id: " + id);
+                return null;
+        }
+    }
+
+    @Override
+    public void updateActionBar() {
+        final Cursor cursor = getCursorAtProperPosition();
+
+        if (mSaveItem == null || cursor == null) {
+            // Load not finished, called from framework code before ready
+            return;
+        }
+        // Show the name as the title
+        mActionBarTitle = cursor.getString(PhotoViewQuery.INDEX_SENDER_FULL_NAME);
+        if (TextUtils.isEmpty(mActionBarTitle)) {
+            // If the name is not known, fall back to the phone number
+            mActionBarTitle = cursor.getString(PhotoViewQuery.INDEX_DISPLAY_DESTINATION);
+        }
+
+        // Show the timestamp as the subtitle
+        final long receivedTimestamp = cursor.getLong(PhotoViewQuery.INDEX_RECEIVED_TIMESTAMP);
+        mActionBarSubtitle = Dates.getMessageTimeString(receivedTimestamp).toString();
+
+        setActionBarTitles(getActivity().getActionBarInterface());
+        mSaveItem.setVisible(!isTempFile());
+
+        updateShareActionProvider();
+    }
+
+    private void updateShareActionProvider() {
+        final PhotoPagerAdapter adapter = getAdapter();
+        final Cursor cursor = getCursorAtProperPosition();
+        if (mShareActionProvider == null || mShareItem == null || adapter == null ||
+                cursor == null) {
+            // Not enough stuff loaded to update the share action
+            return;
+        }
+        final String photoUri = adapter.getPhotoUri(cursor);
+        if (isTempFile()) {
+            mShareItem.setVisible(false);
+            return;
+        }
+        final String contentType = adapter.getContentType(cursor);
+
+        final Intent shareIntent = new Intent();
+        shareIntent.setAction(Intent.ACTION_SEND);
+        shareIntent.setType(contentType);
+        shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(photoUri));
+        mShareActionProvider.setShareIntent(shareIntent);
+        mShareItem.setVisible(true);
+    }
+
+    /**
+     * Checks whether the current photo is a temp file.  A temp file can be deleted at any time, so
+     * we need to disable share and save options because the file may no longer be there.
+     */
+    private boolean isTempFile() {
+        final Cursor cursor = getCursorAtProperPosition();
+        final Uri photoUri = Uri.parse(getAdapter().getPhotoUri(cursor));
+        return MediaScratchFileProvider.isMediaScratchSpaceUri(photoUri);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        ((Activity) getActivity()).getMenuInflater().inflate(R.menu.photo_view_menu, menu);
+
+        // Get the ShareActionProvider
+        mShareItem = menu.findItem(R.id.action_share);
+        mShareActionProvider = (ShareActionProvider) mShareItem.getActionProvider();
+        updateShareActionProvider();
+
+        mSaveItem = menu.findItem(R.id.action_save);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        return !mIsEmpty;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        if (item.getItemId() == R.id.action_save) {
+            if (OsUtil.hasStoragePermission()) {
+                final PhotoPagerAdapter adapter = getAdapter();
+                final Cursor cursor = getCursorAtProperPosition();
+                if (cursor == null) {
+                    final Context context = getActivity().getContext();
+                    final String error = context.getResources().getQuantityString(
+                            R.plurals.attachment_save_error, 1, 1);
+                    Toast.makeText(context, error, Toast.LENGTH_SHORT).show();
+                    return true;
+                }
+                final String photoUri = adapter.getPhotoUri(cursor);
+                new ConversationFragment.SaveAttachmentTask(((Activity) getActivity()),
+                        Uri.parse(photoUri), adapter.getContentType(cursor)).executeOnThreadPool();
+            } else {
+                ((Activity)getActivity()).requestPermissions(
+                        new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
+            }
+            return true;
+        } else {
+            return super.onOptionsItemSelected(item);
+        }
+    }
+
+    @Override
+    public PhotoPagerAdapter createPhotoPagerAdapter(final Context context,
+            final FragmentManager fm, final Cursor c, final float maxScale) {
+        return new BuglePhotoPageAdapter(context, fm, c, maxScale, mDisplayThumbsFullScreen);
+    }
+}
diff --git a/src/com/android/messaging/ui/photoviewer/BuglePhotoViewFragment.java b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewFragment.java
new file mode 100644
index 0000000..a6293dc
--- /dev/null
+++ b/src/com/android/messaging/ui/photoviewer/BuglePhotoViewFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.photoviewer;
+
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.support.rastermill.FrameSequenceDrawable;
+import androidx.loader.content.Loader;
+
+import com.android.ex.photo.PhotoViewCallbacks;
+import com.android.ex.photo.fragments.PhotoViewFragment;
+import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult;
+
+public class BuglePhotoViewFragment extends PhotoViewFragment {
+
+    /** Public no-arg constructor for allowing the framework to handle orientation changes */
+    public BuglePhotoViewFragment() {
+        // Do nothing.
+    }
+
+    public static PhotoViewFragment newInstance(Intent intent, int position,
+            boolean onlyShowSpinner) {
+        final PhotoViewFragment f = new BuglePhotoViewFragment();
+        initializeArguments(intent, position, onlyShowSpinner, f);
+        return f;
+    }
+
+    @Override
+    public void onLoadFinished(Loader<BitmapResult> loader, BitmapResult result) {
+        super.onLoadFinished(loader, result);
+        // Need to check for the first time when we load the photos
+        if (PhotoViewCallbacks.BITMAP_LOADER_PHOTO == loader.getId()
+                && result.status == BitmapResult.STATUS_SUCCESS
+                && mCallback.isFragmentActive(this)) {
+            startGif();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        startGif();
+    }
+
+    @Override
+    public void onPause() {
+        stopGif();
+        super.onPause();
+    }
+
+    @Override
+    public void onViewActivated() {
+        super.onViewActivated();
+        startGif();
+    }
+
+    @Override
+    public void resetViews() {
+        super.resetViews();
+        stopGif();
+    }
+
+    private void stopGif() {
+        final Drawable drawable = getDrawable();
+        if (drawable != null && drawable instanceof FrameSequenceDrawable) {
+            ((FrameSequenceDrawable) drawable).stop();
+        }
+    }
+
+    private void startGif() {
+        final Drawable drawable = getDrawable();
+        if (drawable != null && drawable instanceof FrameSequenceDrawable) {
+            ((FrameSequenceDrawable) drawable).start();
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/AccessibilityUtil.java b/src/com/android/messaging/util/AccessibilityUtil.java
new file mode 100644
index 0000000..788f482
--- /dev/null
+++ b/src/com/android/messaging/util/AccessibilityUtil.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.res.Resources;
+import androidx.core.view.accessibility.AccessibilityEventCompat;
+import androidx.core.view.accessibility.AccessibilityRecordCompat;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+
+import javax.annotation.Nullable;
+
+public class AccessibilityUtil {
+    public static String sContentDescriptionDivider;
+
+    public static boolean isTouchExplorationEnabled(final Context context) {
+        final AccessibilityManager accessibilityManager = (AccessibilityManager)
+                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        return accessibilityManager.isTouchExplorationEnabled();
+    }
+
+    public static StringBuilder appendContentDescription(final Context context,
+            final StringBuilder contentDescription, final String val) {
+        if (sContentDescriptionDivider == null) {
+            sContentDescriptionDivider =
+                    context.getResources().getString(R.string.enumeration_comma);
+        }
+        if (contentDescription.length() != 0) {
+            contentDescription.append(sContentDescriptionDivider);
+        }
+        contentDescription.append(val);
+        return contentDescription;
+    }
+
+    public static void announceForAccessibilityCompat(
+            final View view, @Nullable final AccessibilityManager accessibilityManager,
+            final int textResourceId) {
+        final String text = Factory.get().getApplicationContext().getResources().getString(
+                textResourceId);
+        announceForAccessibilityCompat(view, accessibilityManager, text);
+    }
+
+    public static void announceForAccessibilityCompat(
+            final View view, @Nullable AccessibilityManager accessibilityManager,
+            final CharSequence text) {
+        final Context context = view.getContext().getApplicationContext();
+        if (accessibilityManager == null) {
+            accessibilityManager = (AccessibilityManager) context.getSystemService(
+                    Context.ACCESSIBILITY_SERVICE);
+        }
+
+        if (!accessibilityManager.isEnabled()) {
+            return;
+        }
+
+        // Jelly Bean added support for speaking text verbatim
+        final int eventType = OsUtil.isAtLeastJB() ? AccessibilityEvent.TYPE_ANNOUNCEMENT
+                : AccessibilityEvent.TYPE_VIEW_FOCUSED;
+
+        // Construct an accessibility event with the minimum recommended
+        // attributes. An event without a class name or package may be dropped.
+        final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+        event.getText().add(text);
+        event.setEnabled(view.isEnabled());
+        event.setClassName(view.getClass().getName());
+        event.setPackageName(context.getPackageName());
+
+        // JellyBean MR1 requires a source view to set the window ID.
+        final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
+        record.setSource(view);
+
+        // Sends the event directly through the accessibility manager. If we only supported SDK 14+
+        // we could have done:
+        // getParent().requestSendAccessibilityEvent(this, event);
+        accessibilityManager.sendAccessibilityEvent(event);
+    }
+
+    /**
+     * Check to see if the current layout is Right-to-Left. This check is only supported for
+     * API 17+.
+     * For earlier versions, this method will just return false.
+     * @return boolean Boolean indicating whether the currently locale is RTL.
+     */
+    public static boolean isLayoutRtl(final View view) {
+        if (OsUtil.isAtLeastJB_MR1()) {
+            return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection();
+        } else {
+            return false;
+        }
+    }
+
+    public static String getVocalizedPhoneNumber(final Resources res, final String phoneNumber) {
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return "";
+        }
+        final StringBuilder vocalizedPhoneNumber = new StringBuilder();
+        for (final char c : phoneNumber.toCharArray()) {
+            getVocalizedNumber(res, c, vocalizedPhoneNumber);
+        }
+        return vocalizedPhoneNumber.toString();
+    }
+
+    public static void getVocalizedNumber(final Resources res, final char c,
+            final StringBuilder builder) {
+        switch (c) {
+            case '0':
+                builder.append(res.getString(R.string.content_description_for_number_zero));
+                builder.append(" ");
+                return;
+            case '1':
+                builder.append(res.getString(R.string.content_description_for_number_one));
+                builder.append(" ");
+                return;
+            case '2':
+                builder.append(res.getString(R.string.content_description_for_number_two));
+                builder.append(" ");
+                return;
+            case '3':
+                builder.append(res.getString(R.string.content_description_for_number_three));
+                builder.append(" ");
+                return;
+            case '4':
+                builder.append(res.getString(R.string.content_description_for_number_four));
+                builder.append(" ");
+                return;
+            case '5':
+                builder.append(res.getString(R.string.content_description_for_number_five));
+                builder.append(" ");
+                return;
+            case '6':
+                builder.append(res.getString(R.string.content_description_for_number_six));
+                builder.append(" ");
+                return;
+            case '7':
+                builder.append(res.getString(R.string.content_description_for_number_seven));
+                builder.append(" ");
+                return;
+            case '8':
+                builder.append(res.getString(R.string.content_description_for_number_eight));
+                builder.append(" ");
+                return;
+            case '9':
+                builder.append(res.getString(R.string.content_description_for_number_nine));
+                builder.append(" ");
+                return;
+            default:
+                builder.append(c);
+                return;
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/Assert.java b/src/com/android/messaging/util/Assert.java
new file mode 100644
index 0000000..437965c
--- /dev/null
+++ b/src/com/android/messaging/util/Assert.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.os.Looper;
+
+import java.util.Arrays;
+
+public final class Assert {
+    public static @interface RunsOnMainThread {}
+    public static @interface DoesNotRunOnMainThread {}
+    public static @interface RunsOnAnyThread {}
+
+    private static final String TEST_THREAD_SUBSTRING = "test";
+
+    private static boolean sIsEngBuild;
+    private static boolean sShouldCrash;
+
+    // Private constructor so no one creates this class.
+    private Assert() {
+    }
+
+    // The proguard rules will strip this method out on user/userdebug builds.
+    // If you change the method signature you MUST edit proguard-release.flags.
+    private static void setIfEngBuild() {
+        sShouldCrash = sIsEngBuild = true;
+    }
+
+    private static void refreshGservices(final BugleGservices gservices) {
+        sShouldCrash = sIsEngBuild;
+        if (!sShouldCrash) {
+            sShouldCrash = gservices.getBoolean(
+                    BugleGservicesKeys.ASSERTS_FATAL,
+                    BugleGservicesKeys.ASSERTS_FATAL_DEFAULT);
+        }
+    }
+
+    // Static initializer block to find out if we're running an eng or
+    // release build.
+    static {
+        setIfEngBuild();
+    }
+
+    // This is called from FactoryImpl once the Gservices class is initialized.
+    public static void initializeGservices (final BugleGservices gservices) {
+        gservices.registerForChanges(new Runnable() {
+            @Override
+            public void run() {
+                refreshGservices(gservices);
+            }
+        });
+        refreshGservices(gservices);
+    }
+
+    /**
+     * Halt execution if this is not an eng build.
+     * <p>Intended for use in code paths that should be run only for tests and never on
+     * a real build.
+     * <p>Note that this will crash on a user build even though asserts don't normally
+     * crash on a user build.
+     */
+    public static void isEngBuild() {
+        isTrueReleaseCheck(sIsEngBuild);
+    }
+
+    /**
+     * Halt execution if this isn't the case.
+     */
+    public static void isTrue(final boolean condition) {
+        if (!condition) {
+            fail("Expected condition to be true", false);
+        }
+    }
+
+    /**
+     * Halt execution if this isn't the case.
+     */
+    public static void isFalse(final boolean condition) {
+        if (condition) {
+            fail("Expected condition to be false", false);
+        }
+    }
+
+    /**
+     * Halt execution even in release builds if this isn't the case.
+     */
+    public static void isTrueReleaseCheck(final boolean condition) {
+        if (!condition) {
+            fail("Expected condition to be true", true);
+        }
+    }
+
+    public static void equals(final int expected, final int actual) {
+        if (expected != actual) {
+            fail("Expected " + expected + " but got " + actual, false);
+        }
+    }
+
+    public static void equals(final long expected, final long actual) {
+        if (expected != actual) {
+            fail("Expected " + expected + " but got " + actual, false);
+        }
+    }
+
+    public static void equals(final Object expected, final Object actual) {
+        if (expected != actual
+                && (expected == null || actual == null || !expected.equals(actual))) {
+            fail("Expected " + expected + " but got " + actual, false);
+        }
+    }
+
+    public static void oneOf(final int actual, final int ...expected) {
+        for (int value : expected) {
+            if (actual == value) {
+                return;
+            }
+        }
+        fail("Expected value to be one of " + Arrays.toString(expected) + " but was " + actual);
+    }
+
+    public static void inRange(
+            final int val, final int rangeMinInclusive, final int rangeMaxInclusive) {
+        if (val < rangeMinInclusive || val > rangeMaxInclusive) {
+            fail("Expected value in range [" + rangeMinInclusive + ", " +
+                    rangeMaxInclusive + "], but was " + val, false);
+        }
+    }
+
+    public static void inRange(
+            final long val, final long rangeMinInclusive, final long rangeMaxInclusive) {
+        if (val < rangeMinInclusive || val > rangeMaxInclusive) {
+            fail("Expected value in range [" + rangeMinInclusive + ", " +
+                    rangeMaxInclusive + "], but was " + val, false);
+        }
+    }
+
+    public static void isMainThread() {
+        if (Looper.myLooper() != Looper.getMainLooper()
+                && !Thread.currentThread().getName().contains(TEST_THREAD_SUBSTRING)) {
+            fail("Expected to run on main thread", false);
+        }
+    }
+
+    public static void isNotMainThread() {
+        if (Looper.myLooper() == Looper.getMainLooper()
+                && !Thread.currentThread().getName().contains(TEST_THREAD_SUBSTRING)) {
+            fail("Not expected to run on main thread", false);
+        }
+    }
+
+    /**
+     * Halt execution if the value passed in is not null
+     * @param obj The object to check
+     */
+    public static void isNull(final Object obj) {
+        if (obj != null) {
+            fail("Expected object to be null", false);
+        }
+    }
+
+    /**
+     * Halt execution if the value passed in is not null
+     * @param obj The object to check
+     * @param failureMessage message to print when halting execution
+     */
+    public static void isNull(final Object obj, final String failureMessage) {
+        if (obj != null) {
+            fail(failureMessage, false);
+        }
+    }
+
+    /**
+     * Halt execution if the value passed in is null
+     * @param obj The object to check
+     */
+    public static void notNull(final Object obj) {
+        if (obj == null) {
+            fail("Expected value to be non-null", false);
+        }
+    }
+
+    public static void fail(final String message) {
+        fail("Assert.fail() called: " + message, false);
+    }
+
+    private static void fail(final String message, final boolean crashRelease) {
+        LogUtil.e(LogUtil.BUGLE_TAG, message);
+        if (crashRelease || sShouldCrash) {
+            throw new AssertionError(message);
+        } else {
+            // Find the method whose assertion failed. We're using a depth of 2, because all public
+            // Assert methods delegate to this one (see javadoc on getCaller() for details).
+            StackTraceElement caller = DebugUtils.getCaller(2);
+            if (caller != null) {
+                // This log message can be de-obfuscated by the Proguard retrace tool, just like a
+                // full stack trace from a crash.
+                LogUtil.e(LogUtil.BUGLE_TAG, "\tat " + caller.toString());
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/AvatarUriUtil.java b/src/com/android/messaging/util/AvatarUriUtil.java
new file mode 100644
index 0000000..b6c65e3
--- /dev/null
+++ b/src/com/android/messaging/util/AvatarUriUtil.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.graphics.Color;
+import android.net.Uri;
+import android.net.Uri.Builder;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.data.ParticipantData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper utility for creating {@link android.net.Uri}s to describe what avatar to fetch or
+ * generate and will help verify and extract information from avatar {@link android.net.Uri}s.
+ *
+ * There are three types of avatar {@link android.net.Uri}.
+ *
+ * 1) Group Avatars - These are avatars which are used to represent a group conversation. Group
+ * avatars uris are basically multiple avatar uri which can be any of the below types but not
+ * another group avatar. The group avatars can hold anywhere from two to four avatars uri and can
+ * be in any of the following format
+ * messaging://avatar/g?p=<avatarUri>&p=<avatarUri2>
+ * messaging://avatar/g?p=<avatarUri>&p=<avatarUri2>&p=<avatarUri3>
+ * messaging://avatar/g?p=<avatarUri>&p=<avatarUri2>&p=<avatarUri3>&p=<avatarUri4>
+ *
+ * 2) Local Resource - A local resource avatar is use when there is a profile photo for the
+ * participant. This can be any local resource.
+ *
+ * 3) Letter Tile - A letter tile is used when a participant has a name but no profile photo. A
+ * letter tile will contain the first code point of the participant's name and a background color
+ * based on the hash of the participant's full name. Letter tiles will be in the following format.
+ * messaging://avatar/l?n=<fullName>
+ *
+ * 4) Default Avatars - These are avatars are used when the participant has no profile photo or
+ * name. In these cases we use the default person icon with a color background. The color
+ * background is based on a hash of the normalized phone number.
+ *
+ * 5) Default Background Avatars - This is a special case for Default Avatars where we use the
+ * default background color for the default avatar.
+ *
+ * 6) SIM Selector Avatars - These are avatars used in the SIM selector. This may either be a
+ * regular local resource avatar (2) or an avatar with a SIM identifier (i.e. SIM background with
+ * a letter or a slot number).
+ */
+public class AvatarUriUtil {
+    private static final int MAX_GROUP_PARTICIPANTS = 4;
+
+    public static final String TYPE_GROUP_URI = "g";
+    public static final String TYPE_LOCAL_RESOURCE_URI = "r";
+    public static final String TYPE_LETTER_TILE_URI = "l";
+    public static final String TYPE_DEFAULT_URI = "d";
+    public static final String TYPE_DEFAULT_BACKGROUND_URI = "b";
+    public static final String TYPE_SIM_SELECTOR_URI = "s";
+
+    private static final String SCHEME = "messaging";
+    private static final String AUTHORITY = "avatar";
+    private static final String PARAM_NAME = "n";
+    private static final String PARAM_PRIMARY_URI = "m";
+    private static final String PARAM_FALLBACK_URI = "f";
+    private static final String PARAM_PARTICIPANT = "p";
+    private static final String PARAM_IDENTIFIER = "i";
+    private static final String PARAM_SIM_COLOR = "c";
+    private static final String PARAM_SIM_SELECTED = "s";
+    private static final String PARAM_SIM_INCOMING = "g";
+
+    public static final Uri DEFAULT_BACKGROUND_AVATAR = new Uri.Builder().scheme(SCHEME)
+            .authority(AUTHORITY).appendPath(TYPE_DEFAULT_BACKGROUND_URI).build();
+
+    private static final Uri BLANK_SIM_INDICATOR_INCOMING_URI = createSimIconUri("",
+            false /* selected */, Color.TRANSPARENT, true /* incoming */);
+    private static final Uri BLANK_SIM_INDICATOR_OUTGOING_URI = createSimIconUri("",
+            false /* selected */, Color.TRANSPARENT, false /* incoming */);
+
+    /**
+     * Creates an avatar uri based on a list of ParticipantData. The list of participants may not
+     * be null or empty. Depending on the size of the list either a group avatar uri will be create
+     * or an individual's avatar will be created. This will never return a null uri.
+     */
+    public static Uri createAvatarUri(@NonNull final List<ParticipantData> participants) {
+        Assert.notNull(participants);
+        Assert.isTrue(!participants.isEmpty());
+
+        if (participants.size() == 1) {
+            return createAvatarUri(participants.get(0));
+        }
+
+        final int numParticipants = Math.min(participants.size(), MAX_GROUP_PARTICIPANTS);
+        final ArrayList<Uri> avatarUris = new ArrayList<Uri>(numParticipants);
+        for (int i = 0; i < numParticipants; i++) {
+            avatarUris.add(createAvatarUri(participants.get(i)));
+        }
+        return AvatarUriUtil.joinAvatarUriToGroup(avatarUris);
+    }
+
+    /**
+     * Joins together a list of valid avatar uri into a group uri.The list of participants may not
+     * be null or empty. If a lit of one is given then the first element will be return back
+     * instead of a group avatar uri. All uris in the list must be a valid avatar uri. This will
+     * never return a null uri.
+     */
+    public static Uri joinAvatarUriToGroup(@NonNull final List<Uri> avatarUris) {
+        Assert.notNull(avatarUris);
+        Assert.isTrue(!avatarUris.isEmpty());
+
+        if (avatarUris.size() == 1) {
+            final Uri firstAvatar = avatarUris.get(0);
+            Assert.isTrue(AvatarUriUtil.isAvatarUri(firstAvatar));
+            return firstAvatar;
+        }
+
+        final Builder builder = new Builder();
+        builder.scheme(SCHEME);
+        builder.authority(AUTHORITY);
+        builder.appendPath(TYPE_GROUP_URI);
+        final int numParticipants = Math.min(avatarUris.size(), MAX_GROUP_PARTICIPANTS);
+        for (int i = 0; i < numParticipants; i++) {
+            final Uri uri = avatarUris.get(i);
+            Assert.notNull(uri);
+            Assert.isTrue(UriUtil.isLocalResourceUri(uri) || AvatarUriUtil.isAvatarUri(uri));
+            builder.appendQueryParameter(PARAM_PARTICIPANT, uri.toString());
+        }
+        return builder.build();
+    }
+
+    /**
+     * Creates an avatar uri based on ParticipantData which may not be null and expected to have
+     * profilePhotoUri, fullName and normalizedDestination populated. This will never return a null
+     * uri.
+     */
+    public static Uri createAvatarUri(@NonNull final ParticipantData participant) {
+        Assert.notNull(participant);
+        final String photoUriString = participant.getProfilePhotoUri();
+        final Uri profilePhotoUri = (photoUriString == null) ? null : Uri.parse(photoUriString);
+        final String name = participant.getFullName();
+        final String destination = participant.getNormalizedDestination();
+        final String contactLookupKey = participant.getLookupKey();
+        return createAvatarUri(profilePhotoUri, name, destination, contactLookupKey);
+    }
+
+    /**
+     * Creates an avatar uri based on a the input data.
+     */
+    public static Uri createAvatarUri(final Uri profilePhotoUri, final CharSequence name,
+            final String defaultIdentifier, final String contactLookupKey) {
+        Uri generatedUri;
+        if (!TextUtils.isEmpty(name) && isValidFirstCharacter(name)) {
+            generatedUri = AvatarUriUtil.fromName(name, contactLookupKey);
+        } else {
+            final String identifier = TextUtils.isEmpty(contactLookupKey)
+                    ? defaultIdentifier : contactLookupKey;
+            generatedUri = AvatarUriUtil.fromIdentifier(identifier);
+        }
+
+        if (profilePhotoUri != null) {
+            if (UriUtil.isLocalResourceUri(profilePhotoUri)) {
+                return fromLocalResourceWithFallback(profilePhotoUri, generatedUri);
+            } else {
+                return profilePhotoUri;
+            }
+        } else {
+            return generatedUri;
+        }
+    }
+
+    public static boolean isValidFirstCharacter(final CharSequence name) {
+        final char c = name.charAt(0);
+        return c != '+';
+    }
+
+    /**
+     * Creates an avatar URI used for the SIM selector.
+     * @param participantData the self participant data for an <i>active</i> SIM
+     * @param slotIdentifier when null, this will simply use a regular avatar; otherwise, the
+     *        first letter of slotIdentifier will be used for the icon.
+     * @param selected is this the currently selected SIM?
+     * @param incoming is this for an incoming message or outgoing message?
+     */
+    public static Uri createAvatarUri(@NonNull final ParticipantData participantData,
+            @Nullable final String slotIdentifier, final boolean selected, final boolean incoming) {
+        Assert.notNull(participantData);
+        Assert.isTrue(participantData.isActiveSubscription());
+        Assert.isTrue(!TextUtils.isEmpty(slotIdentifier) ||
+                !TextUtils.isEmpty(participantData.getProfilePhotoUri()));
+        if (TextUtils.isEmpty(slotIdentifier)) {
+            return createAvatarUri(participantData);
+        }
+
+        return createSimIconUri(slotIdentifier, selected, participantData.getSubscriptionColor(),
+                incoming);
+    }
+
+    private static Uri createSimIconUri(final String slotIdentifier, final boolean selected,
+            final int subColor, final boolean incoming) {
+        final Builder builder = new Builder();
+        builder.scheme(SCHEME);
+        builder.authority(AUTHORITY);
+        builder.appendPath(TYPE_SIM_SELECTOR_URI);
+        builder.appendQueryParameter(PARAM_IDENTIFIER, slotIdentifier);
+        builder.appendQueryParameter(PARAM_SIM_COLOR, String.valueOf(subColor));
+        builder.appendQueryParameter(PARAM_SIM_SELECTED, String.valueOf(selected));
+        builder.appendQueryParameter(PARAM_SIM_INCOMING, String.valueOf(incoming));
+        return builder.build();
+    }
+
+    public static Uri getBlankSimIndicatorUri(final boolean incoming) {
+        return incoming ? BLANK_SIM_INDICATOR_INCOMING_URI : BLANK_SIM_INDICATOR_OUTGOING_URI;
+    }
+
+    /**
+     * Creates an avatar uri from the given local resource Uri, followed by a fallback Uri in case
+     * the local resource one could not be loaded.
+     */
+    private static Uri fromLocalResourceWithFallback(@NonNull final Uri profilePhotoUri,
+            @NonNull Uri fallbackUri) {
+        Assert.notNull(profilePhotoUri);
+        Assert.notNull(fallbackUri);
+        final Builder builder = new Builder();
+        builder.scheme(SCHEME);
+        builder.authority(AUTHORITY);
+        builder.appendPath(TYPE_LOCAL_RESOURCE_URI);
+        builder.appendQueryParameter(PARAM_PRIMARY_URI, profilePhotoUri.toString());
+        builder.appendQueryParameter(PARAM_FALLBACK_URI, fallbackUri.toString());
+        return builder.build();
+    }
+
+    private static Uri fromName(@NonNull final CharSequence name, final String contactLookupKey) {
+        Assert.notNull(name);
+        final Builder builder = new Builder();
+        builder.scheme(SCHEME);
+        builder.authority(AUTHORITY);
+        builder.appendPath(TYPE_LETTER_TILE_URI);
+        final String nameString = String.valueOf(name);
+        builder.appendQueryParameter(PARAM_NAME, nameString);
+        final String identifier =
+                TextUtils.isEmpty(contactLookupKey) ? nameString : contactLookupKey;
+        builder.appendQueryParameter(PARAM_IDENTIFIER, identifier);
+        return builder.build();
+    }
+
+    private static Uri fromIdentifier(@NonNull final String identifier) {
+        final Builder builder = new Builder();
+        builder.scheme(SCHEME);
+        builder.authority(AUTHORITY);
+        builder.appendPath(TYPE_DEFAULT_URI);
+        builder.appendQueryParameter(PARAM_IDENTIFIER, identifier);
+        return builder.build();
+    }
+
+    public static boolean isAvatarUri(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return uri != null && TextUtils.equals(SCHEME, uri.getScheme()) &&
+                TextUtils.equals(AUTHORITY, uri.getAuthority());
+    }
+
+    public static String getAvatarType(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        final List<String> path = uri.getPathSegments();
+        return path.isEmpty() ? null : path.get(0);
+    }
+
+    public static String getIdentifier(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return uri.getQueryParameter(PARAM_IDENTIFIER);
+    }
+
+    public static String getName(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return uri.getQueryParameter(PARAM_NAME);
+    }
+
+    public static List<String> getGroupParticipantUris(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return uri.getQueryParameters(PARAM_PARTICIPANT);
+    }
+
+    public static int getSimColor(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return Integer.valueOf(uri.getQueryParameter(PARAM_SIM_COLOR));
+    }
+
+    public static boolean getSimSelected(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return Boolean.valueOf(uri.getQueryParameter(PARAM_SIM_SELECTED));
+    }
+
+    public static boolean getSimIncoming(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return Boolean.valueOf(uri.getQueryParameter(PARAM_SIM_INCOMING));
+    }
+
+    public static Uri getPrimaryUri(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        final String primaryUriString = uri.getQueryParameter(PARAM_PRIMARY_URI);
+        return primaryUriString == null ? null : Uri.parse(primaryUriString);
+    }
+
+    public static Uri getFallbackUri(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        final String fallbackUriString = uri.getQueryParameter(PARAM_FALLBACK_URI);
+        return fallbackUriString == null ? null : Uri.parse(fallbackUriString);
+    }
+}
diff --git a/src/com/android/messaging/util/BugleActivityUtil.java b/src/com/android/messaging/util/BugleActivityUtil.java
new file mode 100644
index 0000000..7f722fd
--- /dev/null
+++ b/src/com/android/messaging/util/BugleActivityUtil.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.UserManager;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.ui.conversation.ConversationActivity;
+import com.android.messaging.ui.conversationlist.ConversationListActivity;
+
+/**
+ * Utility class including logic to verify requirements to run Bugle and other activity startup
+ * logic. Called from base Bugle activity classes.
+ */
+public class BugleActivityUtil {
+
+    private static final int REQUEST_GOOGLE_PLAY_SERVICES = 0;
+
+    /**
+     * Determine if the requirements for the app to run are met. Log any Activity startup
+     * analytics.
+     * @param context
+     * @param activity is used to launch an error Dialog if necessary
+     * @return true if resume should continue normally. Returns false if some requirements to run
+     * are not met.
+     */
+    public static boolean onActivityResume(Context context, Activity activity) {
+        DataModel.get().onActivityResume();
+        Factory.get().onActivityResume();
+
+        // Validate all requirements to run are met
+        return checkHasSmsPermissionsForUser(context, activity);
+    }
+
+    /**
+     * Determine if the user doesn't have SMS permissions. This can happen if you are not the phone
+     * owner and the owner has disabled your SMS permissions.
+     * @param context is the Context used to resolve the user permissions
+     * @param activity is the Activity used to launch an error Dialog if necessary
+     * @return true if the user has SMS permissions, otherwise false.
+     */
+    private static boolean checkHasSmsPermissionsForUser(Context context, Activity activity) {
+        if (!OsUtil.isAtLeastL()) {
+            // UserManager.DISALLOW_SMS added in L. No multiuser phones before this
+            return true;
+        }
+        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        if (userManager.hasUserRestriction(UserManager.DISALLOW_SMS)) {
+            new AlertDialog.Builder(activity)
+                    .setMessage(R.string.requires_sms_permissions_message)
+                    .setCancelable(false)
+                    .setNegativeButton(R.string.requires_sms_permissions_close_button,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(final DialogInterface dialog,
+                                        final int button) {
+                                    System.exit(0);
+                                }
+                            })
+                    .show();
+            return false;
+        }
+        return true;
+    }
+}
+
diff --git a/src/com/android/messaging/util/BugleApplicationPrefs.java b/src/com/android/messaging/util/BugleApplicationPrefs.java
new file mode 100644
index 0000000..e9fceb4
--- /dev/null
+++ b/src/com/android/messaging/util/BugleApplicationPrefs.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+
+/**
+ * Provides interface to access application-wide shared preferences. This includes both the user
+ * visible preferences (e.g. the general settings in the settings page), and internal preferences
+ * under {@link BuglePrefsKeys}.
+ */
+public class BugleApplicationPrefs extends BuglePrefsImpl {
+    public BugleApplicationPrefs(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getSharedPreferencesName() {
+        return SHARED_PREFERENCES_NAME;
+    }
+
+    @Override
+    protected void validateKey(String key) {
+        super.validateKey(key);
+        // Callers shouldn't try to access per-subscription preferences from this class
+        Assert.isFalse(key.startsWith(SHARED_PREFERENCES_PER_SUBSCRIPTION_PREFIX));
+    }
+
+    @Override
+    public void onUpgrade(int oldVersion, int newVersion) {
+    }
+}
diff --git a/src/com/android/messaging/util/BugleGservices.java b/src/com/android/messaging/util/BugleGservices.java
new file mode 100644
index 0000000..2e095de
--- /dev/null
+++ b/src/com/android/messaging/util/BugleGservices.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import com.android.messaging.Factory;
+
+/**
+ * A thin wrapper for getting GServices value. During constructor time a one time background thread
+ * will cache all GServices key with the prefix of "bugle_". All get calls will wait for Gservices
+ * to finish caching the first time. In practice, the background thread will finish before any get
+ * request.
+ */
+public abstract class BugleGservices {
+    static final String BUGLE_GSERVICES_PREFIX = "bugle_";
+
+    public static BugleGservices get() {
+        return Factory.get().getBugleGservices();
+    }
+
+    public abstract void registerForChanges(final Runnable r);
+
+    /**
+     * @param key The key to look up in GServices
+     * @param defaultValue The default value if value in GServices is null or if
+     * NumberFormatException is caught.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract long getLong(final String key, final long defaultValue);
+
+    /**
+     * @param key The key to look up in GServices
+     * @param defaultValue The default value if value in GServices is null or if
+     * NumberFormatException is caught.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract int getInt(final String key, final int defaultValue);
+
+    /**
+     * @param key The key to look up in GServices
+     * @param defaultValue The default value if value in GServices is null.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract boolean getBoolean(final String key, final boolean defaultValue);
+
+    /**
+     * @param key The key to look up in GServices
+     * @param defaultValue The default value if value in GServices is null.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract String getString(final String key, final String defaultValue);
+
+    /**
+     * @param key The key to look up in GServices
+     * @param defaultValue The default value if value in GServices is null.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract float getFloat(final String key, final float defaultValue);
+}
diff --git a/src/com/android/messaging/util/BugleGservicesImpl.java b/src/com/android/messaging/util/BugleGservicesImpl.java
new file mode 100644
index 0000000..5ef0898
--- /dev/null
+++ b/src/com/android/messaging/util/BugleGservicesImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+
+/**
+ * A thin wrapper for getting GServices value.
+ */
+public class BugleGservicesImpl extends BugleGservices {
+    public BugleGservicesImpl(final Context context) {
+    }
+
+    @Override
+    public void registerForChanges(final Runnable r) {
+    }
+
+    /**
+     * Asserts that the key has the expected prefix.
+     */
+    private void assertKeyAndWaitForGservices(final String key) {
+        Assert.isTrue(key.startsWith(BUGLE_GSERVICES_PREFIX));
+    }
+
+    @Override
+    public long getLong(final String key, final long defaultValue) {
+        assertKeyAndWaitForGservices(key);
+        return defaultValue;
+    }
+
+    @Override
+    public int getInt(final String key, final int defaultValue) {
+        assertKeyAndWaitForGservices(key);
+        return defaultValue;
+    }
+
+    @Override
+    public boolean getBoolean(final String key, final boolean defaultValue) {
+        assertKeyAndWaitForGservices(key);
+        return defaultValue;
+    }
+
+    @Override
+    public String getString(final String key, final String defaultValue) {
+        assertKeyAndWaitForGservices(key);
+        return defaultValue;
+    }
+
+    @Override
+    public float getFloat(final String key, final float defaultValue) {
+        assertKeyAndWaitForGservices(key);
+        return defaultValue;
+    }
+}
diff --git a/src/com/android/messaging/util/BugleGservicesKeys.java b/src/com/android/messaging/util/BugleGservicesKeys.java
new file mode 100644
index 0000000..f36dd7f
--- /dev/null
+++ b/src/com/android/messaging/util/BugleGservicesKeys.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+
+/**
+ * List of gservices keys and default values which are in use.
+ */
+public final class BugleGservicesKeys {
+    private BugleGservicesKeys() {}   // do not instantiate
+
+    /**
+     * Whether to enable extra debugging features on the client. Default is
+     * {@value #ENABLE_DEBUGGING_FEATURES_DEFAULT}.
+     */
+    public static final String ENABLE_DEBUGGING_FEATURES
+            = "bugle_debugging";
+    public static final boolean ENABLE_DEBUGGING_FEATURES_DEFAULT
+            = false;
+
+    /**
+     * Whether to enable saving extra logs. Default is {@value #ENABLE_LOG_SAVER_DEFAULT}.
+     */
+    public static final String ENABLE_LOG_SAVER = "bugle_logsaver";
+    public static final boolean ENABLE_LOG_SAVER_DEFAULT = false;
+
+    /**
+     * Time in milliseconds of initial (attempt 1) resend backoff for failing messages
+     */
+    public static final String INITIAL_MESSAGE_RESEND_DELAY_MS = "bugle_resend_delay_in_millis";
+    public static final long INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT = 5 * 1000L;
+
+    /**
+     * Time in milliseconds of max resend backoff for failing messages
+     */
+    public static final String MAX_MESSAGE_RESEND_DELAY_MS = "bugle_max_resend_delay_in_millis";
+    public static final long MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT = 2 * 60 * 60 * 1000L;
+
+    /**
+     * Time in milliseconds of resend window for unsent messages
+     */
+    public static final String MESSAGE_RESEND_TIMEOUT_MS = "bugle_resend_timeout_in_millis";
+    public static final long MESSAGE_RESEND_TIMEOUT_MS_DEFAULT = 20 * 60 * 1000L;
+
+    /**
+     * Time in milliseconds of download window for new mms notifications
+     */
+    public static final String MESSAGE_DOWNLOAD_TIMEOUT_MS = "bugle_download_timeout_in_millis";
+    public static final long MESSAGE_DOWNLOAD_TIMEOUT_MS_DEFAULT = 20 * 60 * 1000L;
+
+    /**
+     * Time in milliseconds for SMS send timeout
+     */
+    public static final String SMS_SEND_TIMEOUT_IN_MILLIS = "bugle_sms_send_timeout";
+    public static final long SMS_SEND_TIMEOUT_IN_MILLIS_DEFAULT = 5 * 60 * 1000L;
+
+    /**
+     * Keys to control the SMS sync batch size. The batch size is defined by the number
+     * of messages that incur local database change, e.g. importing messages and
+     * deleting messages.
+     *
+     * 1. The minimum size for a batch and
+     * 2. The maximum size for a batch.
+     * The first batch uses the minimum size for probing. Set this to a small number for the
+     * first sync batch to make sure the user sees SMS showing up in conversations quickly
+     * Use these two settings to limit the number of messages to sync in each batch.
+     * The minimum is to make sure we always make progress during sync. The maximum is
+     * to limit the sync batch size within a reasonable range (needs to fit in an intent).
+     * 3. The time limit controls the limit of time duration of a sync batch. We can
+     * not control this directly due to the batching nature of sync. So this provides
+     * heuristics. We may sometime exceeds the limit if our calculation is off due to
+     * whatever reasons. Keeping this low ensures responsiveness of the application.
+     * 4. The limit on number of total messages to scan in one batch.
+     */
+    public static final String SMS_SYNC_BATCH_SIZE_MIN =
+            "bugle_sms_sync_batch_size_min";
+    public static final int SMS_SYNC_BATCH_SIZE_MIN_DEFAULT = 80;
+    public static final String SMS_SYNC_BATCH_SIZE_MAX =
+            "bugle_sms_sync_batch_size_max";
+    public static final int SMS_SYNC_BATCH_SIZE_MAX_DEFAULT = 1000;
+    public static final String SMS_SYNC_BATCH_TIME_LIMIT_MILLIS =
+            "bugle_sms_sync_batch_time_limit";
+    public static final long SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT = 400;
+    public static final String SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN =
+            "bugle_sms_sync_batch_max_messages_to_scan";
+    public static final int SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT =
+            SMS_SYNC_BATCH_SIZE_MAX_DEFAULT * 4;
+
+    /**
+     * Time in ms for sync to backoff from "now" to the latest message that will be sync'd.
+     *
+     * This controls the best case for how out of date the application will appear to be
+     * when bringing in changes made outside the application. It also represents a buffer
+     * to ensure that sync doesn't trigger based on changes made within the application.
+     */
+    public static final String SMS_SYNC_BACKOFF_TIME_MILLIS =
+            "bugle_sms_sync_backoff_time";
+    public static final long SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT = 5000L;
+
+    /**
+     * Just in case if we fall into a loop of full sync -> still not synchronized -> full sync ...
+     * This forces a backoff time so that we at most do full sync once a while (an hour by default)
+     */
+    public static final String SMS_FULL_SYNC_BACKOFF_TIME_MILLIS =
+            "bugle_sms_full_sync_backoff_time";
+    public static final long SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT = 60 * 60 * 1000;
+
+    /**
+     * Time duration to retain the most recent SMS messages for SMS storage purging
+     *
+     * Format:
+     *   <number>(w|m|y)
+     * Examples:
+     *   "1y" -- a year
+     *   "2w" -- two weeks
+     *   "6m" -- six months
+     */
+    public static final String SMS_STORAGE_PURGING_MESSAGE_RETAINING_DURATION =
+            "bugle_sms_storage_purging_message_retaining_duration";
+    public static final String SMS_STORAGE_PURGING_MESSAGE_RETAINING_DURATION_DEFAULT = "1m";
+
+    /**
+     * MMS UA profile url.
+     *
+     * This is used on all Android devices running Hangout, so cannot just host the profile of the
+     * latest and greatest phones. However, if we're on KitKat or below we can't get the phone's
+     * UA profile and thus we need to send them the default url.
+     */
+    public static final String MMS_UA_PROFILE_URL =
+            "bugle_mms_uaprofurl";
+    public static final String MMS_UA_PROFILE_URL_DEFAULT =
+            "http://www.gstatic.com/android/sms/mms_ua_profile.xml";
+
+    /**
+     * MMS apn mmsc
+     */
+    public static final String MMS_MMSC =
+            "bugle_mms_mmsc";
+
+    /**
+     * MMS apn proxy ip address
+     */
+    public static final String MMS_PROXY_ADDRESS =
+            "bugle_mms_proxy_address";
+
+    /**
+     * MMS apn proxy port
+     */
+    public static final String MMS_PROXY_PORT =
+            "bugle_mms_proxy_port";
+
+    /**
+     * List of known SMS system messages that we will ignore (no deliver, no abort) so that the
+     * user doesn't see them and the appropriate app is able to handle them. We are delivering
+     * these as a \n delimited list of patterns, however we should eventually move to storing
+     * them with the per-carrier mms config xml file.
+     */
+    public static final String SMS_IGNORE_MESSAGE_REGEX =
+            "bugle_sms_ignore_message_regex";
+    public static final String SMS_IGNORE_MESSAGE_REGEX_DEFAULT = "";
+
+    /**
+     * When receiving or importing an mms, limit the length of text to this limit. Huge blocks
+     * of text can cause the app to hang/ANR/or crash in native text code..
+     */
+    public static final String MMS_TEXT_LIMIT = "bugle_mms_text_limit";
+    public static final int MMS_TEXT_LIMIT_DEFAULT = 2000;
+
+    /**
+     * Max number of attachments the user may add to a single message.
+     */
+    public static final String MMS_ATTACHMENT_LIMIT = "bugle_mms_attachment_limit";
+    public static final int MMS_ATTACHMENT_LIMIT_DEFAULT = 10;
+
+    /**
+     * The max number of messages to show in a single conversation notification. We always show
+     * the most recent message. If this value is >1, we may also include prior messages as well.
+     */
+    public static final String MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION =
+            "bugle_max_messages_in_conversation_notification";
+    public static final int MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_DEFAULT = 7;
+
+    /**
+     * Time (in seconds) between notification ringing for incoming messages of the same
+     * conversation. We won't ding more often than this value for messages coming in at a high rate.
+     */
+    public static final String NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS
+            = "bugle_notification_time_between_rings_seconds";
+    public static final int NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS_DEFAULT = 10;
+
+    /**
+     * The max number of messages to show in a single conversation notification, when a wearable
+     * device (i.e. smartwatch) is paired with the phone. Watches have a different UX model and
+     * less screen real estate, so we may want to optimize for that case. Note that if a wearable
+     * is paired, this value will apply to notifications as shown both on the watch and the phone.
+     */
+    public static final String MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE =
+            "bugle_max_messages_in_conversation_notification_with_wearable";
+    public static final int MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE_DEFAULT = 1;
+
+    /**
+     * Regular expression to match against query.  If it matches then display
+     * the query plan for this query.
+     */
+    public static final String EXPLAIN_QUERY_PLAN_REGEXP = "bugle_query_plan_regexp";
+
+    /**
+     * Whether asserts are fatal on user/userdebug builds.
+     * Default is {@value #ASSERTS_FATAL_DEFAULT}.
+     */
+    public static final String ASSERTS_FATAL = "bugle_asserts_fatal";
+    public static final boolean ASSERTS_FATAL_DEFAULT = false;
+
+    /**
+     * Whether to use API for sending/downloading MMS (if present, true for L).
+     * Default is {@value #USE_MMS_API_IF_PRESENT_DEFAULT}.
+     */
+    public static final String USE_MMS_API_IF_PRESENT = "bugle_use_mms_api";
+    public static final boolean USE_MMS_API_IF_PRESENT_DEFAULT = true;
+
+    /**
+     * Whether to always auto-complete email addresses for sending MMS. By default, Bugle starts
+     * to auto-complete after the user has typed the "@" character.
+     * Default is (@value ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT}.
+     */
+    public static final String ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS =
+            "bugle_always_autocomplete_email_address";
+    public static final boolean ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT = false;
+
+    // We typically request an aspect ratio close the the screen size, but some cameras can be
+    // flaky and not work well in certain aspect ratios.  This allows us to guide the CameraManager
+    // to pick a more reliable aspect ratio.  The value is a float like 1.333f or 1.777f.  There is
+    // no hard coded default because the default is the screen aspect ratio.
+    public static final String CAMERA_ASPECT_RATIO = "bugle_camera_aspect_ratio";
+
+    /**
+     * The recent time range within which we should check MMS WAP Push duplication
+     * If the value is 0, it signals that we should use old dedup algorithm for wap push
+     */
+    public static final String MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS =
+            "bugle_mms_wap_push_dedup_time_limit_secs";
+    public static final long MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS_DEFAULT = 7 * 24 * 3600; // 7 days
+
+    /**
+     * Whether to use persistent, on-disk LogSaver
+     */
+    public static final String PERSISTENT_LOGSAVER = "bugle_persistent_logsaver";
+    public static final boolean PERSISTENT_LOGSAVER_DEFAULT = false;
+
+    /**
+     * For in-memory LogSaver, what's the size of memory buffer in number of records
+     */
+    public static final String IN_MEMORY_LOGSAVER_RECORD_COUNT =
+            "bugle_in_memory_logsaver_record_count";
+    public static final int IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT = 500;
+
+    /**
+     * For on-disk LogSaver, what's the size of file rotation set
+     */
+    public static final String PERSISTENT_LOGSAVER_ROTATION_SET_SIZE =
+            "bugle_persistent_logsaver_rotation_set_size";
+    public static final int PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT = 8;
+
+    /**
+     * For on-disk LogSaver, what's the byte limit of a single log file
+     */
+    public static final String PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES =
+            "bugle_persistent_logsaver_file_limit";
+    public static final int PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT = 256 * 1024; // 256KB
+
+    /**
+     * We concatenate all text parts in an MMS to form the message text. This specifies
+     * the separator between the combinated text parts. Default is ' ' (space).
+     */
+    public static final String MMS_TEXT_CONCAT_SEPARATOR = "bugle_mms_text_concat_separator";
+    public static final String MMS_TEXT_CONCAT_SEPARATOR_DEFAULT = " ";
+
+    /**
+     * Whether to enable transcoding GIFs. We sometimes need to compress GIFs to make them small
+     * enough to send via MMS (which often limits messages to 1 MB in size).
+     */
+    public static final String ENABLE_GIF_TRANSCODING = "bugle_gif_transcoding";
+    public static final boolean ENABLE_GIF_TRANSCODING_DEFAULT = true;
+}
diff --git a/src/com/android/messaging/util/BuglePrefs.java b/src/com/android/messaging/util/BuglePrefs.java
new file mode 100644
index 0000000..74a0d46
--- /dev/null
+++ b/src/com/android/messaging/util/BuglePrefs.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import com.android.messaging.Factory;
+
+/**
+ * Thin wrapper to get/set shared prefs values.
+ */
+public abstract class BuglePrefs {
+    /**
+     * Shared preferences name for preferences applicable to the entire app.
+     */
+    public static final String SHARED_PREFERENCES_NAME = "bugle";
+
+    /**
+     * Shared preferences name for subscription-specific preferences.
+     * Note: for all subscription-specific preferences, please prefix the shared preference keys
+     * with "buglesub_", so that Bugle may perform runtime validations on preferences to make sure
+     * you don't accidentally write per-subscription settings into the general pref file, and vice
+     * versa.
+     */
+    public static final String SHARED_PREFERENCES_PER_SUBSCRIPTION_PREFIX = "buglesub_";
+
+    /**
+     * A placeholder base version for Bugle builds where no shared pref version was defined.
+     */
+    public static final int NO_SHARED_PREFERENCES_VERSION = -1;
+
+    /**
+     * Returns the shared preferences file name to use.
+     * Subclasses should override and return the shared preferences file.
+     */
+    public abstract String getSharedPreferencesName();
+
+
+    /**
+     * Handles pref version upgrade.
+     */
+    public abstract void onUpgrade(final int oldVersion, final int newVersion);
+
+    /**
+     * Gets the SharedPreferences accessor to the application-wide preferences.
+     */
+    public static BuglePrefs getApplicationPrefs() {
+        return Factory.get().getApplicationPrefs();
+    }
+
+    /**
+     * Gets the SharedPreferences accessor to the subscription-specific preferences.
+     */
+    public static BuglePrefs getSubscriptionPrefs(final int subId) {
+        return Factory.get().getSubscriptionPrefs(subId);
+    }
+
+    /**
+     * @param key The key to look up in shared prefs
+     * @param defaultValue The default value if value in shared prefs is null or if
+     * NumberFormatException is caught.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract int getInt(final String key, final int defaultValue);
+
+    /**
+     * @param key The key to look up in shared prefs
+     * @param defaultValue The default value if value in shared prefs is null or if
+     * NumberFormatException is caught.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract long getLong(final String key, final long defaultValue);
+
+    /**
+     * @param key The key to look up in shared prefs
+     * @param defaultValue The default value if value in shared prefs is null.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract boolean getBoolean(final String key, final boolean defaultValue);
+
+    /**
+     * @param key The key to look up in shared prefs
+     * @param defaultValue The default value if value in shared prefs is null.
+     * @return The corresponding value, or the default value.
+     */
+    public abstract String getString(final String key, final String defaultValue);
+
+    /**
+     * @param key The key to look up in shared prefs
+     * @return The corresponding value, or null if not found.
+     */
+    public abstract byte[] getBytes(final String key);
+
+    /**
+     * @param key The key to set in shared prefs
+     * @param value The value to assign to the key
+     */
+    public abstract void putInt(final String key, final int value);
+
+    /**
+     * @param key The key to set in shared prefs
+     * @param value The value to assign to the key
+     */
+    public abstract void putLong(final String key, final long value);
+
+    /**
+     * @param key The key to set in shared prefs
+     * @param value The value to assign to the key
+     */
+    public abstract void putBoolean(final String key, final boolean value);
+
+    /**
+     * @param key The key to set in shared prefs
+     * @param value The value to assign to the key
+     */
+    public abstract void putString(final String key, final String value);
+
+    /**
+     * @param key The key to set in shared prefs
+     * @param value The value to assign to the key
+     */
+    public abstract void putBytes(final String key, final byte[] value);
+
+    /**
+     * @param key The key to remove from shared prefs
+     */
+    public abstract void remove(String key);
+}
diff --git a/src/com/android/messaging/util/BuglePrefsImpl.java b/src/com/android/messaging/util/BuglePrefsImpl.java
new file mode 100644
index 0000000..7563040
--- /dev/null
+++ b/src/com/android/messaging/util/BuglePrefsImpl.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Base64;
+
+/**
+ * Thin wrapper to get/set shared prefs values.
+ */
+public abstract class BuglePrefsImpl extends BuglePrefs {
+
+    private final Context mContext;
+
+    public BuglePrefsImpl(final Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Validate the prefs key passed in. Subclasses should override this as needed to perform
+     * runtime checks (such as making sure per-subscription settings don't sneak into application-
+     * wide settings).
+     */
+    protected void validateKey(String key) {
+    }
+
+    @Override
+    public int getInt(final String key, final int defaultValue) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        return prefs.getInt(key, defaultValue);
+    }
+
+    @Override
+    public long getLong(final String key, final long defaultValue) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        return prefs.getLong(key, defaultValue);
+    }
+
+    @Override
+    public boolean getBoolean(final String key, final boolean defaultValue) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        return prefs.getBoolean(key, defaultValue);
+    }
+
+    @Override
+    public String getString(final String key, final String defaultValue) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        return prefs.getString(key, defaultValue);
+    }
+
+    @Override
+    public byte[] getBytes(String key) {
+        final String byteValue = getString(key, null);
+        return byteValue == null ? null : Base64.decode(byteValue, Base64.DEFAULT);
+    }
+
+    @Override
+    public void putInt(final String key, final int value) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.putInt(key, value);
+        editor.apply();
+    }
+
+    @Override
+    public void putLong(final String key, final long value) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.putLong(key, value);
+        editor.apply();
+    }
+
+    @Override
+    public void putBoolean(final String key, final boolean value) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.putBoolean(key, value);
+        editor.apply();
+    }
+
+    @Override
+    public void putString(final String key, final String value) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.putString(key, value);
+        editor.apply();
+    }
+
+    @Override
+    public void putBytes(String key, byte[] value) {
+        final String encodedBytes = Base64.encodeToString(value, Base64.DEFAULT);
+        putString(key, encodedBytes);
+    }
+
+    @Override
+    public void remove(final String key) {
+        validateKey(key);
+        final SharedPreferences prefs = mContext.getSharedPreferences(
+                getSharedPreferencesName(), Context.MODE_PRIVATE);
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.remove(key);
+        editor.apply();
+    }
+}
diff --git a/src/com/android/messaging/util/BuglePrefsKeys.java b/src/com/android/messaging/util/BuglePrefsKeys.java
new file mode 100644
index 0000000..a30b5a3
--- /dev/null
+++ b/src/com/android/messaging/util/BuglePrefsKeys.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+/**
+ * List of shared preferences keys and default values. These are all internal
+ * (not user-visible) preferences. Preferences that are exposed via the Settings
+ * activity should be defined in the constants.xml resource file instead.
+ */
+public final class BuglePrefsKeys {
+    private BuglePrefsKeys() {}   // do not instantiate
+
+    /**
+     * Bugle's shared preferences version
+     */
+    public static final String SHARED_PREFERENCES_VERSION =
+            "shared_preferences_version";
+    public static final int SHARED_PREFERENCES_VERSION_DEFAULT =
+            BuglePrefs.NO_SHARED_PREFERENCES_VERSION;
+
+    /**
+     * Last time that we ran a a sync (in millis)
+     */
+    public static final String LAST_SYNC_TIME
+            = "last_sync_time_millis";
+    public static final long LAST_SYNC_TIME_DEFAULT
+            = -1;
+
+    /**
+     * Last time that we ran a full sync (in millis)
+     */
+    public static final String LAST_FULL_SYNC_TIME
+            = "last_full_sync_time_millis";
+    public static final long LAST_FULL_SYNC_TIME_DEFAULT
+            = -1;
+
+    /**
+     * Timestamp of the message for which we last did a message notification.
+     */
+    public static final String LATEST_NOTIFICATION_MESSAGE_TIMESTAMP
+        = "latest_notification_message_timestamp";
+
+    /**
+     * The last selected chooser index in the media picker.
+     */
+    public static final String SELECTED_MEDIA_PICKER_CHOOSER_INDEX
+            = "selected_media_picker_chooser_index";
+    public static final int SELECTED_MEDIA_PICKER_CHOOSER_INDEX_DEFAULT
+            = -1;
+
+    /**
+     * The attempt number when retrying ProcessPendingMessagesAction
+     */
+    public static final String PROCESS_PENDING_MESSAGES_RETRY_COUNT
+            = BuglePrefs.SHARED_PREFERENCES_PER_SUBSCRIPTION_PREFIX + "process_pending_retry";
+
+}
diff --git a/src/com/android/messaging/util/BugleSubscriptionPrefs.java b/src/com/android/messaging/util/BugleSubscriptionPrefs.java
new file mode 100644
index 0000000..039712a
--- /dev/null
+++ b/src/com/android/messaging/util/BugleSubscriptionPrefs.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+
+/**
+ * Provides interface to access per-subscription shared preferences. We have one instance of
+ * this per active subscription.
+ */
+public class BugleSubscriptionPrefs extends BuglePrefsImpl {
+    private final int mSubId;
+
+    public BugleSubscriptionPrefs(final Context context, final int subId) {
+        super(context);
+        mSubId = subId;
+    }
+
+    @Override
+    public String getSharedPreferencesName() {
+        return SHARED_PREFERENCES_PER_SUBSCRIPTION_PREFIX + String.valueOf(mSubId);
+    }
+
+    @Override
+    protected void validateKey(String key) {
+        super.validateKey(key);
+        // Callers should only access per-subscription preferences from this class
+        Assert.isTrue(key.startsWith(SHARED_PREFERENCES_PER_SUBSCRIPTION_PREFIX));
+    }
+
+    @Override
+    public void onUpgrade(final int oldVersion, final int newVersion) {
+        switch (oldVersion) {
+            case BuglePrefs.NO_SHARED_PREFERENCES_VERSION:
+                // Upgrade to version 1. Adding per-subscription shared prefs.
+                // Migrate values from the application-wide settings.
+                migratePrefBooleanInternal(BuglePrefs.getApplicationPrefs(), "delivery_reports",
+                        R.string.delivery_reports_pref_key, R.bool.delivery_reports_pref_default);
+                migratePrefBooleanInternal(BuglePrefs.getApplicationPrefs(), "auto_retrieve_mms",
+                        R.string.auto_retrieve_mms_pref_key, R.bool.auto_retrieve_mms_pref_default);
+                migratePrefBooleanInternal(BuglePrefs.getApplicationPrefs(),
+                        "auto_retrieve_mms_when_roaming",
+                        R.string.auto_retrieve_mms_when_roaming_pref_key,
+                        R.bool.auto_retrieve_mms_when_roaming_pref_default);
+                migratePrefBooleanInternal(BuglePrefs.getApplicationPrefs(), "group_messaging",
+                        R.string.group_mms_pref_key, R.bool.group_mms_pref_default);
+
+                if (PhoneUtils.getDefault().getActiveSubscriptionCount() == 1) {
+                    migratePrefStringInternal(BuglePrefs.getApplicationPrefs(), "mms_phone_number",
+                            R.string.mms_phone_number_pref_key, null);
+                }
+        }
+    }
+
+    private void migratePrefBooleanInternal(final BuglePrefs oldPrefs, final String oldKey,
+            final int newKeyResId, final int defaultValueResId) {
+        final Resources resources = Factory.get().getApplicationContext().getResources();
+        final boolean defaultValue = resources.getBoolean(defaultValueResId);
+        final boolean oldValue = oldPrefs.getBoolean(oldKey, defaultValue);
+
+        // Only migrate pref value if it's different than the default.
+        if (oldValue != defaultValue) {
+            putBoolean(resources.getString(newKeyResId), oldValue);
+        }
+    }
+
+    private void migratePrefStringInternal(final BuglePrefs oldPrefs, final String oldKey,
+            final int newKeyResId, final String defaultValue) {
+        final Resources resources = Factory.get().getApplicationContext().getResources();
+        final String oldValue = oldPrefs.getString(oldKey, defaultValue);
+
+        // Only migrate pref value if it's different than the default.
+        if (!TextUtils.equals(oldValue, defaultValue)) {
+            putString(resources.getString(newKeyResId), oldValue);
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/BugleWidgetPrefs.java b/src/com/android/messaging/util/BugleWidgetPrefs.java
new file mode 100644
index 0000000..63ba567
--- /dev/null
+++ b/src/com/android/messaging/util/BugleWidgetPrefs.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+
+/**
+ * Provides interface to access shared preferences used by bugle widgets.
+ */
+public class BugleWidgetPrefs extends BuglePrefsImpl {
+    /**
+     * Shared preferences name for preferences applicable to the entire app.
+     */
+    public static final String SHARED_PREFERENCES_WIDGET_NAME = "bugle_widgets";
+
+    public BugleWidgetPrefs(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getSharedPreferencesName() {
+        return SHARED_PREFERENCES_WIDGET_NAME;
+    }
+
+    @Override
+    public void onUpgrade(int oldVersion, int newVersion) {
+    }
+}
diff --git a/src/com/android/messaging/util/ChangeDefaultSmsAppHelper.java b/src/com/android/messaging/util/ChangeDefaultSmsAppHelper.java
new file mode 100644
index 0000000..6cf2f25
--- /dev/null
+++ b/src/com/android/messaging/util/ChangeDefaultSmsAppHelper.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.view.View;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.SnackBar;
+import com.android.messaging.ui.UIIntents;
+
+public class ChangeDefaultSmsAppHelper {
+    private Runnable mRunAfterMadeDefault;
+    private ChangeSmsAppSettingRunnable mChangeSmsAppSettingRunnable;
+
+    private static final int REQUEST_SET_DEFAULT_SMS_APP = 1;
+
+    /**
+     * When there's some condition that prevents an operation, such as sending a message,
+     * call warnOfMissingActionConditions to put up a toast and allow the user to repair
+     * that condition.
+     * @param sending - true if we're called during a sending operation
+     * @param runAfterMadeDefault - a runnable to run after the user responds
+     *                  positively to the condition prompt and resolves the condition. It is
+     *                  preferable to specify the value in {@link #handleChangeDefaultSmsResult}
+     *                  as that handles the case where the process gets restarted.
+     *                  If null, the user will be shown a generic toast message.
+     * @param composeView - compose view that may have the keyboard opened and focused
+     * @param rootView - if non-null, use this to attach a snackBar
+     * @param activity - calling activity
+     * @param fragment - calling fragment, may be null if called directly from an activity
+     */
+    public void warnOfMissingActionConditions(final boolean sending,
+            final Runnable runAfterMadeDefault,
+            final View composeView, final View rootView,
+            final Activity activity, final Fragment fragment) {
+        final PhoneUtils phoneUtils = PhoneUtils.getDefault();
+        final boolean isSmsCapable = phoneUtils.isSmsCapable();
+        final boolean hasPreferredSmsSim = phoneUtils.getHasPreferredSmsSim();
+        final boolean isDefaultSmsApp = phoneUtils.isDefaultSmsApp();
+
+        // Supports SMS?
+        if (!isSmsCapable) {
+            UiUtils.showToast(R.string.sms_disabled);
+
+        // Has a preferred sim?
+        } else if (!hasPreferredSmsSim) {
+            UiUtils.showToast(R.string.no_preferred_sim_selected);
+
+        // Is the default sms app?
+        } else if (!isDefaultSmsApp) {
+            mChangeSmsAppSettingRunnable = new ChangeSmsAppSettingRunnable(activity, fragment);
+            promptToChangeDefaultSmsApp(sending, runAfterMadeDefault,
+                    composeView, rootView, activity);
+        }
+
+        LogUtil.w(LogUtil.BUGLE_TAG, "Unsatisfied action condition: "
+                + "isSmsCapable=" + isSmsCapable + ", "
+                + "hasPreferredSmsSim=" + hasPreferredSmsSim + ", "
+                + "isDefaultSmsApp=" + isDefaultSmsApp);
+    }
+
+    private void promptToChangeDefaultSmsApp(final boolean sending,
+            final Runnable runAfterMadeDefault,
+            final View composeView, final View rootView,
+            final Activity activity) {
+        if (composeView != null) {
+            // Avoid bug in system which puts soft keyboard over dialog after orientation change
+            ImeUtil.hideSoftInput(activity, composeView);
+        }
+        mRunAfterMadeDefault = runAfterMadeDefault;
+
+        if (rootView == null) {
+            // Immediately open the system "Change default SMS app?" dialog setting.
+            mChangeSmsAppSettingRunnable.run();
+        } else {
+            UiUtils.showSnackBarWithCustomAction(activity,
+                    rootView,
+                    activity.getString(sending ? R.string.requires_default_sms_app_to_send :
+                        R.string.requires_default_sms_app),
+                        SnackBar.Action.createCustomAction(mChangeSmsAppSettingRunnable,
+                                activity.getString(R.string.requires_default_sms_change_button)),
+                                null /* interactions */,
+                                SnackBar.Placement.above(composeView));
+        }
+    }
+
+    private class ChangeSmsAppSettingRunnable implements Runnable {
+        private final Activity mActivity;
+        private final Fragment mFragment;
+
+        public ChangeSmsAppSettingRunnable(final Activity activity, final Fragment fragment) {
+            mActivity = activity;
+            mFragment = fragment;
+        }
+
+        @Override
+        public void run() {
+            try {
+                final Intent intent = UIIntents.get().getChangeDefaultSmsAppIntent(mActivity);
+                if (mFragment != null) {
+                    mFragment.startActivityForResult(intent, REQUEST_SET_DEFAULT_SMS_APP);
+                } else {
+                    mActivity.startActivityForResult(intent, REQUEST_SET_DEFAULT_SMS_APP);
+                }
+            } catch (final ActivityNotFoundException ex) {
+                // We shouldn't get here, but the monkey on JB MR0 can trigger it.
+                LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't find activity:", ex);
+                UiUtils.showToastAtBottom(R.string.activity_not_found_message);
+            }
+        }
+    }
+
+    public void handleChangeDefaultSmsResult(
+            final int requestCode,
+            final int resultCode,
+            Runnable runAfterMadeDefault) {
+        Assert.isTrue(mRunAfterMadeDefault == null || runAfterMadeDefault == null);
+        if (runAfterMadeDefault == null) {
+            runAfterMadeDefault = mRunAfterMadeDefault;
+        }
+
+        if (requestCode == REQUEST_SET_DEFAULT_SMS_APP) {
+            if (resultCode == Activity.RESULT_OK) {
+                // mRunAfterMadeDefault can be null if it was set only in
+                // promptToChangeDefaultSmsApp, and the process subsequently restarted when the
+                // user momentarily switched to another app. In that case, we'll simply show a
+                // generic toast since we do not know what the runnable was supposed to do.
+                if  (runAfterMadeDefault != null) {
+                    runAfterMadeDefault.run();
+                } else {
+                    UiUtils.showToast(R.string.toast_after_setting_default_sms_app);
+                }
+            }
+            mRunAfterMadeDefault = null;    // don't want to accidentally run it again
+        }
+    }
+}
+
+
diff --git a/src/com/android/messaging/util/CircularArray.java b/src/com/android/messaging/util/CircularArray.java
new file mode 100644
index 0000000..db6cf12
--- /dev/null
+++ b/src/com/android/messaging/util/CircularArray.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+/**
+ * Very simple circular array implementation.
+ *
+ * @param <E> The element type of this list.
+ * @LibraryInternal
+ */
+public class CircularArray<E> {
+    private int mNextWriter;
+    private boolean mHasWrapped;
+    private int mMaxCount;
+    Object mList[];
+
+    /**
+     * Constructor for CircularArray.
+     *
+     * @param count Max elements to hold in the list.
+     */
+    public CircularArray(int count) {
+        mMaxCount = count;
+        clear();
+    }
+
+    /**
+     * Reset the list.
+     */
+    public void clear() {
+        mNextWriter = 0;
+        mHasWrapped = false;
+        mList = new Object[mMaxCount];
+    }
+
+    /**
+     * Add an element to the end of the list.
+     *
+     * @param object The object to add.
+     */
+    public void add(E object) {
+        mList[mNextWriter] = object;
+        ++mNextWriter;
+        if (mNextWriter == mMaxCount) {
+            mNextWriter = 0;
+            mHasWrapped = true;
+        }
+    }
+
+    /**
+     * Get the number of elements in the list. This will be 0 <= returned count <= max count
+     *
+     * @return Elements in the circular list.
+     */
+    public int count() {
+        if (mHasWrapped) {
+            return mMaxCount;
+        } else {
+            return mNextWriter;
+        }
+    }
+
+    /**
+     * Return null if the list hasn't wrapped yet. Otherwise return the next object that would be
+     * overwritten. Can be useful to avoid extra allocations.
+     *
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public E getFree() {
+        if (!mHasWrapped) {
+            return null;
+        } else {
+            return (E) mList[mNextWriter];
+        }
+    }
+
+    /**
+     * Get the object at index. Index 0 is the oldest item inserted into the list. Index (count() -
+     * 1) is the newest.
+     *
+     * @param index Index to retrieve.
+     * @return Object at index.
+     */
+    @SuppressWarnings("unchecked")
+    public E get(int index) {
+        if (mHasWrapped) {
+            int wrappedIndex = index + mNextWriter;
+            if (wrappedIndex >= mMaxCount) {
+                wrappedIndex -= mMaxCount;
+            }
+            return (E) mList[wrappedIndex];
+        } else {
+            return (E) mList[index];
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/ConnectivityUtil.java b/src/com/android/messaging/util/ConnectivityUtil.java
new file mode 100644
index 0000000..a7467e4
--- /dev/null
+++ b/src/com/android/messaging/util/ConnectivityUtil.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+
+import com.android.messaging.datamodel.data.ParticipantData;
+
+/**
+ * ConnectivityUtil listens to the network service state changes.
+ *
+ * On N and beyond, This class instance can be created via ConnectivityUtil(context, subId), use
+ * ConnectivityUtil(context) for others.
+ *
+ * Note that TelephonyManager has createForSubscriptionId() for a specific subId from N but listen()
+ * does not use the subId on the manager, and uses the default subId on PhoneStateListener. From O,
+ * the manager uses its' own subId in listen().
+ */
+public class ConnectivityUtil {
+    // Assume not connected until informed differently
+    private volatile int mCurrentServiceState = ServiceState.STATE_POWER_OFF;
+
+    private final TelephonyManager mTelephonyManager;
+
+    private ConnectivityListener mListener;
+
+    public interface ConnectivityListener {
+        public void onPhoneStateChanged(int serviceState);
+    }
+
+    public ConnectivityUtil(final Context context) {
+        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    public ConnectivityUtil(final Context context, final int subId) {
+        Assert.isTrue(OsUtil.isAtLeastN());
+        mTelephonyManager =
+                ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
+                        .createForSubscriptionId(subId);
+    }
+
+    public int getCurrentServiceState() {
+        return mCurrentServiceState;
+    }
+
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onServiceStateChanged(final ServiceState serviceState) {
+            if (mCurrentServiceState != serviceState.getState()) {
+                mCurrentServiceState = serviceState.getState();
+                onPhoneStateChanged(mCurrentServiceState);
+            }
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(final int state) {
+            mCurrentServiceState = (state == TelephonyManager.DATA_DISCONNECTED) ?
+                    ServiceState.STATE_OUT_OF_SERVICE : ServiceState.STATE_IN_SERVICE;
+        }
+    };
+
+    private void onPhoneStateChanged(final int serviceState) {
+        final ConnectivityListener listener = mListener;
+        if (listener != null) {
+            listener.onPhoneStateChanged(serviceState);
+        }
+    }
+
+    public void register(final ConnectivityListener listener) {
+        Assert.isTrue(mListener == null || mListener == listener);
+        if (mListener == null) {
+            if (mTelephonyManager != null) {
+                mCurrentServiceState = (PhoneUtils.getDefault().isAirplaneModeOn() ?
+                        ServiceState.STATE_POWER_OFF : ServiceState.STATE_IN_SERVICE);
+                mTelephonyManager.listen(mPhoneStateListener,
+                        PhoneStateListener.LISTEN_SERVICE_STATE);
+            }
+        }
+        mListener = listener;
+    }
+
+    public void unregister() {
+        if (mListener != null) {
+            if (mTelephonyManager != null) {
+                mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+                mCurrentServiceState = ServiceState.STATE_POWER_OFF;
+            }
+        }
+        mListener = null;
+    }
+}
diff --git a/src/com/android/messaging/util/ContactRecipientEntryUtils.java b/src/com/android/messaging/util/ContactRecipientEntryUtils.java
new file mode 100644
index 0000000..78c6ffd
--- /dev/null
+++ b/src/com/android/messaging/util/ContactRecipientEntryUtils.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.net.Uri;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.text.TextUtils;
+
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.BugleRecipientEntry;
+import com.android.messaging.datamodel.data.ParticipantData;
+
+/**
+ * Provides utility methods around creating RecipientEntry instance specific to Bugle's needs.
+ */
+public class ContactRecipientEntryUtils {
+    /**
+     * A special contact id for generated contacts with no display name (number only) and avatar.
+     * By default, the chips UI doesn't load any avatar for chips with no display name, or where
+     * the display name is the same as phone number (which is true for unknown contacts).
+     * Since Bugle always generate a default avatar for all contacts, this is used to replace
+     * those default generated chips with a phone number and no avatars.
+     */
+    private static final long CONTACT_ID_NUMBER_WITH_AVATAR = -1000;
+
+    /**
+     * A generated special contact which says "Send to xxx" in the contact list, which allows
+     * a user to direct send an SMS to a number that was manually typed in.
+     */
+    private static final long CONTACT_ID_SENDTO_DESTINATION = -1001;
+
+    /**
+     * Construct a special "Send to xxx" entry for a given destination.
+     */
+    public static RecipientEntry constructSendToDestinationEntry(final String destination) {
+        return constructSpecialRecipientEntry(destination, CONTACT_ID_SENDTO_DESTINATION);
+    }
+
+    /**
+     * Construct a generated contact entry but with rendered avatar.
+     */
+    public static RecipientEntry constructNumberWithAvatarEntry(final String destination) {
+        return constructSpecialRecipientEntry(destination, CONTACT_ID_NUMBER_WITH_AVATAR);
+    }
+
+    private static RecipientEntry constructSpecialRecipientEntry(final String destination,
+            final long contactId) {
+        // For the send-to-destination (e.g. "Send to xxx" in the auto-complete drop-down)
+        // we want to show a default avatar with a static background so that it doesn't flicker
+        // as the user types.
+        final Uri avatarUri = contactId == CONTACT_ID_SENDTO_DESTINATION ?
+                AvatarUriUtil.DEFAULT_BACKGROUND_AVATAR : null;
+        return BugleRecipientEntry.constructTopLevelEntry(null, DisplayNameSources.STRUCTURED_NAME,
+                destination, RecipientEntry.INVALID_DESTINATION_TYPE, null, contactId,
+                null, contactId, avatarUri, true, null);
+    }
+
+    /**
+     * Gets the display name for contact list only. For most cases this is the same as the normal
+     * contact name, but there are cases where these two differ. For example, for the
+     * send to typed number item, we'd like to show "Send to xxx" in the contact list. However,
+     * when this item is actually added to the chips edit box, we would like to show just the
+     * phone number (i.e. no display name).
+     */
+    public static String getDisplayNameForContactList(final RecipientEntry entry) {
+        if (entry.getContactId() == CONTACT_ID_SENDTO_DESTINATION) {
+            return Factory.get().getApplicationContext().getResources().getString(
+                    R.string.contact_list_send_to_text, formatDestination(entry));
+        } else if (!TextUtils.isEmpty(entry.getDisplayName())) {
+            return entry.getDisplayName();
+        } else {
+            return formatDestination(entry);
+        }
+    }
+
+    public static String formatDestination(final RecipientEntry entry) {
+        return PhoneUtils.getDefault().formatForDisplay(entry.getDestination());
+    }
+
+    /**
+     * Returns true if the given entry has only avatar and number
+     */
+    public static boolean isAvatarAndNumberOnlyContact(final RecipientEntry entry) {
+        return entry.getContactId() == CONTACT_ID_NUMBER_WITH_AVATAR;
+    }
+
+    /**
+     * Returns true if the given entry is a special send to number item.
+     */
+    public static boolean isSendToDestinationContact(final RecipientEntry entry) {
+        return entry.getContactId() == CONTACT_ID_SENDTO_DESTINATION;
+    }
+
+    /**
+     * Returns true if the given participant is a special send to number item.
+     */
+    public static boolean isSendToDestinationContact(final ParticipantData participant) {
+        return participant.getContactId() == CONTACT_ID_SENDTO_DESTINATION;
+    }
+}
diff --git a/src/com/android/messaging/util/ContactUtil.java b/src/com/android/messaging/util/ContactUtil.java
new file mode 100644
index 0000000..94af3ba
--- /dev/null
+++ b/src/com/android/messaging/util/ContactUtil.java
@@ -0,0 +1,556 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.Profile;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.CursorQueryData;
+import com.android.messaging.datamodel.FrequentContactsCursorQueryData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsSmsUtils;
+import com.android.messaging.ui.contact.AddContactsConfirmationDialog;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Utility class including logic to list, filter, and lookup phone and emails in CP2.
+ */
+@VisibleForTesting
+public class ContactUtil {
+
+    /**
+     * Index of different columns in phone or email queries. All queries below should confirm to
+     * this column content and ordering so that caller can use the uniformed way to process
+     * returned cursors.
+     */
+    public static final int INDEX_CONTACT_ID              = 0;
+    public static final int INDEX_DISPLAY_NAME            = 1;
+    public static final int INDEX_PHOTO_URI               = 2;
+    public static final int INDEX_PHONE_EMAIL             = 3;
+    public static final int INDEX_PHONE_EMAIL_TYPE        = 4;
+    public static final int INDEX_PHONE_EMAIL_LABEL       = 5;
+
+    // An optional lookup_id column used by PhoneLookupQuery that is needed when querying for
+    // contact information.
+    public static final int INDEX_LOOKUP_KEY              = 6;
+
+    // An optional _id column to query results that need to be displayed in a list view.
+    public static final int INDEX_DATA_ID                 = 7;
+
+    // An optional sort_key column for displaying contact section labels.
+    public static final int INDEX_SORT_KEY                = 8;
+
+    // Lookup key column index specific to frequent contacts query.
+    public static final int INDEX_LOOKUP_KEY_FREQUENT     = 3;
+
+    /**
+     * Constants for listing and filtering phones.
+     */
+    public static class PhoneQuery {
+        public static final String SORT_KEY = Phone.SORT_KEY_PRIMARY;
+
+        public static final String[] PROJECTION = new String[] {
+            Phone.CONTACT_ID,                   // 0
+            Phone.DISPLAY_NAME_PRIMARY,         // 1
+            Phone.PHOTO_THUMBNAIL_URI,          // 2
+            Phone.NUMBER,                       // 3
+            Phone.TYPE,                         // 4
+            Phone.LABEL,                        // 5
+            Phone.LOOKUP_KEY,                   // 6
+            Phone._ID,                          // 7
+            PhoneQuery.SORT_KEY,                // 8
+        };
+    }
+
+    /**
+     * Constants for looking up phone numbers.
+     */
+    public static class PhoneLookupQuery {
+        public static final String[] PROJECTION = new String[] {
+            // The _ID field points to the contact id of the content
+            PhoneLookup._ID,                          // 0
+            PhoneLookup.DISPLAY_NAME,                 // 1
+            PhoneLookup.PHOTO_THUMBNAIL_URI,          // 2
+            PhoneLookup.NUMBER,                       // 3
+            PhoneLookup.TYPE,                         // 4
+            PhoneLookup.LABEL,                        // 5
+            PhoneLookup.LOOKUP_KEY,                   // 6
+            // The data id is not included as part of the projection since it's not part of
+            // PhoneLookup. This is okay because the _id field serves as both the data id and
+            // contact id. Also we never show the results directly in a list view so we are not
+            // concerned about duplicated _id's (namely, the same contact has two same phone
+            // numbers)
+        };
+    }
+
+    public static class FrequentContactQuery {
+        public static final String[] PROJECTION = new String[] {
+            Contacts._ID,                       // 0
+            Contacts.DISPLAY_NAME,              // 1
+            Contacts.PHOTO_URI,                 // 2
+            Phone.LOOKUP_KEY,                   // 3
+        };
+    }
+
+    /**
+     * Constants for listing and filtering emails.
+     */
+    public static class EmailQuery {
+        public static final String SORT_KEY = Email.SORT_KEY_PRIMARY;
+
+        public static final String[] PROJECTION = new String[] {
+            Email.CONTACT_ID,                   // 0
+            Email.DISPLAY_NAME_PRIMARY,         // 1
+            Email.PHOTO_THUMBNAIL_URI,          // 2
+            Email.ADDRESS,                      // 3
+            Email.TYPE,                         // 4
+            Email.LABEL,                        // 5
+            Email.LOOKUP_KEY,                   // 6
+            Email._ID,                          // 7
+            EmailQuery.SORT_KEY,                // 8
+        };
+    }
+
+    public static final int INDEX_SELF_QUERY_LOOKUP_KEY = 3;
+
+    /**
+     * Constants for querying self from CP2.
+     */
+    public static class SelfQuery {
+        public static final String[] PROJECTION = new String[] {
+            Profile._ID,                        // 0
+            Profile.DISPLAY_NAME_PRIMARY,       // 1
+            Profile.PHOTO_THUMBNAIL_URI,        // 2
+            Profile.LOOKUP_KEY                  // 3
+            // Phone number, type, label and data_id is not provided in this projection since
+            // Profile CONTENT_URI doesn't include this information. Also, we don't need it
+            // we just need the name and avatar url.
+        };
+    }
+
+    public static class StructuredNameQuery {
+        public static final String[] PROJECTION = new String[] {
+            StructuredName.DISPLAY_NAME,
+            StructuredName.GIVEN_NAME,
+            StructuredName.FAMILY_NAME,
+            StructuredName.PREFIX,
+            StructuredName.MIDDLE_NAME,
+            StructuredName.SUFFIX
+        };
+    }
+
+    public static final int INDEX_STRUCTURED_NAME_DISPLAY_NAME = 0;
+    public static final int INDEX_STRUCTURED_NAME_GIVEN_NAME = 1;
+    public static final int INDEX_STRUCTURED_NAME_FAMILY_NAME = 2;
+    public static final int INDEX_STRUCTURED_NAME_PREFIX = 3;
+    public static final int INDEX_STRUCTURED_NAME_MIDDLE_NAME = 4;
+    public static final int INDEX_STRUCTURED_NAME_SUFFIX = 5;
+
+    public static final long INVALID_CONTACT_ID = -1;
+
+    /**
+     * This class is static. No need to create an instance.
+     */
+    private ContactUtil() {
+    }
+
+    /**
+     * Shows a contact card or add to contacts dialog for the given contact info
+     * @param view The view whose click triggered this to show
+     * @param contactId The id of the contact in the android contacts DB
+     * @param contactLookupKey The lookup key from contacts DB
+     * @param avatarUri Uri to the avatar image if available
+     * @param normalizedDestination The normalized phone number or email
+     */
+    public static void showOrAddContact(final View view, final long contactId,
+            final String contactLookupKey, final Uri avatarUri,
+            final String normalizedDestination) {
+        if (contactId > ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED
+                && !TextUtils.isEmpty(contactLookupKey)) {
+            final Uri lookupUri =
+                    ContactsContract.Contacts.getLookupUri(contactId, contactLookupKey);
+            ContactsContract.QuickContact.showQuickContact(view.getContext(), view, lookupUri,
+                    ContactsContract.QuickContact.MODE_LARGE, null);
+        } else if (!TextUtils.isEmpty(normalizedDestination) && !TextUtils.equals(
+                normalizedDestination, ParticipantData.getUnknownSenderDestination())) {
+            final AddContactsConfirmationDialog dialog = new AddContactsConfirmationDialog(
+                    view.getContext(), avatarUri, normalizedDestination);
+            dialog.show();
+        }
+    }
+
+    @VisibleForTesting
+    public static CursorQueryData getSelf(final Context context) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+        return new CursorQueryData(context, Profile.CONTENT_URI, SelfQuery.PROJECTION, null, null,
+                null);
+    }
+
+    /**
+     * Get a list of phones sorted by contact name. One contact may have multiple phones.
+     * In that case, each phone will be returned as a separate record in the result cursor.
+     */
+    @VisibleForTesting
+    public static CursorQueryData getPhones(final Context context) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+
+        // The AOSP Contacts provider allows adding a ContactsContract.REMOVE_DUPLICATE_ENTRIES
+        // query parameter that removes duplicate (raw) numbers. Unfortunately, we can't use that
+        // because it causes the some phones' contacts provider to return incorrect sections.
+        final Uri uri = Phone.CONTENT_URI.buildUpon().appendQueryParameter(
+                ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
+                .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
+                .build();
+
+        return new CursorQueryData(context, uri, PhoneQuery.PROJECTION, null, null,
+                PhoneQuery.SORT_KEY);
+    }
+
+    /**
+     * Lookup a destination (phone, email). Supplied destination should be a relatively complete
+     * one for this to succeed. PhoneLookup / EmailLookup URI will apply some smartness to do a
+     * loose match to see whether there is a contact that matches this destination.
+     */
+    public static CursorQueryData lookupDestination(final Context context,
+            final String destination) {
+        if (MmsSmsUtils.isEmailAddress(destination)) {
+            return ContactUtil.lookupEmail(context, destination);
+        } else {
+            return ContactUtil.lookupPhone(context, destination);
+        }
+    }
+
+    /**
+     * Returns whether the search text indicates an email based search or a phone number based one.
+     */
+    private static boolean shouldFilterForEmail(final String searchText) {
+        return searchText != null && searchText.contains("@");
+    }
+
+    /**
+     * Get a list of destinations (phone, email) matching the partial destination.
+     */
+    public static CursorQueryData filterDestination(final Context context,
+            final String destination) {
+        if (shouldFilterForEmail(destination)) {
+            return ContactUtil.filterEmails(context, destination);
+        } else {
+            return ContactUtil.filterPhones(context, destination);
+        }
+    }
+
+    /**
+     * Get a list of destinations (phone, email) matching the partial destination in work profile.
+     */
+    public static CursorQueryData filterDestinationEnterprise(final Context context,
+            final String destination) {
+        if (shouldFilterForEmail(destination)) {
+            return ContactUtil.filterEmailsEnterprise(context, destination);
+        } else {
+            return ContactUtil.filterPhonesEnterprise(context, destination);
+        }
+    }
+
+    /**
+     * Get a list of phones matching a search criteria. The search may be on contact name or
+     * phone number. In case search is on contact name, all matching contact's phone number
+     * will be returned.
+     * NOTE: This is visible for testing only, clients should only call filterDestination() since
+     * we support email addresses as well.
+     */
+    @VisibleForTesting
+    public static CursorQueryData filterPhones(final Context context, final String query) {
+        return filterPhonesInternal(context, Phone.CONTENT_FILTER_URI, query, Directory.DEFAULT);
+    }
+
+    /**
+     * Similar to {@link #filterPhones(Context, String)}, but search in work profile instead.
+     */
+    public static CursorQueryData filterPhonesEnterprise(final Context context,
+            final String query) {
+        return filterPhonesInternal(context, Phone.ENTERPRISE_CONTENT_FILTER_URI, query,
+                Directory.ENTERPRISE_DEFAULT);
+    }
+
+    private static CursorQueryData filterPhonesInternal(final Context context,
+            final Uri phoneFilterBaseUri, final String query, final long directoryId) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+        Uri phoneFilterUri = buildDirectorySearchUri(phoneFilterBaseUri, query, directoryId);
+        return new CursorQueryData(context,
+                phoneFilterUri,
+                PhoneQuery.PROJECTION, null, null,
+                PhoneQuery.SORT_KEY);
+    }
+    /**
+     * Lookup a phone based on a phone number. Supplied phone should be a relatively complete
+     * phone number for this to succeed. PhoneLookup URI will apply some smartness to do a
+     * loose match to see whether there is a contact that matches this phone.
+     * NOTE: This is visible for testing only, clients should only call lookupDestination() since
+     * we support email addresses as well.
+     */
+    @VisibleForTesting
+    public static CursorQueryData lookupPhone(final Context context, final String phone) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+
+        final Uri uri = getPhoneLookupUri().buildUpon()
+                .appendPath(phone).build();
+
+        return new CursorQueryData(context, uri, PhoneLookupQuery.PROJECTION, null, null, null);
+    }
+
+    /**
+     * Get frequently contacted people. This queries for Contacts.CONTENT_STREQUENT_URI, which
+     * includes both starred or frequently contacted people.
+     */
+    public static CursorQueryData getFrequentContacts(final Context context) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+
+        return new FrequentContactsCursorQueryData(context, FrequentContactQuery.PROJECTION,
+                null, null, null);
+    }
+
+    /**
+     * Get a list of emails matching a search criteria. In Bugle, since email is not a common
+     * usage scenario, we should only do email search after user typed in a query indicating
+     * an intention to search by email (for example, "joe@").
+     * NOTE: This is visible for testing only, clients should only call filterDestination() since
+     * we support email addresses as well.
+     */
+    @VisibleForTesting
+    public static CursorQueryData filterEmails(final Context context, final String query) {
+        return filterEmailsInternal(context, Email.CONTENT_FILTER_URI, query, Directory.DEFAULT);
+    }
+
+    /**
+     * Similar to {@link #filterEmails(Context, String)}, but search in work profile instead.
+     */
+    public static CursorQueryData filterEmailsEnterprise(final Context context,
+            final String query) {
+        return filterEmailsInternal(context, Email.ENTERPRISE_CONTENT_FILTER_URI, query,
+                Directory.ENTERPRISE_DEFAULT);
+    }
+
+    private static CursorQueryData filterEmailsInternal(final Context context,
+            final Uri filterEmailsBaseUri, final String query, final long directoryId) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+        final Uri filterEmailsUri = buildDirectorySearchUri(filterEmailsBaseUri, query,
+                directoryId);
+        return new CursorQueryData(context,
+                filterEmailsUri,
+                PhoneQuery.PROJECTION, null, null,
+                PhoneQuery.SORT_KEY);
+    }
+
+    /**
+     * Lookup emails based a complete email address. Since there is no special logic needed for
+     * email lookup, this simply calls filterEmails.
+     * NOTE: This is visible for testing only, clients should only call lookupDestination() since
+     * we support email addresses as well.
+     */
+    @VisibleForTesting
+    public static CursorQueryData lookupEmail(final Context context, final String email) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+
+        final Uri uri = getEmailContentLookupUri().buildUpon()
+                .appendPath(email).appendQueryParameter(
+                        ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
+                        .build();
+
+        return new CursorQueryData(context, uri, EmailQuery.PROJECTION, null, null,
+                EmailQuery.SORT_KEY);
+    }
+
+    /**
+     * Looks up the structured name for a contact.
+     *
+     * @param primaryOnly If there are multiple raw contacts, set this flag to return only the
+     * name used as the primary display name. Otherwise, this method returns all names.
+     */
+    private static CursorQueryData lookupStructuredName(final Context context, final long contactId,
+            final boolean primaryOnly) {
+        if (!ContactUtil.hasReadContactsPermission()) {
+            return CursorQueryData.getEmptyQueryData();
+        }
+
+        // TODO: Handle enterprise contacts
+        final Uri uri = ContactsContract.Contacts.CONTENT_URI.buildUpon()
+                .appendPath(String.valueOf(contactId))
+                .appendPath(ContactsContract.Contacts.Data.CONTENT_DIRECTORY).build();
+
+        String selection = ContactsContract.Data.MIMETYPE + "=?";
+        final String[] selectionArgs = {
+                StructuredName.CONTENT_ITEM_TYPE
+        };
+        if (primaryOnly) {
+            selection += " AND " + Contacts.DISPLAY_NAME_PRIMARY + "="
+                    + StructuredName.DISPLAY_NAME;
+        }
+
+        return new CursorQueryData(context, uri,
+                StructuredNameQuery.PROJECTION, selection, selectionArgs, null);
+    }
+
+    /**
+     * Looks up the first name for a contact. If there are multiple raw
+     * contacts, this returns the name that is associated with the contact's
+     * primary display name. The name is null when contact id does not exist
+     * (possibly because it is a corp contact) or it does not have a first name.
+     */
+    public static String lookupFirstName(final Context context, final long contactId) {
+        if (isEnterpriseContactId(contactId)) {
+            return null;
+        }
+        String firstName = null;
+        Cursor nameCursor = null;
+        try {
+            nameCursor = ContactUtil.lookupStructuredName(context, contactId, true)
+                    .performSynchronousQuery();
+            if (nameCursor != null && nameCursor.moveToFirst()) {
+                firstName = nameCursor.getString(ContactUtil.INDEX_STRUCTURED_NAME_GIVEN_NAME);
+            }
+        } finally {
+            if (nameCursor != null) {
+                nameCursor.close();
+            }
+        }
+        return firstName;
+    }
+
+    /**
+     * Creates a RecipientEntry from the provided data fields (from the contacts cursor).
+     * @param firstLevel whether this item is the first entry of this contact in the list.
+     */
+    public static RecipientEntry createRecipientEntry(final String displayName,
+            final int displayNameSource, final String destination, final int destinationType,
+            final String destinationLabel, final long contactId, final String lookupKey,
+            final long dataId, final String photoThumbnailUri, final boolean firstLevel) {
+        if (firstLevel) {
+            return RecipientEntry.constructTopLevelEntry(displayName, displayNameSource,
+                    destination, destinationType, destinationLabel, contactId, null, dataId,
+                    photoThumbnailUri, true, lookupKey);
+        } else {
+            return RecipientEntry.constructSecondLevelEntry(displayName, displayNameSource,
+                    destination, destinationType, destinationLabel, contactId, null, dataId,
+                    photoThumbnailUri, true, lookupKey);
+        }
+    }
+
+    /**
+     * Creates a RecipientEntry for PhoneQuery result. The result is then displayed in the
+     * contact search drop down or as replacement chips in the chips edit box.
+     */
+    public static RecipientEntry createRecipientEntryForPhoneQuery(final Cursor cursor,
+            final boolean isFirstLevel) {
+        final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+        final String displayName = cursor.getString(
+                ContactUtil.INDEX_DISPLAY_NAME);
+        final String photoThumbnailUri = cursor.getString(
+                ContactUtil.INDEX_PHOTO_URI);
+        final String destination = cursor.getString(
+                ContactUtil.INDEX_PHONE_EMAIL);
+        final int destinationType = cursor.getInt(
+                ContactUtil.INDEX_PHONE_EMAIL_TYPE);
+        final String destinationLabel = cursor.getString(
+                ContactUtil.INDEX_PHONE_EMAIL_LABEL);
+        final String lookupKey = cursor.getString(
+                ContactUtil.INDEX_LOOKUP_KEY);
+
+        // PhoneQuery uses the contact id as the data id ("_id").
+        final long dataId = contactId;
+
+        return createRecipientEntry(displayName,
+                DisplayNameSources.STRUCTURED_NAME, destination, destinationType,
+                destinationLabel, contactId, lookupKey, dataId, photoThumbnailUri,
+                isFirstLevel);
+    }
+
+    /**
+     * Returns if a given contact id is valid.
+     */
+    public static boolean isValidContactId(final long contactId) {
+        return contactId >= 0;
+    }
+
+    /**
+     * Returns if a given contact id belongs to managed profile.
+     */
+    public static boolean isEnterpriseContactId(final long contactId) {
+        return OsUtil.isAtLeastL() && ContactsContract.Contacts.isEnterpriseContactId(contactId);
+    }
+
+    /**
+     * Returns Email lookup uri that will query both primary and corp profile
+     */
+    private static Uri getEmailContentLookupUri() {
+        if (OsUtil.isAtLeastM()) {
+            return Email.ENTERPRISE_CONTENT_LOOKUP_URI;
+        }
+        return Email.CONTENT_LOOKUP_URI;
+    }
+
+    /**
+     * Returns PhoneLookup URI.
+     */
+    public static Uri getPhoneLookupUri() {
+        if (OsUtil.isAtLeastM()) {
+            return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI;
+        }
+        return PhoneLookup.CONTENT_FILTER_URI;
+    }
+
+    public static boolean hasReadContactsPermission() {
+        return OsUtil.hasPermission(Manifest.permission.READ_CONTACTS);
+    }
+
+    private static Uri buildDirectorySearchUri(final Uri uri, final String query,
+            final long directoryId) {
+        return uri.buildUpon()
+                .appendPath(query).appendQueryParameter(
+                        ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId))
+                .build();
+    }
+}
diff --git a/src/com/android/messaging/util/ContentType.java b/src/com/android/messaging/util/ContentType.java
new file mode 100644
index 0000000..75fff93
--- /dev/null
+++ b/src/com/android/messaging/util/ContentType.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.webkit.MimeTypeMap;
+
+public final class ContentType {
+    public static String THREE_GPP_EXTENSION = "3gp";
+    public static String VIDEO_MP4_EXTENSION = "mp4";
+    // Default extension used when we don't know one.
+    public static String DEFAULT_EXTENSION = "dat";
+
+    public static final int TYPE_IMAGE = 0;
+    public static final int TYPE_VIDEO = 1;
+    public static final int TYPE_AUDIO = 2;
+    public static final int TYPE_VCARD = 3;
+    public static final int TYPE_OTHER = 4;
+
+    public static final String ANY_TYPE          = "*/*";
+    public static final String MMS_MESSAGE       = "application/vnd.wap.mms-message";
+    // The phony content type for generic PDUs (e.g. ReadOrig.ind,
+    // Notification.ind, Delivery.ind).
+    public static final String MMS_GENERIC       = "application/vnd.wap.mms-generic";
+    public static final String MMS_MULTIPART_MIXED   = "application/vnd.wap.multipart.mixed";
+    public static final String MMS_MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+    public static final String MMS_MULTIPART_ALTERNATIVE =
+            "application/vnd.wap.multipart.alternative";
+
+    public static final String TEXT_PLAIN        = "text/plain";
+    public static final String TEXT_HTML         = "text/html";
+    public static final String TEXT_VCALENDAR    = "text/x-vCalendar";
+    public static final String TEXT_VCARD        = "text/x-vCard";
+
+    public static final String IMAGE_PREFIX      = "image/";
+    public static final String IMAGE_UNSPECIFIED = "image/*";
+    public static final String IMAGE_JPEG        = "image/jpeg";
+    public static final String IMAGE_JPG         = "image/jpg";
+    public static final String IMAGE_GIF         = "image/gif";
+    public static final String IMAGE_WBMP        = "image/vnd.wap.wbmp";
+    public static final String IMAGE_PNG         = "image/png";
+    public static final String IMAGE_X_MS_BMP    = "image/x-ms-bmp";
+
+    public static final String AUDIO_UNSPECIFIED = "audio/*";
+    public static final String AUDIO_AAC         = "audio/aac";
+    public static final String AUDIO_AMR         = "audio/amr";
+    public static final String AUDIO_IMELODY     = "audio/imelody";
+    public static final String AUDIO_MID         = "audio/mid";
+    public static final String AUDIO_MIDI        = "audio/midi";
+    public static final String AUDIO_MP3         = "audio/mp3";
+    public static final String AUDIO_MPEG3       = "audio/mpeg3";
+    public static final String AUDIO_MPEG        = "audio/mpeg";
+    public static final String AUDIO_MPG         = "audio/mpg";
+    public static final String AUDIO_MP4         = "audio/mp4";
+    public static final String AUDIO_MP4_LATM    = "audio/mp4-latm";
+    public static final String AUDIO_X_MID       = "audio/x-mid";
+    public static final String AUDIO_X_MIDI      = "audio/x-midi";
+    public static final String AUDIO_X_MP3       = "audio/x-mp3";
+    public static final String AUDIO_X_MPEG3     = "audio/x-mpeg3";
+    public static final String AUDIO_X_MPEG      = "audio/x-mpeg";
+    public static final String AUDIO_X_MPG       = "audio/x-mpg";
+    public static final String AUDIO_3GPP        = "audio/3gpp";
+    public static final String AUDIO_X_WAV       = "audio/x-wav";
+    public static final String AUDIO_OGG         = "application/ogg";
+
+    public static final String MULTIPART_MIXED = "multipart/mixed";
+
+    public static final String VIDEO_UNSPECIFIED = "video/*";
+    public static final String VIDEO_3GP         = "video/3gp";
+    public static final String VIDEO_3GPP        = "video/3gpp";
+    public static final String VIDEO_3G2         = "video/3gpp2";
+    public static final String VIDEO_H263        = "video/h263";
+    public static final String VIDEO_M4V         = "video/m4v";
+    public static final String VIDEO_MP4         = "video/mp4";
+    public static final String VIDEO_MPEG        = "video/mpeg";
+    public static final String VIDEO_MPEG4       = "video/mpeg4";
+    public static final String VIDEO_WEBM        = "video/webm";
+
+    public static final String APP_SMIL          = "application/smil";
+    public static final String APP_WAP_XHTML     = "application/vnd.wap.xhtml+xml";
+    public static final String APP_XHTML         = "application/xhtml+xml";
+
+    public static final String APP_DRM_CONTENT   = "application/vnd.oma.drm.content";
+    public static final String APP_DRM_MESSAGE   = "application/vnd.oma.drm.message";
+
+    // This class should never be instantiated.
+    private ContentType() {
+    }
+
+    public static boolean isTextType(final String contentType) {
+        return TEXT_PLAIN.equals(contentType)
+                || TEXT_HTML.equals(contentType)
+                || APP_WAP_XHTML.equals(contentType);
+    }
+
+    public static boolean isMediaType(final String contentType) {
+        return isImageType(contentType)
+                || isVideoType(contentType)
+                || isAudioType(contentType)
+                || isVCardType(contentType);
+    }
+
+    public static boolean isImageType(final String contentType) {
+        return (null != contentType) && contentType.startsWith(IMAGE_PREFIX);
+    }
+
+    public static boolean isAudioType(final String contentType) {
+        return (null != contentType) &&
+                (contentType.startsWith("audio/") || contentType.equalsIgnoreCase(AUDIO_OGG));
+    }
+
+    public static boolean isVideoType(final String contentType) {
+        return (null != contentType) && contentType.startsWith("video/");
+    }
+
+    public static boolean isVCardType(final String contentType) {
+        return (null != contentType) && contentType.equalsIgnoreCase(TEXT_VCARD);
+    }
+
+    public static boolean isDrmType(final String contentType) {
+        return (null != contentType)
+                && (contentType.equals(APP_DRM_CONTENT)
+                        || contentType.equals(APP_DRM_MESSAGE));
+    }
+
+    public static boolean isUnspecified(final String contentType) {
+        return (null != contentType) && contentType.endsWith("*");
+    }
+
+    /**
+     * If the content type is a type which can be displayed in the conversation list as a preview.
+     */
+    public static boolean isConversationListPreviewableType(final String contentType) {
+        return ContentType.isAudioType(contentType) || ContentType.isVideoType(contentType) ||
+                ContentType.isImageType(contentType) || ContentType.isVCardType(contentType);
+    }
+
+    /**
+     * Given a filename, look at the extension and try and determine the mime type.
+     *
+     * @param fileName a filename to determine the type from, such as img1231.jpg
+     * @param contentTypeDefault type to use when the content type can't be determined from the file
+     *      extension. It can be null or a type such as ContentType.IMAGE_UNSPECIFIED
+     * @return Content type of the extension.
+     */
+    public static String getContentTypeFromExtension(final String fileName,
+            final String contentTypeDefault) {
+        final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+        final String extension = MimeTypeMap.getFileExtensionFromUrl(fileName);
+        String contentType = mimeTypeMap.getMimeTypeFromExtension(extension);
+        if (contentType == null) {
+            contentType = contentTypeDefault;
+        }
+        return contentType;
+    }
+
+    public static String getExtensionFromMimeType(final String mimeType) {
+        final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+        final String extension = mimeTypeMap.getExtensionFromMimeType(mimeType);
+        return extension;
+    }
+
+    /**
+     * Get the common file extension for a given content type
+     * @param contentType The content type
+     * @return The extension without the .
+     */
+    public static String getExtension(final String contentType) {
+        if (VIDEO_MP4.equals(contentType)) {
+            return VIDEO_MP4_EXTENSION;
+        } else if (VIDEO_3GPP.equals(contentType)) {
+            return THREE_GPP_EXTENSION;
+        } else {
+            return DEFAULT_EXTENSION;
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/ConversationIdSet.java b/src/com/android/messaging/util/ConversationIdSet.java
new file mode 100644
index 0000000..75bf634
--- /dev/null
+++ b/src/com/android/messaging/util/ConversationIdSet.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * Utility class to make it easy to store multiple conversation id strings in a single string
+ * with delimeters.
+ */
+public class ConversationIdSet extends HashSet<String> {
+    private static final String JOIN_DELIMITER = "|";
+    private static final String SPLIT_DELIMITER = "\\|";
+
+    public ConversationIdSet() {
+        super();
+    }
+
+    public ConversationIdSet(final Collection<String> asList) {
+        super(asList);
+    }
+
+    public String first() {
+        if (size() > 0) {
+            return iterator().next();
+        } else {
+            return null;
+        }
+    }
+
+    public static ConversationIdSet createSet(final String conversationIdSetString) {
+        ConversationIdSet set = null;
+        if (conversationIdSetString != null) {
+            set = new ConversationIdSet(Arrays.asList(conversationIdSetString.split(
+                    SPLIT_DELIMITER)));
+        }
+        return set;
+    }
+
+    public String getDelimitedString() {
+        return OsUtil.joinFromSetWithDelimiter(this, JOIN_DELIMITER);
+    }
+
+    public static String join(final String conversationIdSet1, final String conversationIdSet2) {
+        String joined = null;
+        if (conversationIdSet1 == null) {
+            joined = conversationIdSet2;
+        } else if (conversationIdSet2 != null) {
+            joined = conversationIdSet1 + JOIN_DELIMITER + conversationIdSet2;
+        }
+        return joined;
+    }
+
+}
diff --git a/src/com/android/messaging/util/CubicBezierInterpolator.java b/src/com/android/messaging/util/CubicBezierInterpolator.java
new file mode 100644
index 0000000..317b3e6
--- /dev/null
+++ b/src/com/android/messaging/util/CubicBezierInterpolator.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Class that acts as an interpolator to match the cubic-bezier css timing function where p0 is
+ * fixed at 0,0 and p3 is fixed at 1,1
+ */
+public class CubicBezierInterpolator implements Interpolator {
+    private final float mX1;
+    private final float mY1;
+    private final float mX2;
+    private final float mY2;
+
+    public CubicBezierInterpolator(final float x1, final float y1, final float x2, final float y2) {
+        mX1 = x1;
+        mY1 = y1;
+        mX2 = x2;
+        mY2 = y2;
+    }
+
+    @Override
+    public float getInterpolation(float v) {
+        return getY(getTForXValue(v));
+    }
+
+    private float getX(final float t) {
+        return getCoordinate(t, mX1, mX2);
+    }
+
+    private float getY(final float t) {
+        return getCoordinate(t, mY1, mY2);
+    }
+
+    private float getCoordinate(float t, float p1, float p2) {
+        // Special case start and end.
+        if (t == 0.0f || t == 1.0f) {
+            return t;
+        }
+
+        // Step one - from 4 points to 3.
+        float ip0 = linearInterpolate(0, p1, t);
+        float ip1 = linearInterpolate(p1, p2, t);
+        float ip2 = linearInterpolate(p2, 1, t);
+
+        // Step two - from 3 points to 2.
+        ip0 = linearInterpolate(ip0, ip1, t);
+        ip1 = linearInterpolate(ip1, ip2, t);
+
+        // Final step - last point.
+        return linearInterpolate(ip0, ip1, t);
+    }
+
+    private float linearInterpolate(float a, float b, float progress) {
+        return a + (b - a) * progress;
+    }
+
+    private float getTForXValue(final float x) {
+        final float epsilon = 1e-6f;
+        final int iterations = 8;
+
+        if (x <= 0.0f) {
+            return 0.0f;
+        } else if (x >= 1.0f) {
+            return 1.0f;
+        }
+
+        // Try gradient descent to solve for t. If it works, it is very fast.
+        float t = x;
+        float minT = 0.0f;
+        float maxT = 1.0f;
+        float value = 0.0f;
+        for (int i = 0; i < iterations; i++) {
+            value = getX(t);
+            double derivative = (getX(t + epsilon) - value) / epsilon;
+            if (Math.abs(value - x) < epsilon) {
+                return t;
+            } else if (Math.abs(derivative) < epsilon) {
+                break;
+            } else {
+                if (value < x) {
+                    minT = t;
+                } else {
+                    maxT = t;
+                }
+                t -= (value - x) / derivative;
+            }
+        }
+
+        // If the gradient descent got stuck in a local minimum, e.g. because the
+        // derivative was close to 0, use an interval bisection instead.
+        for (int i = 0; Math.abs(value - x) > epsilon && i < iterations; i++) {
+            if (value < x) {
+                minT = t;
+                t = (t + maxT) / 2.0f;
+            } else {
+                maxT = t;
+                t = (t + minT) / 2.0f;
+            }
+            value = getX(t);
+        }
+        return t;
+    }
+}
diff --git a/src/com/android/messaging/util/Dates.java b/src/com/android/messaging/util/Dates.java
new file mode 100644
index 0000000..49f0c7f
--- /dev/null
+++ b/src/com/android/messaging/util/Dates.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.text.format.DateUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Collection of date utilities.
+ */
+public class Dates {
+    public static final long SECOND_IN_MILLIS = 1000;
+    public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
+    public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
+    public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
+    public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
+
+    // Flags to specify whether or not to use 12 or 24 hour mode.
+    // Callers of methods in this class should never have to specify these; this is really
+    // intended only for unit tests.
+    @SuppressWarnings("deprecation")
+    @VisibleForTesting public static final int FORCE_12_HOUR = DateUtils.FORMAT_12HOUR;
+    @SuppressWarnings("deprecation")
+    @VisibleForTesting public static final int FORCE_24_HOUR = DateUtils.FORMAT_24HOUR;
+
+    /**
+     * Private default constructor
+     */
+    private Dates() {
+    }
+
+    private static Context getContext() {
+        return Factory.get().getApplicationContext();
+    }
+    /**
+     * Get the relative time as a string
+     *
+     * @param time The time
+     *
+     * @return The relative time
+     */
+    public static CharSequence getRelativeTimeSpanString(final long time) {
+        final long now = System.currentTimeMillis();
+        if (now - time < DateUtils.MINUTE_IN_MILLIS) {
+            // Also fixes bug where posts appear in the future
+            return getContext().getResources().getText(R.string.posted_just_now);
+        }
+
+        // Workaround for b/5657035. The platform method {@link DateUtils#getRelativeTimeSpan()}
+        // passes a null context to other platform methods. However, on some devices, this
+        // context is dereferenced when it shouldn't be and an NPE is thrown. We catch that
+        // here and use a slightly less precise time.
+        try {
+            return DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS,
+                    DateUtils.FORMAT_ABBREV_RELATIVE).toString();
+        } catch (final NullPointerException npe) {
+            return getShortRelativeTimeSpanString(time);
+        }
+    }
+
+    public static CharSequence getConversationTimeString(final long time) {
+        return getTimeString(time, true /*abbreviated*/, false /*minPeriodToday*/);
+    }
+
+    public static CharSequence getMessageTimeString(final long time) {
+        return getTimeString(time, false /*abbreviated*/, false /*minPeriodToday*/);
+    }
+
+    public static CharSequence getWidgetTimeString(final long time, final boolean abbreviated) {
+        return getTimeString(time, abbreviated, true /*minPeriodToday*/);
+    }
+
+    public static CharSequence getFastScrollPreviewTimeString(final long time) {
+        return getTimeString(time, true /* abbreviated */, true /* minPeriodToday */);
+    }
+
+    public static CharSequence getMessageDetailsTimeString(final long time) {
+        final Context context = getContext();
+        int flags;
+        if (android.text.format.DateFormat.is24HourFormat(context)) {
+            flags = FORCE_24_HOUR;
+        } else {
+            flags = FORCE_12_HOUR;
+        }
+        return getOlderThanAYearTimestamp(time,
+                context.getResources().getConfiguration().locale, false /*abbreviated*/,
+                flags);
+    }
+
+    private static CharSequence getTimeString(final long time, final boolean abbreviated,
+            final boolean minPeriodToday) {
+        final Context context = getContext();
+        int flags;
+        if (android.text.format.DateFormat.is24HourFormat(context)) {
+            flags = FORCE_24_HOUR;
+        } else {
+            flags = FORCE_12_HOUR;
+        }
+        return getTimestamp(time, System.currentTimeMillis(), abbreviated,
+                context.getResources().getConfiguration().locale, flags, minPeriodToday);
+    }
+
+    @VisibleForTesting
+    public static CharSequence getTimestamp(final long time, final long now,
+            final boolean abbreviated, final Locale locale, final int flags,
+            final boolean minPeriodToday) {
+        final long timeDiff = now - time;
+
+        if (!minPeriodToday && timeDiff < DateUtils.MINUTE_IN_MILLIS) {
+            return getLessThanAMinuteOldTimeString(abbreviated);
+        } else if (!minPeriodToday && timeDiff < DateUtils.HOUR_IN_MILLIS) {
+            return getLessThanAnHourOldTimeString(timeDiff, flags);
+        } else if (getNumberOfDaysPassed(time, now) == 0) {
+            return getTodayTimeStamp(time, flags);
+        } else if (timeDiff < DateUtils.WEEK_IN_MILLIS) {
+            return getThisWeekTimestamp(time, locale, abbreviated, flags);
+        } else if (timeDiff < DateUtils.YEAR_IN_MILLIS) {
+            return getThisYearTimestamp(time, locale, abbreviated, flags);
+        } else {
+            return getOlderThanAYearTimestamp(time, locale, abbreviated, flags);
+        }
+    }
+
+    private static CharSequence getLessThanAMinuteOldTimeString(
+            final boolean abbreviated) {
+        return getContext().getResources().getText(
+                abbreviated ? R.string.posted_just_now : R.string.posted_now);
+    }
+
+    private static CharSequence getLessThanAnHourOldTimeString(final long timeDiff,
+            final int flags) {
+        final long count = (timeDiff / MINUTE_IN_MILLIS);
+        final String format = getContext().getResources().getQuantityString(
+                R.plurals.num_minutes_ago, (int) count);
+        return String.format(format, count);
+    }
+
+    private static CharSequence getTodayTimeStamp(final long time, final int flags) {
+        return DateUtils.formatDateTime(getContext(), time,
+                DateUtils.FORMAT_SHOW_TIME | flags);
+    }
+
+    private static CharSequence getExplicitFormattedTime(final long time, final int flags,
+            final String format24, final String format12) {
+        SimpleDateFormat formatter;
+        if ((flags & FORCE_24_HOUR) == FORCE_24_HOUR) {
+            formatter = new SimpleDateFormat(format24);
+        } else {
+            formatter = new SimpleDateFormat(format12);
+        }
+        return formatter.format(new Date(time));
+    }
+
+    private static CharSequence getThisWeekTimestamp(final long time,
+            final Locale locale, final boolean abbreviated, final int flags) {
+        final Context context = getContext();
+        if (abbreviated) {
+            return DateUtils.formatDateTime(context, time,
+                    DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY | flags);
+        } else {
+            if (locale.equals(Locale.US)) {
+                return getExplicitFormattedTime(time, flags, "EEE HH:mm", "EEE h:mmaa");
+            } else {
+                return DateUtils.formatDateTime(context, time,
+                        DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_TIME
+                        | DateUtils.FORMAT_ABBREV_WEEKDAY
+                        | flags);
+            }
+        }
+    }
+
+    private static CharSequence getThisYearTimestamp(final long time, final Locale locale,
+            final boolean abbreviated, final int flags) {
+        final Context context = getContext();
+        if (abbreviated) {
+            return DateUtils.formatDateTime(context, time,
+                    DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH
+                    | DateUtils.FORMAT_NO_YEAR | flags);
+        } else {
+            if (locale.equals(Locale.US)) {
+                return getExplicitFormattedTime(time, flags, "MMM d, HH:mm", "MMM d, h:mmaa");
+            } else {
+                return DateUtils.formatDateTime(context, time,
+                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME
+                        | DateUtils.FORMAT_ABBREV_MONTH
+                        | DateUtils.FORMAT_NO_YEAR
+                        | flags);
+            }
+        }
+    }
+
+    private static CharSequence getOlderThanAYearTimestamp(final long time,
+            final Locale locale, final boolean abbreviated, final int flags) {
+        final Context context = getContext();
+        if (abbreviated) {
+            if (locale.equals(Locale.US)) {
+                return getExplicitFormattedTime(time, flags, "M/d/yy", "M/d/yy");
+            } else {
+                return DateUtils.formatDateTime(context, time,
+                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR
+                        | DateUtils.FORMAT_NUMERIC_DATE);
+            }
+        } else {
+            if (locale.equals(Locale.US)) {
+                return getExplicitFormattedTime(time, flags, "M/d/yy, HH:mm", "M/d/yy, h:mmaa");
+            } else {
+                return DateUtils.formatDateTime(context, time,
+                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME
+                        | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_YEAR
+                        | flags);
+            }
+        }
+    }
+
+    public static CharSequence getShortRelativeTimeSpanString(final long time) {
+        final long now = System.currentTimeMillis();
+        final long duration = Math.abs(now - time);
+
+        int resId;
+        long count;
+
+        final Context context = getContext();
+
+        if (duration < HOUR_IN_MILLIS) {
+            count = duration / MINUTE_IN_MILLIS;
+            resId = R.plurals.num_minutes_ago;
+        } else if (duration < DAY_IN_MILLIS) {
+            count = duration / HOUR_IN_MILLIS;
+            resId = R.plurals.num_hours_ago;
+        } else if (duration < WEEK_IN_MILLIS) {
+            count = getNumberOfDaysPassed(time, now);
+            resId = R.plurals.num_days_ago;
+        } else {
+            // Although we won't be showing a time, there is a bug on some devices that use
+            // the passed in context. On these devices, passing in a {@code null} context
+            // here will generate an NPE. See b/5657035.
+            return DateUtils.formatDateRange(context, time, time,
+                    DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_ABBREV_RELATIVE);
+        }
+
+        final String format = context.getResources().getQuantityString(resId, (int) count);
+        return String.format(format, count);
+    }
+
+    private static long getNumberOfDaysPassed(final long date1, final long date2) {
+        LocalDateTime dateTime1 = LocalDateTime.ofInstant(Instant.ofEpochMilli(date1),
+                                                          ZoneId.systemDefault());
+        LocalDateTime dateTime2 = LocalDateTime.ofInstant(Instant.ofEpochMilli(date2),
+                                                          ZoneId.systemDefault());
+        return Math.abs(ChronoUnit.DAYS.between(dateTime2, dateTime1));
+    }
+}
diff --git a/src/com/android/messaging/util/DebugUtils.java b/src/com/android/messaging/util/DebugUtils.java
new file mode 100644
index 0000000..6e33f48
--- /dev/null
+++ b/src/com/android/messaging/util/DebugUtils.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Environment;
+import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.widget.ArrayAdapter;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.SyncManager;
+import com.android.messaging.datamodel.action.DumpDatabaseAction;
+import com.android.messaging.datamodel.action.LogTelephonyDatabaseAction;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.debug.DebugSmsMmsFromDumpFileDialogFragment;
+import com.google.common.io.ByteStreams;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.StreamCorruptedException;
+
+public class DebugUtils {
+    private static final String TAG = "bugle.util.DebugUtils";
+
+    private static boolean sDebugNoise;
+    private static boolean sDebugClassZeroSms;
+    private static MediaPlayer [] sMediaPlayer;
+    private static final Object sLock = new Object();
+
+    public static final int DEBUG_SOUND_SERVER_REQUEST = 0;
+    public static final int DEBUG_SOUND_DB_OP = 1;
+
+    public static void maybePlayDebugNoise(final Context context, final int sound) {
+        if (sDebugNoise) {
+            synchronized (sLock) {
+                try {
+                    if (sMediaPlayer == null) {
+                        sMediaPlayer = new MediaPlayer[2];
+                        sMediaPlayer[DEBUG_SOUND_SERVER_REQUEST] =
+                                MediaPlayer.create(context, R.raw.server_request_debug);
+                        sMediaPlayer[DEBUG_SOUND_DB_OP] =
+                                MediaPlayer.create(context, R.raw.db_op_debug);
+                        sMediaPlayer[DEBUG_SOUND_DB_OP].setVolume(1.0F, 1.0F);
+                        sMediaPlayer[DEBUG_SOUND_SERVER_REQUEST].setVolume(0.3F, 0.3F);
+                    }
+                    if (sMediaPlayer[sound] != null) {
+                        sMediaPlayer[sound].start();
+                    }
+                } catch (final IllegalArgumentException e) {
+                    LogUtil.e(TAG, "MediaPlayer exception", e);
+                } catch (final SecurityException e) {
+                    LogUtil.e(TAG, "MediaPlayer exception", e);
+                } catch (final IllegalStateException e) {
+                    LogUtil.e(TAG, "MediaPlayer exception", e);
+                }
+            }
+        }
+    }
+
+    public static boolean isDebugEnabled() {
+        return BugleGservices.get().getBoolean(BugleGservicesKeys.ENABLE_DEBUGGING_FEATURES,
+                BugleGservicesKeys.ENABLE_DEBUGGING_FEATURES_DEFAULT);
+    }
+
+    public abstract static class DebugAction {
+        String mTitle;
+        public DebugAction(final String title) {
+            mTitle = title;
+        }
+
+        @Override
+        public String toString() {
+            return mTitle;
+        }
+
+        public abstract void run();
+    }
+
+    public static void showDebugOptions(final Activity host) {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(host);
+
+        final ArrayAdapter<DebugAction> arrayAdapter = new ArrayAdapter<DebugAction>(
+                host, android.R.layout.simple_list_item_1);
+
+        arrayAdapter.add(new DebugAction("Dump Database") {
+            @Override
+            public void run() {
+                DumpDatabaseAction.dumpDatabase();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Log Telephony Data") {
+            @Override
+            public void run() {
+                LogTelephonyDatabaseAction.dumpDatabase();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Toggle Noise") {
+            @Override
+            public void run() {
+                sDebugNoise = !sDebugNoise;
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Force sync SMS") {
+            @Override
+            public void run() {
+                final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+                prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, -1);
+                SyncManager.forceSync();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Sync SMS") {
+            @Override
+            public void run() {
+                SyncManager.sync();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Load SMS/MMS from dump file") {
+            @Override
+            public void run() {
+                new DebugSmsMmsDumpTask(host,
+                        DebugSmsMmsFromDumpFileDialogFragment.ACTION_LOAD).executeOnThreadPool();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Email SMS/MMS dump file") {
+            @Override
+            public void run() {
+                new DebugSmsMmsDumpTask(host,
+                        DebugSmsMmsFromDumpFileDialogFragment.ACTION_EMAIL).executeOnThreadPool();
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("MMS Config...") {
+            @Override
+            public void run() {
+                UIIntents.get().launchDebugMmsConfigActivity(host);
+            }
+        });
+
+        arrayAdapter.add(new DebugAction(sDebugClassZeroSms ? "Turn off Class 0 sms test" :
+                "Turn on Class Zero test") {
+            @Override
+            public void run() {
+                sDebugClassZeroSms = !sDebugClassZeroSms;
+            }
+        });
+
+        arrayAdapter.add(new DebugAction("Test sharing a file URI") {
+            @Override
+            public void run() {
+                shareFileUri();
+            }
+        });
+
+        builder.setAdapter(arrayAdapter,
+                new android.content.DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(final DialogInterface arg0, final int pos) {
+                arrayAdapter.getItem(pos).run();
+            }
+        });
+
+        builder.create().show();
+    }
+
+    /**
+     * Task to list all the dump files and perform an action on it
+     */
+    private static class DebugSmsMmsDumpTask extends SafeAsyncTask<Void, Void, String[]> {
+        private final String mAction;
+        private final Activity mHost;
+
+        public DebugSmsMmsDumpTask(final Activity host, final String action) {
+            mHost = host;
+            mAction = action;
+        }
+
+        @Override
+        protected void onPostExecute(final String[] result) {
+            if (result == null || result.length < 1) {
+                return;
+            }
+            final FragmentManager fragmentManager = mHost.getFragmentManager();
+            final FragmentTransaction ft = fragmentManager.beginTransaction();
+            final DebugSmsMmsFromDumpFileDialogFragment dialog =
+                    DebugSmsMmsFromDumpFileDialogFragment.newInstance(result, mAction);
+            dialog.show(fragmentManager, ""/*tag*/);
+        }
+
+        @Override
+        protected String[] doInBackgroundTimed(final Void... params) {
+            final File dir = DebugUtils.getDebugFilesDir();
+            return dir.list(new FilenameFilter() {
+                @Override
+                public boolean accept(final File dir, final String filename) {
+                    return filename != null
+                            && ((mAction == DebugSmsMmsFromDumpFileDialogFragment.ACTION_EMAIL
+                            && filename.equals(DumpDatabaseAction.DUMP_NAME))
+                            || filename.startsWith(MmsUtils.MMS_DUMP_PREFIX)
+                            || filename.startsWith(MmsUtils.SMS_DUMP_PREFIX));
+                }
+            });
+        }
+    }
+
+    /**
+     * Dump the received raw SMS data into a file on external storage
+     *
+     * @param id The ID to use as part of the dump file name
+     * @param messages The raw SMS data
+     */
+    public static void dumpSms(final long id, final android.telephony.SmsMessage[] messages,
+            final String format) {
+        try {
+            final String dumpFileName = MmsUtils.SMS_DUMP_PREFIX + Long.toString(id);
+            final File dumpFile = DebugUtils.getDebugFile(dumpFileName, true);
+            if (dumpFile != null) {
+                final FileOutputStream fos = new FileOutputStream(dumpFile);
+                final DataOutputStream dos = new DataOutputStream(fos);
+                try {
+                    final int chars = (TextUtils.isEmpty(format) ? 0 : format.length());
+                    dos.writeInt(chars);
+                    if (chars > 0) {
+                        dos.writeUTF(format);
+                    }
+                    dos.writeInt(messages.length);
+                    for (final android.telephony.SmsMessage message : messages) {
+                        final byte[] pdu = message.getPdu();
+                        dos.writeInt(pdu.length);
+                        dos.write(pdu, 0, pdu.length);
+                    }
+                    dos.flush();
+                } finally {
+                    dos.close();
+                    ensureReadable(dumpFile);
+                }
+            }
+        } catch (final IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "dumpSms: " + e, e);
+        }
+    }
+
+    /**
+     * Load MMS/SMS from the dump file
+     */
+    public static SmsMessage[] retreiveSmsFromDumpFile(final String dumpFileName) {
+        SmsMessage[] messages = null;
+        final File inputFile = DebugUtils.getDebugFile(dumpFileName, false);
+        if (inputFile != null) {
+            FileInputStream fis = null;
+            DataInputStream dis = null;
+            try {
+                fis = new FileInputStream(inputFile);
+                dis = new DataInputStream(fis);
+
+                // SMS dump
+                String format = null;
+                final int chars = dis.readInt();
+                if (chars > 0) {
+                    format = dis.readUTF();
+                }
+                final int count = dis.readInt();
+                final SmsMessage[] messagesTemp = new SmsMessage[count];
+                for (int i = 0; i < count; i++) {
+                    final int length = dis.readInt();
+                    final byte[] pdu = new byte[length];
+                    dis.read(pdu, 0, length);
+                    messagesTemp[i] =
+                            OsUtil.isAtLeastM()
+                                    ? SmsMessage.createFromPdu(pdu, format)
+                                    : SmsMessage.createFromPdu(pdu);
+                }
+                messages = messagesTemp;
+            } catch (final FileNotFoundException e) {
+                // Nothing to do
+            } catch (final StreamCorruptedException e) {
+                // Nothing to do
+            } catch (final IOException e) {
+                // Nothing to do
+            } finally {
+                if (dis != null) {
+                    try {
+                        dis.close();
+                    } catch (final IOException e) {
+                        // Nothing to do
+                    }
+                }
+            }
+        }
+        return messages;
+    }
+
+    public static File getDebugFile(final String fileName, final boolean create) {
+        final File dir = getDebugFilesDir();
+        final File file = new File(dir, fileName);
+        if (create && file.exists()) {
+            file.delete();
+        }
+        return file;
+    }
+
+    public static File getDebugFilesDir() {
+        final File dir = Environment.getExternalStorageDirectory();
+        return dir;
+    }
+
+    /**
+     * Load MMS/SMS from the dump file
+     */
+    public static byte[] receiveFromDumpFile(final String dumpFileName) {
+        byte[] data = null;
+        try {
+            final File inputFile = getDebugFile(dumpFileName, false);
+            if (inputFile != null) {
+                final FileInputStream fis = new FileInputStream(inputFile);
+                final BufferedInputStream bis = new BufferedInputStream(fis);
+                try {
+                    // dump file
+                    data = ByteStreams.toByteArray(bis);
+                    if (data == null || data.length < 1) {
+                        LogUtil.e(LogUtil.BUGLE_TAG, "receiveFromDumpFile: empty data");
+                    }
+                } finally {
+                    bis.close();
+                }
+            }
+        } catch (final IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "receiveFromDumpFile: " + e, e);
+        }
+        return data;
+    }
+
+    public static void ensureReadable(final File file) {
+        if (file.exists()){
+            file.setReadable(true, false);
+        }
+    }
+
+    /**
+     * Logs the name of the method that is currently executing, e.g. "MyActivity.onCreate". This is
+     * useful for surgically adding logs for tracing execution while debugging.
+     * <p>
+     * NOTE: This method retrieves the current thread's stack trace, which adds runtime overhead.
+     * However, this method is only executed on eng builds if DEBUG logs are loggable.
+     */
+    public static void logCurrentMethod(String tag) {
+        if (!LogUtil.isLoggable(tag, LogUtil.DEBUG)) {
+            return;
+        }
+        StackTraceElement caller = getCaller(1);
+        if (caller == null) {
+            return;
+        }
+        String className = caller.getClassName();
+        // Strip off the package name
+        int lastDot = className.lastIndexOf('.');
+        if (lastDot > -1) {
+            className = className.substring(lastDot + 1);
+        }
+        LogUtil.d(tag, className + "." + caller.getMethodName());
+    }
+
+    /**
+     * Returns info about the calling method. The {@code depth} parameter controls how far back to
+     * go. For example, if foo() calls bar(), and bar() calls getCaller(0), it returns info about
+     * bar(). If bar() instead called getCaller(1), it would return info about foo(). And so on.
+     * <p>
+     * NOTE: This method retrieves the current thread's stack trace, which adds runtime overhead.
+     * It should only be used in production where necessary to gather context about an error or
+     * unexpected event (e.g. the {@link Assert} class uses it).
+     *
+     * @return stack frame information for the caller (if found); otherwise {@code null}.
+     */
+    public static StackTraceElement getCaller(int depth) {
+        // If the signature of this method is changed, proguard.flags must be updated!
+        if (depth < 0) {
+            throw new IllegalArgumentException("depth cannot be negative");
+        }
+        StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+        if (trace == null || trace.length < (depth + 2)) {
+            return null;
+        }
+        // The stack trace includes some methods we don't care about (e.g. this method).
+        // Walk down until we find this method, and then back up to the caller we're looking for.
+        for (int i = 0; i < trace.length - 1; i++) {
+            String methodName = trace[i].getMethodName();
+            if ("getCaller".equals(methodName)) {
+                return trace[i + depth + 1];
+            }
+        }
+        // Never found ourself in the stack?!
+        return null;
+    }
+
+    /**
+     * Returns a boolean indicating whether ClassZero debugging is enabled. If enabled, any received
+     * sms is treated as if it were a class zero message and displayed by the ClassZeroActivity.
+     */
+    public static boolean debugClassZeroSmsEnabled() {
+        return sDebugClassZeroSms;
+    }
+
+    /** Shares a ringtone file via file URI. */
+    private static void shareFileUri() {
+        final String packageName = "com.android.messaging";
+        final String fileName = "/system/media/audio/ringtones/Andromeda.ogg";
+
+        Intent intent = new Intent(Intent.ACTION_SEND);
+        intent.setPackage(packageName);
+        intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fileName));
+        intent.setType("image/*");
+        Factory.get().getApplicationContext().startActivity(intent);
+    }
+}
diff --git a/src/com/android/messaging/util/EmailAddress.java b/src/com/android/messaging/util/EmailAddress.java
new file mode 100644
index 0000000..c59170e
--- /dev/null
+++ b/src/com/android/messaging/util/EmailAddress.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import com.google.common.base.CharMatcher;
+
+/**
+ * Parsing the email address
+ */
+public final class EmailAddress {
+    private static final CharMatcher ANY_WHITESPACE = CharMatcher.anyOf(
+            " \t\n\r\f\u000B\u0085\u2028\u2029\u200D\uFFEF\uFFFD\uFFFE\uFFFF");
+    private static final CharMatcher EMAIL_ALLOWED_CHARS = CharMatcher.inRange((char) 0, (char) 31)
+            .or(CharMatcher.is((char) 127))
+            .or(CharMatcher.anyOf(" @,:<>"))
+            .negate();
+
+    /**
+     * Helper method that checks whether the input text is valid email address.
+     * TODO: This creates a new EmailAddress object each time
+     * Need to make it more lightweight by pulling out the validation code into a static method.
+     */
+    public static boolean isValidEmail(final String emailText) {
+        return new EmailAddress(emailText).isValid();
+    }
+
+    /**
+     * Parses the specified email address. Internationalized addresses are treated as invalid.
+     *
+     * @param emailString A string representing just an email address. It should
+     * not contain any other tokens. <code>"Name&lt;foo@example.org>"</code> won't be valid.
+     */
+    public EmailAddress(final String emailString) {
+        this(emailString, false);
+    }
+
+    /**
+     * Parses the specified email address.
+     *
+     * @param emailString A string representing just an email address. It should
+     * not contain any other tokens. <code>"Name&lt;foo@example.org>"</code> won't be valid.
+     * @param i18n Accept an internationalized address if it is true.
+     */
+    public EmailAddress(final String emailString, final boolean i18n) {
+        allowI18n = i18n;
+        valid = parseEmail(emailString);
+    }
+
+    /**
+     * Parses the specified email address. Internationalized addresses are treated as invalid.
+     *
+     * @param user A string representing the username in the email prior to the '@' symbol
+     * @param host A string representing the host following the '@' symbol
+     */
+    public EmailAddress(final String user, final String host) {
+        this(user, host, false);
+    }
+
+    /**
+     * Parses the specified email address.
+     *
+     * @param user A string representing the username in the email prior to the '@' symbol
+     * @param host A string representing the host following the '@' symbol
+     * @param i18n Accept an internationalized address if it is true.
+     */
+    public EmailAddress(final String user, final String host, final boolean i18n) {
+        allowI18n = i18n;
+        this.user = user;
+        setHost(host);
+    }
+
+    protected boolean parseEmail(final String emailString) {
+        // check for null
+        if (emailString == null) {
+            return false;
+        }
+
+        // Check for an '@' character. Get the last one, in case the local part is
+        // quoted. See http://b/1944742.
+        final int atIndex = emailString.lastIndexOf('@');
+        if ((atIndex <= 0) || // no '@' character in the email address
+                              // or @ on the first position
+                (atIndex == (emailString.length() - 1))) { // last character, no host
+            return false;
+        }
+
+        user = emailString.substring(0, atIndex);
+        host = emailString.substring(atIndex + 1);
+
+        return isValidInternal();
+    }
+
+    @Override
+    public String toString() {
+        return user + "@" + host;
+    }
+
+    /**
+     * Ensure the email address is valid, conforming to current RFC2821 and
+     * RFC2822 guidelines (although some iffy characters, like ! and ;, are
+     * allowed because they are not technically prohibited in the RFC)
+     */
+    private boolean isValidInternal() {
+        if ((user == null) || (host == null)) {
+            return false;
+        }
+
+        if ((user.length() == 0) || (host.length() == 0)) {
+            return false;
+        }
+
+        // check for white space in the host
+        if (ANY_WHITESPACE.indexIn(host) >= 0) {
+            return false;
+        }
+
+        // ensure the host is above the minimum length
+        if (host.length() < 4) {
+            return false;
+        }
+
+        final int firstDot = host.indexOf('.');
+
+        // ensure host contains at least one dot
+        if (firstDot == -1) {
+            return false;
+        }
+
+        // check if the host contains two continuous dots.
+        if (host.indexOf("..") >= 0) {
+            return false;
+        }
+
+        // check if the first host char is a dot.
+        if (host.charAt(0) == '.') {
+            return false;
+        }
+
+        final int secondDot = host.indexOf(".", firstDot + 1);
+
+        // if there's a dot at the end, there needs to be a second dot
+        if (host.charAt(host.length() - 1) == '.' && secondDot == -1) {
+            return false;
+        }
+
+        // Host must not have any disallowed characters; allowI18n dictates whether
+        // host must be ASCII.
+        if (!EMAIL_ALLOWED_CHARS.matchesAllOf(host)
+                || (!allowI18n && !CharMatcher.ascii().matchesAllOf(host))) {
+            return false;
+        }
+
+        if (user.startsWith("\"")) {
+            if (!isQuotedUserValid()) {
+                return false;
+            }
+        } else {
+            // check for white space in the user
+            if (ANY_WHITESPACE.indexIn(user) >= 0) {
+                return false;
+            }
+
+            // the user cannot contain two continuous dots
+            if (user.indexOf("..") >= 0) {
+                return false;
+            }
+
+            // User must not have any disallowed characters; allow I18n dictates whether
+            // user must be ASCII.
+            if (!EMAIL_ALLOWED_CHARS.matchesAllOf(user)
+                    || (!allowI18n && !CharMatcher.ascii().matchesAllOf(user))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean isQuotedUserValid() {
+        final int limit = user.length() - 1;
+        if (limit < 1 || !user.endsWith("\"")) {
+            return false;
+        }
+
+        // Unusual loop bounds (looking only at characters between the outer quotes,
+        // not at either quote character). Plus, i is manipulated within the loop.
+        for (int i = 1; i < limit; ++i) {
+            final char ch = user.charAt(i);
+            if (ch == '"' || ch == 127
+                    // No non-whitespace control chars:
+                    || (ch < 32 && !ANY_WHITESPACE.matches(ch))
+                    // No non-ASCII chars, unless i18n is in effect:
+                    || (ch >= 128 && !allowI18n)) {
+                return false;
+            } else if (ch == '\\') {
+                if (i + 1 < limit) {
+                    ++i; // Skip the quoted character
+                } else {
+                    // We have a trailing backslash -- so it can't be quoting anything.
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean equals(final Object otherObject) {
+        // Do an instance check first as an optimization.
+        if (this == otherObject) {
+            return true;
+        }
+        if (otherObject instanceof EmailAddress) {
+            final EmailAddress otherAddress = (EmailAddress) otherObject;
+            return toString().equals(otherAddress.toString());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        // Arbitrary hash code as a function of both host and user.
+        return toString().hashCode();
+    }
+
+    // accessors
+    public boolean isValid() {
+        return valid;
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    // used to change the host on an email address and rechecks validity
+
+    /**
+     * Changes the host name of the email address and rechecks the address'
+     * validity. Exercise caution when storing EmailAddress instances in
+     * hash-keyed collections. Calling setHost() with a different host name will
+     * change the return value of hashCode.
+     *
+     * @param hostName The new host name of the email address.
+     */
+    public void setHost(final String hostName) {
+        host = hostName;
+        valid = isValidInternal();
+    }
+
+    protected boolean valid = false;
+    protected String user = null;
+    protected String host = null;
+    protected boolean allowI18n = false;
+}
diff --git a/src/com/android/messaging/util/FallbackStrategies.java b/src/com/android/messaging/util/FallbackStrategies.java
new file mode 100644
index 0000000..57c208f
--- /dev/null
+++ b/src/com/android/messaging/util/FallbackStrategies.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides a generic and loose-coupled framework to execute one primary and multiple fallback
+ * strategies for solving a given task.<p>
+ * Basically, what would have been a nasty try-catch that's hard to separate and maintain:
+ * <pre><code>
+ * try {
+ *     // doSomething() that may fail.
+ * } catch (Exception ex) {
+ *     try {
+ *         // fallback1() that may fail.
+ *     } catch (Exception ex2) {
+ *         try {
+ *             // fallback2() that may fail.
+ *         } catch (Exception ex3) {
+ *             // ...
+ *         }
+ *     }
+ * }
+ * </code></pre>
+ * Now becomes:<br>
+ * <pre><code>
+ * FallbackStrategies
+ *      .startWith(something)
+ *      .thenTry(fallback1)
+ *      .thenTry(fallback2)
+ *      .execute();
+ * </code></pre>
+ */
+public class FallbackStrategies<Input, Output> {
+    public interface Strategy<Input, Output> {
+        Output execute(Input params) throws Exception;
+    }
+
+    private final List<Strategy<Input, Output>> mChainedStrategies;
+
+    private FallbackStrategies(final Strategy<Input, Output> primaryStrategy) {
+        mChainedStrategies = new ArrayList<Strategy<Input, Output>>();
+        mChainedStrategies.add(primaryStrategy);
+    }
+
+    public static <Input, Output> FallbackStrategies<Input, Output> startWith(
+            final Strategy<Input, Output> primaryStrategy) {
+        return new FallbackStrategies<Input, Output>(primaryStrategy);
+    }
+
+    public FallbackStrategies<Input, Output> thenTry(final Strategy<Input, Output> strategy) {
+        Assert.isFalse(mChainedStrategies.isEmpty());
+        mChainedStrategies.add(strategy);
+        return this;
+    }
+
+    public Output execute(final Input params) {
+        final int count = mChainedStrategies.size();
+        for (int i = 0; i < count; i++) {
+            final Strategy<Input, Output> strategy = mChainedStrategies.get(i);
+            try {
+                // If succeeds, this will directly return.
+                return strategy.execute(params);
+            } catch (Exception ex) {
+                LogUtil.e(LogUtil.BUGLE_TAG, "Exceptions occured when executing strategy " +
+                        strategy + (i < count - 1 ?
+                                ", attempting fallback " + mChainedStrategies.get(i + 1) :
+                                ", and running out of fallbacks."), ex);
+                // This will fall through and continue with the next strategy (if any).
+            }
+        }
+        // Running out of strategies, return null.
+        // TODO: Should this accept user-defined fallback value other than null?
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/util/FileUtil.java b/src/com/android/messaging/util/FileUtil.java
new file mode 100644
index 0000000..e7d86f2
--- /dev/null
+++ b/src/com/android/messaging/util/FileUtil.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class FileUtil {
+    /** Returns a new file name, ensuring that such a file does not already exist. */
+    private static synchronized File getNewFile(File directory, String extension,
+            String fileNameFormat) throws IOException {
+        final Date date = new Date(System.currentTimeMillis());
+        final SimpleDateFormat dateFormat = new SimpleDateFormat(fileNameFormat);
+        final String numberedFileNameFormat = dateFormat.format(date) + "_%02d" + "." + extension;
+        for (int i = 1; i <= 99; i++) { // Only save 99 of the same file name.
+            final String newName = String.format(Locale.US, numberedFileNameFormat, i);
+            File testFile = new File(directory, newName);
+            if (!testFile.exists()) {
+                testFile.createNewFile();
+                return testFile;
+            }
+        }
+        LogUtil.e(LogUtil.BUGLE_TAG, "Too many duplicate file names: " + numberedFileNameFormat);
+        return null;
+    }
+
+    /**
+     * Creates an unused name to use for creating a new file. The format happens to be similar
+     * to that used by the Android camera application.
+     *
+     * @param directory directory that the file should be saved to
+     * @param contentType of the media being saved
+     * @return file name to be used for creating the new file. The caller is responsible for
+     *   actually creating the file.
+     */
+    public static File getNewFile(File directory, String contentType) throws IOException {
+        String fileExtension = ContentType.getExtensionFromMimeType(contentType);
+        final Context context = Factory.get().getApplicationContext();
+        String fileNameFormat = context.getString(ContentType.isImageType(contentType)
+                ? R.string.new_image_file_name_format : R.string.new_file_name_format);
+        return getNewFile(directory, fileExtension, fileNameFormat);
+    }
+
+    /** Delete everything below and including root */
+    public static void removeFileOrDirectory(File root) {
+        removeFileOrDirectoryExcept(root, null);
+    }
+
+    /** Delete everything below and including root except for the given file */
+    public static void removeFileOrDirectoryExcept(File root, File exclude) {
+        if (root.exists()) {
+            if (root.isDirectory()) {
+                for (File file : root.listFiles()) {
+                    if (exclude == null || !file.equals(exclude)) {
+                        removeFileOrDirectoryExcept(file, exclude);
+                    }
+                }
+                root.delete();
+            } else if (root.isFile()) {
+                root.delete();
+            }
+        }
+    }
+
+    /**
+     * Move all files and folders under a directory into the target.
+     */
+    public static void moveAllContentUnderDirectory(File sourceDir, File targetDir) {
+        if (sourceDir.isDirectory() && targetDir.isDirectory()) {
+            if (isSameOrSubDirectory(sourceDir, targetDir)) {
+                LogUtil.e(LogUtil.BUGLE_TAG, "Can't move directory content since the source " +
+                        "directory is a parent of the target");
+                return;
+            }
+            for (File file : sourceDir.listFiles()) {
+                if (file.isDirectory()) {
+                    final File dirTarget = new File(targetDir, file.getName());
+                    dirTarget.mkdirs();
+                    moveAllContentUnderDirectory(file, dirTarget);
+                } else {
+                    try {
+                        final File fileTarget = new File(targetDir, file.getName());
+                        Files.move(file, fileTarget);
+                    } catch (IOException e) {
+                        LogUtil.e(LogUtil.BUGLE_TAG, "Failed to move files", e);
+                        // Try proceed with the next file.
+                    }
+                }
+            }
+        }
+    }
+
+    // Checks if the file is in /data, and don't allow any app to send personal information.
+    // We're told it's possible to create world readable hardlinks to other apps private data
+    // so we ban all /data file uris.
+    public static boolean isInPrivateDir(Uri uri) {
+        return isFileUriInPrivateDir(uri) || isContentUriInPrivateDir(uri);
+    }
+
+    private static boolean isFileUriInPrivateDir(Uri uri) {
+        if (!UriUtil.isFileUri(uri)) {
+            return false;
+        }
+        final File file = new File(uri.getPath());
+        return FileUtil.isSameOrSubDirectory(Environment.getDataDirectory(), file);
+    }
+
+    private static boolean isContentUriInPrivateDir(Uri uri) {
+        if (!uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+            return false;
+        }
+        try {
+            Context context = Factory.get().getApplicationContext();
+            ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
+            int fd = pfd.getFd();
+            // Use the file descriptor to find out the read file path through symbolic link.
+            Path fdPath = Paths.get("/proc/self/fd/" + fd);
+            Path filePath = java.nio.file.Files.readSymbolicLink(fdPath);
+            pfd.close();
+            return FileUtil.isSameOrSubDirectory(Environment.getDataDirectory(), filePath.toFile());
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Checks, whether the child directory is the same as, or a sub-directory of the base
+     * directory.
+     */
+    private static boolean isSameOrSubDirectory(File base, File child) {
+        try {
+            base = base.getCanonicalFile();
+            child = child.getCanonicalFile();
+            File parentFile = child;
+            while (parentFile != null) {
+                if (base.equals(parentFile)) {
+                    return true;
+                }
+                parentFile = parentFile.getParentFile();
+            }
+            return false;
+        } catch (IOException ex) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error while accessing file", ex);
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/GifTranscoder.java b/src/com/android/messaging/util/GifTranscoder.java
new file mode 100644
index 0000000..65413a0
--- /dev/null
+++ b/src/com/android/messaging/util/GifTranscoder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.text.format.Formatter;
+
+import com.google.common.base.Stopwatch;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Compresses a GIF so it can be sent via MMS.
+ * <p>
+ * The entry point lives in its own class, we can defer loading the native GIF transcoding library
+ * into memory until we actually need it.
+ */
+public class GifTranscoder {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static int MIN_HEIGHT = 100;
+    private static int MIN_WIDTH = 100;
+
+    static {
+        System.loadLibrary("giftranscode");
+    }
+
+    public static boolean transcode(Context context, String filePath, String outFilePath) {
+        if (!isEnabled()) {
+            return false;
+        }
+        final long inputSize = new File(filePath).length();
+        Stopwatch stopwatch = Stopwatch.createStarted();
+        final boolean success = transcodeInternal(filePath, outFilePath);
+        stopwatch.stop();
+        final long elapsedMs = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+        final long outputSize = new File(outFilePath).length();
+        final float compression = (inputSize > 0) ? ((float) outputSize / inputSize) : 0;
+
+        if (success) {
+            LogUtil.i(TAG, String.format("Resized GIF (%s) in %d ms, %s => %s (%.0f%%)",
+                    LogUtil.sanitizePII(filePath),
+                    elapsedMs,
+                    Formatter.formatShortFileSize(context, inputSize),
+                    Formatter.formatShortFileSize(context, outputSize),
+                    compression * 100.0f));
+        }
+        return success;
+    }
+
+    private static native boolean transcodeInternal(String filePath, String outFilePath);
+
+    /**
+     * Estimates the size of a GIF transcoded from a GIF with the specified size.
+     */
+    public static long estimateFileSizeAfterTranscode(long fileSize) {
+        // I tested transcoding on ~70 GIFs and found that the transcoded files are in general
+        // about 25-35% the size of the original. This compression ratio is very consistent for the
+        // class of GIFs we care about most: those converted from video clips and 1-3 MB in size.
+        return (long) (fileSize * 0.35f);
+    }
+
+    public static boolean canBeTranscoded(int width, int height) {
+        if (!isEnabled()) {
+            return false;
+        }
+        return width >= MIN_WIDTH && height >= MIN_HEIGHT;
+    }
+
+    private static boolean isEnabled() {
+        final boolean enabled = BugleGservices.get().getBoolean(
+                BugleGservicesKeys.ENABLE_GIF_TRANSCODING,
+                BugleGservicesKeys.ENABLE_GIF_TRANSCODING_DEFAULT);
+        if (!enabled) {
+            LogUtil.w(TAG, "GIF transcoding is disabled");
+        }
+        return enabled;
+    }
+}
diff --git a/src/com/android/messaging/util/ImageUtils.java b/src/com/android/messaging/util/ImageUtils.java
new file mode 100644
index 0000000..e541d69
--- /dev/null
+++ b/src/com/android/messaging/util/ImageUtils.java
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader.TileMode;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.provider.MediaStore;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.media.ImageRequest;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.android.messaging.util.exif.ExifInterface;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.io.Files;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+public class ImageUtils {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final int MAX_OOM_COUNT = 1;
+    private static final byte[] GIF87_HEADER = "GIF87a".getBytes(Charset.forName("US-ASCII"));
+    private static final byte[] GIF89_HEADER = "GIF89a".getBytes(Charset.forName("US-ASCII"));
+
+    // Used for drawBitmapWithCircleOnCanvas.
+    // Default color is transparent for both circle background and stroke.
+    public static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = 0;
+    public static final int DEFAULT_CIRCLE_STROKE_COLOR = 0;
+
+    private static volatile ImageUtils sInstance;
+
+    public static ImageUtils get() {
+        if (sInstance == null) {
+            synchronized (ImageUtils.class) {
+                if (sInstance == null) {
+                    sInstance = new ImageUtils();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    @VisibleForTesting
+    public static void set(final ImageUtils imageUtils) {
+        sInstance = imageUtils;
+    }
+
+    /**
+     * Transforms a bitmap into a byte array.
+     *
+     * @param quality Value between 0 and 100 that the compressor uses to discern what quality the
+     *                resulting bytes should be
+     * @param bitmap Bitmap to convert into bytes
+     * @return byte array of bitmap
+     */
+    public static byte[] bitmapToBytes(final Bitmap bitmap, final int quality)
+            throws OutOfMemoryError {
+        boolean done = false;
+        int oomCount = 0;
+        byte[] imageBytes = null;
+        while (!done) {
+            try {
+                final ByteArrayOutputStream os = new ByteArrayOutputStream();
+                bitmap.compress(Bitmap.CompressFormat.JPEG, quality, os);
+                imageBytes = os.toByteArray();
+                done = true;
+            } catch (final OutOfMemoryError e) {
+                LogUtil.w(TAG, "OutOfMemory converting bitmap to bytes.");
+                oomCount++;
+                if (oomCount <= MAX_OOM_COUNT) {
+                    Factory.get().reclaimMemory();
+                } else {
+                    done = true;
+                    LogUtil.w(TAG, "Failed to convert bitmap to bytes. Out of Memory.");
+                }
+                throw e;
+            }
+        }
+        return imageBytes;
+    }
+
+    /**
+     * Given the source bitmap and a canvas, draws the bitmap through a circular
+     * mask. Only draws a circle with diameter equal to the destination width.
+     *
+     * @param bitmap The source bitmap to draw.
+     * @param canvas The canvas to draw it on.
+     * @param source The source bound of the bitmap.
+     * @param dest The destination bound on the canvas.
+     * @param bitmapPaint Optional Paint object for the bitmap
+     * @param fillBackground when set, fill the circle with backgroundColor
+     * @param strokeColor draw a border outside the circle with strokeColor
+     */
+    public static void drawBitmapWithCircleOnCanvas(final Bitmap bitmap, final Canvas canvas,
+            final RectF source, final RectF dest, @Nullable Paint bitmapPaint,
+            final boolean fillBackground, final int backgroundColor, int strokeColor) {
+        // Draw bitmap through shader first.
+        final BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
+        final Matrix matrix = new Matrix();
+
+        // Fit bitmap to bounds.
+        matrix.setRectToRect(source, dest, Matrix.ScaleToFit.CENTER);
+
+        shader.setLocalMatrix(matrix);
+
+        if (bitmapPaint == null) {
+            bitmapPaint = new Paint();
+        }
+
+        bitmapPaint.setAntiAlias(true);
+        if (fillBackground) {
+            bitmapPaint.setColor(backgroundColor);
+            canvas.drawCircle(dest.centerX(), dest.centerX(), dest.width() / 2f, bitmapPaint);
+        }
+
+        bitmapPaint.setShader(shader);
+        canvas.drawCircle(dest.centerX(), dest.centerX(), dest.width() / 2f, bitmapPaint);
+        bitmapPaint.setShader(null);
+
+        if (strokeColor != 0) {
+            final Paint stroke = new Paint();
+            stroke.setAntiAlias(true);
+            stroke.setColor(strokeColor);
+            stroke.setStyle(Paint.Style.STROKE);
+            final float strokeWidth = 6f;
+            stroke.setStrokeWidth(strokeWidth);
+            canvas.drawCircle(dest.centerX(),
+                    dest.centerX(),
+                    dest.width() / 2f - stroke.getStrokeWidth() / 2f,
+                    stroke);
+        }
+    }
+
+    /**
+     * Sets a drawable to the background of a view. setBackgroundDrawable() is deprecated since
+     * JB and replaced by setBackground().
+     */
+    @SuppressWarnings("deprecation")
+    public static void setBackgroundDrawableOnView(final View view, final Drawable drawable) {
+        if (OsUtil.isAtLeastJB()) {
+            view.setBackground(drawable);
+        } else {
+            view.setBackgroundDrawable(drawable);
+        }
+    }
+
+    /**
+     * Based on the input bitmap bounds given by BitmapFactory.Options, compute the required
+     * sub-sampling size for loading a scaled down version of the bitmap to the required size
+     * @param options a BitmapFactory.Options instance containing the bounds info of the bitmap
+     * @param reqWidth the desired width of the bitmap. Can be ImageRequest.UNSPECIFIED_SIZE.
+     * @param reqHeight the desired height of the bitmap.  Can be ImageRequest.UNSPECIFIED_SIZE.
+     * @return
+     */
+    public int calculateInSampleSize(
+            final BitmapFactory.Options options, final int reqWidth, final int reqHeight) {
+        // Raw height and width of image
+        final int height = options.outHeight;
+        final int width = options.outWidth;
+        int inSampleSize = 1;
+
+        final boolean checkHeight = reqHeight != ImageRequest.UNSPECIFIED_SIZE;
+        final boolean checkWidth = reqWidth != ImageRequest.UNSPECIFIED_SIZE;
+        if ((checkHeight && height > reqHeight) ||
+                (checkWidth && width > reqWidth)) {
+
+            final int halfHeight = height / 2;
+            final int halfWidth = width / 2;
+
+            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
+            // height and width larger than the requested height and width.
+            while ((!checkHeight || (halfHeight / inSampleSize) > reqHeight)
+                    && (!checkWidth || (halfWidth / inSampleSize) > reqWidth)) {
+                inSampleSize *= 2;
+            }
+        }
+
+        return inSampleSize;
+    }
+
+    private static final String[] MEDIA_CONTENT_PROJECTION = new String[] {
+        MediaStore.MediaColumns.MIME_TYPE
+    };
+
+    private static final int INDEX_CONTENT_TYPE = 0;
+
+    @DoesNotRunOnMainThread
+    public static String getContentType(final ContentResolver cr, final Uri uri) {
+        // Figure out the content type of media.
+        String contentType = null;
+        Cursor cursor = null;
+        if (UriUtil.isMediaStoreUri(uri)) {
+            try {
+                cursor = cr.query(uri, MEDIA_CONTENT_PROJECTION, null, null, null);
+
+                if (cursor != null && cursor.moveToFirst()) {
+                    contentType = cursor.getString(INDEX_CONTENT_TYPE);
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+        if (contentType == null) {
+            // Last ditch effort to get the content type. Look at the file extension.
+            contentType = ContentType.getContentTypeFromExtension(uri.toString(),
+                    ContentType.IMAGE_UNSPECIFIED);
+        }
+        return contentType;
+    }
+
+    /**
+     * @param context Android context
+     * @param uri Uri to the image data
+     * @return The exif orientation value for the image in the specified uri
+     */
+    public static int getOrientation(final Context context, final Uri uri) {
+        try {
+            return getOrientation(context.getContentResolver().openInputStream(uri));
+        } catch (FileNotFoundException e) {
+            LogUtil.e(TAG, "getOrientation couldn't open: " + uri, e);
+        }
+        return android.media.ExifInterface.ORIENTATION_UNDEFINED;
+    }
+
+    /**
+     * @param inputStream The stream to the image file.  Closed on completion
+     * @return The exif orientation value for the image in the specified stream
+     */
+    public static int getOrientation(final InputStream inputStream) {
+        int orientation = android.media.ExifInterface.ORIENTATION_UNDEFINED;
+        if (inputStream != null) {
+            try {
+                final ExifInterface exifInterface = new ExifInterface();
+                exifInterface.readExif(inputStream);
+                final Integer orientationValue =
+                        exifInterface.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+                if (orientationValue != null) {
+                    orientation = orientationValue.intValue();
+                }
+            } catch (IOException e) {
+                // If the image if GIF, PNG, or missing exif header, just use the defaults
+            } finally {
+                try {
+                    if (inputStream != null) {
+                        inputStream.close();
+                    }
+                } catch (IOException e) {
+                    LogUtil.e(TAG, "getOrientation error closing input stream", e);
+                }
+            }
+        }
+        return orientation;
+    }
+
+    /**
+     * Returns whether the resource is a GIF image.
+     */
+    public static boolean isGif(String contentType, Uri contentUri) {
+        if (TextUtils.equals(contentType, ContentType.IMAGE_GIF)) {
+            return true;
+        }
+        if (ContentType.isImageType(contentType)) {
+            try {
+                ContentResolver contentResolver = Factory.get().getApplicationContext()
+                        .getContentResolver();
+                InputStream inputStream = contentResolver.openInputStream(contentUri);
+                return ImageUtils.isGif(inputStream);
+            } catch (Exception e) {
+                LogUtil.w(TAG, "Could not open GIF input stream", e);
+            }
+        }
+        // Assume anything with a non-image content type is not a GIF
+        return false;
+    }
+
+    /**
+     * @param inputStream The stream to the image file. Closed on completion
+     * @return Whether the image stream represents a GIF
+     */
+    public static boolean isGif(InputStream inputStream) {
+        if (inputStream != null) {
+            try {
+                byte[] gifHeaderBytes = new byte[6];
+                int value = inputStream.read(gifHeaderBytes, 0, 6);
+                if (value == 6) {
+                    return Arrays.equals(gifHeaderBytes, GIF87_HEADER)
+                            || Arrays.equals(gifHeaderBytes, GIF89_HEADER);
+                }
+            } catch (IOException e) {
+                return false;
+            } finally {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Read an image and compress it to particular max dimensions and size.
+     * Used to ensure images can fit in an MMS.
+     * TODO: This uses memory very inefficiently as it processes the whole image as a unit
+     *  (rather than slice by slice) but system JPEG functions do not support slicing and dicing.
+     */
+    public static class ImageResizer {
+
+        /**
+         * The quality parameter which is used to compress JPEG images.
+         */
+        private static final int IMAGE_COMPRESSION_QUALITY = 95;
+        /**
+         * The minimum quality parameter which is used to compress JPEG images.
+         */
+        private static final int MINIMUM_IMAGE_COMPRESSION_QUALITY = 50;
+
+        /**
+         * Minimum factor to reduce quality value
+         */
+        private static final double QUALITY_SCALE_DOWN_RATIO = 0.85f;
+
+        /**
+         * Maximum passes through the resize loop before failing permanently
+         */
+        private static final int NUMBER_OF_RESIZE_ATTEMPTS = 6;
+
+        /**
+         * Amount to scale down the picture when it doesn't fit
+         */
+        private static final float MIN_SCALE_DOWN_RATIO = 0.75f;
+
+        /**
+         * When computing sampleSize target scaling of no more than this ratio
+         */
+        private static final float MAX_TARGET_SCALE_FACTOR = 1.5f;
+
+
+        // Current sample size for subsampling image during initial decode
+        private int mSampleSize;
+        // Current bitmap holding initial decoded source image
+        private Bitmap mDecoded;
+        // If scaling is needed this holds the scaled bitmap (else should equal mDecoded)
+        private Bitmap mScaled;
+        // Current JPEG compression quality to use when compressing image
+        private int mQuality;
+        // Current factor to scale down decoded image before compressing
+        private float mScaleFactor;
+        // Flag keeping track of whether cache memory has been reclaimed
+        private boolean mHasReclaimedMemory;
+
+        // Initial size of the image (typically provided but can be UNSPECIFIED_SIZE)
+        private int mWidth;
+        private int mHeight;
+        // Orientation params of image as read from EXIF data
+        private final ExifInterface.OrientationParams mOrientationParams;
+        // Matrix to undo orientation and scale at the same time
+        private final Matrix mMatrix;
+        // Size limit as provided by MMS library
+        private final int mWidthLimit;
+        private final int mHeightLimit;
+        private final int mByteLimit;
+        //  Uri from which to read source image
+        private final Uri mUri;
+        // Application context
+        private final Context mContext;
+        // Cached value of bitmap factory options
+        private final BitmapFactory.Options mOptions;
+        private final String mContentType;
+
+        private final int mMemoryClass;
+
+        /**
+         * Return resized (compressed) image (else null)
+         *
+         * @param width The width of the image (if known)
+         * @param height The height of the image (if known)
+         * @param orientation The orientation of the image as an ExifInterface constant
+         * @param widthLimit The width limit, in pixels
+         * @param heightLimit The height limit, in pixels
+         * @param byteLimit The binary size limit, in bytes
+         * @param uri Uri to the image data
+         * @param context Needed to open the image
+         * @param contentType of image
+         * @return encoded image meeting size requirements else null
+         */
+        public static byte[] getResizedImageData(final int width, final int height,
+                final int orientation, final int widthLimit, final int heightLimit,
+                final int byteLimit, final Uri uri, final Context context,
+                final String contentType) {
+            final ImageResizer resizer = new ImageResizer(width, height, orientation,
+                    widthLimit, heightLimit, byteLimit, uri, context, contentType);
+            return resizer.resize();
+        }
+
+        /**
+         * Create and initialize an image resizer
+         */
+        private ImageResizer(final int width, final int height, final int orientation,
+                final int widthLimit, final int heightLimit, final int byteLimit, final Uri uri,
+                final Context context, final String contentType) {
+            mWidth = width;
+            mHeight = height;
+            mOrientationParams = ExifInterface.getOrientationParams(orientation);
+            mMatrix = new Matrix();
+            mWidthLimit = widthLimit;
+            mHeightLimit = heightLimit;
+            mByteLimit = byteLimit;
+            mUri = uri;
+            mWidth = width;
+            mContext = context;
+            mQuality = IMAGE_COMPRESSION_QUALITY;
+            mScaleFactor = 1.0f;
+            mHasReclaimedMemory = false;
+            mOptions = new BitmapFactory.Options();
+            mOptions.inScaled = false;
+            mOptions.inDensity = 0;
+            mOptions.inTargetDensity = 0;
+            mOptions.inSampleSize = 1;
+            mOptions.inJustDecodeBounds = false;
+            mOptions.inMutable = false;
+            final ActivityManager am =
+                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+            mMemoryClass = Math.max(16, am.getMemoryClass());
+            mContentType = contentType;
+        }
+
+        /**
+         * Try to compress the image
+         *
+         * @return encoded image meeting size requirements else null
+         */
+        private byte[] resize() {
+            return ImageUtils.isGif(mContentType, mUri) ? resizeGifImage() : resizeStaticImage();
+        }
+
+        private byte[] resizeGifImage() {
+            byte[] bytesToReturn = null;
+            final String inputFilePath;
+            if (MediaScratchFileProvider.isMediaScratchSpaceUri(mUri)) {
+                inputFilePath = MediaScratchFileProvider.getFileFromUri(mUri).getAbsolutePath();
+            } else {
+                if (!UriUtil.isFileUri(mUri)) {
+                    Assert.fail("Expected a GIF file uri, but actual uri = " + mUri.toString());
+                }
+                inputFilePath = mUri.getPath();
+            }
+
+            if (GifTranscoder.canBeTranscoded(mWidth, mHeight)) {
+                // Needed to perform the transcoding so that the gif can continue to play in the
+                // conversation while the sending is taking place
+                final Uri tmpUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("gif");
+                final File outputFile = MediaScratchFileProvider.getFileFromUri(tmpUri);
+                final String outputFilePath = outputFile.getAbsolutePath();
+
+                final boolean success =
+                        GifTranscoder.transcode(mContext, inputFilePath, outputFilePath);
+                if (success) {
+                    try {
+                        bytesToReturn = Files.toByteArray(outputFile);
+                    } catch (IOException e) {
+                        LogUtil.e(TAG, "Could not create FileInputStream with path of "
+                                + outputFilePath, e);
+                    }
+                }
+
+                // Need to clean up the new file created to compress the gif
+                mContext.getContentResolver().delete(tmpUri, null, null);
+            } else {
+                // We don't want to transcode the gif because its image dimensions would be too
+                // small so just return the bytes of the original gif
+                try {
+                    bytesToReturn = Files.toByteArray(new File(inputFilePath));
+                } catch (IOException e) {
+                    LogUtil.e(TAG,
+                            "Could not create FileInputStream with path of " + inputFilePath, e);
+                }
+            }
+
+            return bytesToReturn;
+        }
+
+        private byte[] resizeStaticImage() {
+            if (!ensureImageSizeSet()) {
+                // Cannot read image size
+                return null;
+            }
+            // Find incoming image size
+            if (!canBeCompressed()) {
+                return null;
+            }
+
+            //  Decode image - if out of memory - reclaim memory and retry
+            try {
+                for (int attempts = 0; attempts < NUMBER_OF_RESIZE_ATTEMPTS; attempts++) {
+                    final byte[] encoded = recodeImage(attempts);
+
+                    // Only return data within the limit
+                    if (encoded != null && encoded.length <= mByteLimit) {
+                        return encoded;
+                    } else {
+                        final int currentSize = (encoded == null ? 0 : encoded.length);
+                        updateRecodeParameters(currentSize);
+                    }
+                }
+            } catch (final FileNotFoundException e) {
+                LogUtil.e(TAG, "File disappeared during resizing");
+            } finally {
+                // Release all bitmaps
+                if (mScaled != null && mScaled != mDecoded) {
+                    mScaled.recycle();
+                }
+                if (mDecoded != null) {
+                    mDecoded.recycle();
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Ensure that the width and height of the source image are known
+         * @return flag indicating whether size is known
+         */
+        private boolean ensureImageSizeSet() {
+            if (mWidth == MessagingContentProvider.UNSPECIFIED_SIZE ||
+                    mHeight == MessagingContentProvider.UNSPECIFIED_SIZE) {
+                // First get the image data (compressed)
+                final ContentResolver cr = mContext.getContentResolver();
+                InputStream inputStream = null;
+                // Find incoming image size
+                try {
+                    mOptions.inJustDecodeBounds = true;
+                    inputStream = cr.openInputStream(mUri);
+                    BitmapFactory.decodeStream(inputStream, null, mOptions);
+
+                    mWidth = mOptions.outWidth;
+                    mHeight = mOptions.outHeight;
+                    mOptions.inJustDecodeBounds = false;
+
+                    return true;
+                } catch (final FileNotFoundException e) {
+                    LogUtil.e(TAG, "Could not open file corresponding to uri " + mUri, e);
+                } catch (final NullPointerException e) {
+                    LogUtil.e(TAG, "NPE trying to open the uri " + mUri, e);
+                } finally {
+                    if (inputStream != null) {
+                        try {
+                            inputStream.close();
+                        } catch (final IOException e) {
+                            // Nothing to do
+                        }
+                    }
+                }
+
+                return false;
+            }
+            return true;
+        }
+
+        /**
+         * Choose an initial subsamplesize that ensures the decoded image is no more than
+         * MAX_TARGET_SCALE_FACTOR bigger than largest supported image and that it is likely to
+         * compress to smaller than the target size (assuming compression down to 1 bit per pixel).
+         * @return whether the image can be down subsampled
+         */
+        private boolean canBeCompressed() {
+            final boolean logv = LogUtil.isLoggable(LogUtil.BUGLE_IMAGE_TAG, LogUtil.VERBOSE);
+
+            int imageHeight = mHeight;
+            int imageWidth = mWidth;
+
+            // Assume can use half working memory to decode the initial image (4 bytes per pixel)
+            final int workingMemoryPixelLimit = (mMemoryClass * 1024 * 1024 / 8);
+            // Target 1 bits per pixel in final compressed image
+            final int finalSizePixelLimit = mByteLimit * 8;
+            // When choosing to halve the resolution - only do so the image will still be too big
+            // after scaling by MAX_TARGET_SCALE_FACTOR
+            final int heightLimitWithSlop = (int) (mHeightLimit * MAX_TARGET_SCALE_FACTOR);
+            final int widthLimitWithSlop = (int) (mWidthLimit * MAX_TARGET_SCALE_FACTOR);
+            final int pixelLimitWithSlop = (int) (finalSizePixelLimit *
+                    MAX_TARGET_SCALE_FACTOR * MAX_TARGET_SCALE_FACTOR);
+            final int pixelLimit = Math.min(pixelLimitWithSlop, workingMemoryPixelLimit);
+
+            int sampleSize = 1;
+            boolean fits = (imageHeight < heightLimitWithSlop &&
+                    imageWidth < widthLimitWithSlop &&
+                    imageHeight * imageWidth < pixelLimit);
+
+            // Compare sizes to compute sub-sampling needed
+            while (!fits) {
+                sampleSize = sampleSize * 2;
+                // Note that recodeImage may try using mSampleSize * 2. Hence we use the factor of 4
+                if (sampleSize >= (Integer.MAX_VALUE / 4)) {
+                    LogUtil.w(LogUtil.BUGLE_IMAGE_TAG, String.format(
+                            "Cannot resize image: widthLimit=%d heightLimit=%d byteLimit=%d " +
+                            "imageWidth=%d imageHeight=%d", mWidthLimit, mHeightLimit, mByteLimit,
+                            mWidth, mHeight));
+                    Assert.fail("Image cannot be resized"); // http://b/18926934
+                    return false;
+                }
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "computeInitialSampleSize: Increasing sampleSize to " + sampleSize
+                            + " as h=" + imageHeight + " vs " + heightLimitWithSlop
+                            + " w=" + imageWidth  + " vs " +  widthLimitWithSlop
+                            + " p=" + imageHeight * imageWidth + " vs " + pixelLimit);
+                }
+                imageHeight = mHeight / sampleSize;
+                imageWidth = mWidth / sampleSize;
+                fits = (imageHeight < heightLimitWithSlop &&
+                        imageWidth < widthLimitWithSlop &&
+                        imageHeight * imageWidth < pixelLimit);
+            }
+
+            if (logv) {
+                LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                        "computeInitialSampleSize: Initial sampleSize " + sampleSize
+                        + " for h=" + imageHeight + " vs " + heightLimitWithSlop
+                        + " w=" + imageWidth  + " vs " +  widthLimitWithSlop
+                        + " p=" + imageHeight * imageWidth + " vs " + pixelLimit);
+            }
+
+            mSampleSize = sampleSize;
+            return true;
+        }
+
+        /**
+         * Recode the image from initial Uri to encoded JPEG
+         * @param attempt Attempt number
+         * @return encoded image
+         */
+        private byte[] recodeImage(final int attempt) throws FileNotFoundException {
+            byte[] encoded = null;
+            try {
+                final ContentResolver cr = mContext.getContentResolver();
+                final boolean logv = LogUtil.isLoggable(LogUtil.BUGLE_IMAGE_TAG, LogUtil.VERBOSE);
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG, "getResizedImageData: attempt=" + attempt
+                            + " limit (w=" + mWidthLimit + " h=" + mHeightLimit + ") quality="
+                            + mQuality + " scale=" + mScaleFactor + " sampleSize=" + mSampleSize);
+                }
+                if (mScaled == null) {
+                    if (mDecoded == null) {
+                        mOptions.inSampleSize = mSampleSize;
+                        try (final InputStream inputStream = cr.openInputStream(mUri)) {
+                            mDecoded = BitmapFactory.decodeStream(inputStream, null, mOptions);
+                        } catch (IOException e) {
+                            // Ignore
+                        }
+                        if (mDecoded == null) {
+                            if (logv) {
+                                LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                                        "getResizedImageData: got empty decoded bitmap");
+                            }
+                            return null;
+                        }
+                    }
+                    if (logv) {
+                        LogUtil.v(LogUtil.BUGLE_IMAGE_TAG, "getResizedImageData: decoded w,h="
+                                + mDecoded.getWidth() + "," + mDecoded.getHeight());
+                    }
+                    // Make sure to scale the decoded image if dimension is not within limit
+                    final int decodedWidth = mDecoded.getWidth();
+                    final int decodedHeight = mDecoded.getHeight();
+                    if (decodedWidth > mWidthLimit || decodedHeight > mHeightLimit) {
+                        final float minScaleFactor = Math.max(
+                                mWidthLimit == 0 ? 1.0f :
+                                    (float) decodedWidth / (float) mWidthLimit,
+                                    mHeightLimit == 0 ? 1.0f :
+                                        (float) decodedHeight / (float) mHeightLimit);
+                        if (mScaleFactor < minScaleFactor) {
+                            mScaleFactor = minScaleFactor;
+                        }
+                    }
+                    if (mScaleFactor > 1.0 || mOrientationParams.rotation != 0) {
+                        mMatrix.reset();
+                        mMatrix.postRotate(mOrientationParams.rotation);
+                        mMatrix.postScale(mOrientationParams.scaleX / mScaleFactor,
+                                mOrientationParams.scaleY / mScaleFactor);
+                        mScaled = Bitmap.createBitmap(mDecoded, 0, 0, decodedWidth, decodedHeight,
+                                mMatrix, false /* filter */);
+                        if (mScaled == null) {
+                            if (logv) {
+                                LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                                        "getResizedImageData: got empty scaled bitmap");
+                            }
+                            return null;
+                        }
+                        if (logv) {
+                            LogUtil.v(LogUtil.BUGLE_IMAGE_TAG, "getResizedImageData: scaled w,h="
+                                    + mScaled.getWidth() + "," + mScaled.getHeight());
+                        }
+                    } else {
+                        mScaled = mDecoded;
+                    }
+                }
+                // Now encode it at current quality
+                encoded = ImageUtils.bitmapToBytes(mScaled, mQuality);
+                if (encoded != null && logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "getResizedImageData: Encoded down to " + encoded.length + "@"
+                                    + mScaled.getWidth() + "/" + mScaled.getHeight() + "~"
+                                    + mQuality);
+                }
+            } catch (final OutOfMemoryError e) {
+                LogUtil.w(LogUtil.BUGLE_IMAGE_TAG,
+                        "getResizedImageData - image too big (OutOfMemoryError), will try "
+                                + " with smaller scale factor");
+                // fall through and keep trying with more compression
+            }
+            return encoded;
+        }
+
+        /**
+         * When image recode fails this method updates compression parameters for the next attempt
+         * @param currentSize encoded image size (will be 0 if OOM)
+         */
+        private void updateRecodeParameters(final int currentSize) {
+            final boolean logv = LogUtil.isLoggable(LogUtil.BUGLE_IMAGE_TAG, LogUtil.VERBOSE);
+            // Only return data within the limit
+            if (currentSize > 0 &&
+                    mQuality > MINIMUM_IMAGE_COMPRESSION_QUALITY) {
+                // First if everything succeeded but failed to hit target size
+                // Try quality proportioned to sqrt of size over size limit
+                mQuality = Math.max(MINIMUM_IMAGE_COMPRESSION_QUALITY,
+                        Math.min((int) (mQuality * Math.sqrt((1.0 * mByteLimit) / currentSize)),
+                                (int) (mQuality * QUALITY_SCALE_DOWN_RATIO)));
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "getResizedImageData: Retrying at quality " + mQuality);
+                }
+            } else if (currentSize > 0 &&
+                    mScaleFactor < 2.0 * MIN_SCALE_DOWN_RATIO * MIN_SCALE_DOWN_RATIO) {
+                // JPEG compression failed to hit target size - need smaller image
+                // First try scaling by a little (< factor of 2) just so long resulting scale down
+                // ratio is still significantly bigger than next subsampling step
+                // i.e. mScaleFactor/MIN_SCALE_DOWN_RATIO (new scaling factor) <
+                //       2.0 / MIN_SCALE_DOWN_RATIO (arbitrary limit)
+                mQuality = IMAGE_COMPRESSION_QUALITY;
+                mScaleFactor = mScaleFactor / MIN_SCALE_DOWN_RATIO;
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "getResizedImageData: Retrying at scale " + mScaleFactor);
+                }
+                // Release scaled bitmap to trigger rescaling
+                if (mScaled != null && mScaled != mDecoded) {
+                    mScaled.recycle();
+                }
+                mScaled = null;
+            } else if (currentSize <= 0 && !mHasReclaimedMemory) {
+                // Then before we subsample try cleaning up our cached memory
+                Factory.get().reclaimMemory();
+                mHasReclaimedMemory = true;
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "getResizedImageData: Retrying after reclaiming memory ");
+                }
+            } else {
+                // Last resort - subsample image by another factor of 2 and try again
+                mSampleSize = mSampleSize * 2;
+                mQuality = IMAGE_COMPRESSION_QUALITY;
+                mScaleFactor = 1.0f;
+                if (logv) {
+                    LogUtil.v(LogUtil.BUGLE_IMAGE_TAG,
+                            "getResizedImageData: Retrying at sampleSize " + mSampleSize);
+                }
+                // Release all bitmaps to trigger subsampling
+                if (mScaled != null && mScaled != mDecoded) {
+                    mScaled.recycle();
+                }
+                mScaled = null;
+                if (mDecoded != null) {
+                    mDecoded.recycle();
+                    mDecoded = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Scales and center-crops a bitmap to the size passed in and returns the new bitmap.
+     *
+     * @param source Bitmap to scale and center-crop
+     * @param newWidth destination width
+     * @param newHeight destination height
+     * @return Bitmap scaled and center-cropped bitmap
+     */
+    public static Bitmap scaleCenterCrop(final Bitmap source, final int newWidth,
+            final int newHeight) {
+        final int sourceWidth = source.getWidth();
+        final int sourceHeight = source.getHeight();
+
+        // Compute the scaling factors to fit the new height and width, respectively.
+        // To cover the final image, the final scaling will be the bigger
+        // of these two.
+        final float xScale = (float) newWidth / sourceWidth;
+        final float yScale = (float) newHeight / sourceHeight;
+        final float scale = Math.max(xScale, yScale);
+
+        // Now get the size of the source bitmap when scaled
+        final float scaledWidth = scale * sourceWidth;
+        final float scaledHeight = scale * sourceHeight;
+
+        // Let's find out the upper left coordinates if the scaled bitmap
+        // should be centered in the new size give by the parameters
+        final float left = (newWidth - scaledWidth) / 2;
+        final float top = (newHeight - scaledHeight) / 2;
+
+        // The target rectangle for the new, scaled version of the source bitmap will now
+        // be
+        final RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
+
+        // Finally, we create a new bitmap of the specified size and draw our new,
+        // scaled bitmap onto it.
+        final Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
+        final Canvas canvas = new Canvas(dest);
+        canvas.drawBitmap(source, null, targetRect, null);
+
+        return dest;
+    }
+
+    /**
+     *  The drawable can be a Nine-Patch. If we directly use the same drawable instance for each
+     *  drawable of different sizes, then the drawable sizes would interfere with each other. The
+     *  solution here is to create a new drawable instance for every time with the SAME
+     *  ConstantState (i.e. sharing the same common state such as the bitmap, so that we don't have
+     *  to recreate the bitmap resource), and apply the different properties on top (nine-patch
+     *  size and color tint).
+     *
+     *  TODO: we are creating new drawable instances here, but there are optimizations that
+     *  can be made. For example, message bubbles shouldn't need the mutate() call and the
+     *  play/pause buttons shouldn't need to create new drawable from the constant state.
+     */
+    public static Drawable getTintedDrawable(final Context context, final Drawable drawable,
+            final int color) {
+        // For some reason occassionally drawables on JB has a null constant state
+        final Drawable.ConstantState constantStateDrawable = drawable.getConstantState();
+        final Drawable retDrawable = (constantStateDrawable != null)
+                ? constantStateDrawable.newDrawable(context.getResources()).mutate()
+                : drawable;
+        retDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+        return retDrawable;
+    }
+
+    /**
+     * Decodes image resource header and returns the image size.
+     */
+    public static Rect decodeImageBounds(final Context context, final Uri imageUri) {
+        final ContentResolver cr = context.getContentResolver();
+        try {
+            final InputStream inputStream = cr.openInputStream(imageUri);
+            if (inputStream != null) {
+                try {
+                    BitmapFactory.Options options = new BitmapFactory.Options();
+                    options.inJustDecodeBounds = true;
+                    BitmapFactory.decodeStream(inputStream, null, options);
+                    return new Rect(0, 0, options.outWidth, options.outHeight);
+                } finally {
+                    try {
+                        inputStream.close();
+                    } catch (IOException e) {
+                        // Do nothing.
+                    }
+                }
+            }
+        } catch (FileNotFoundException e) {
+            LogUtil.e(TAG, "Couldn't open input stream for uri = " + imageUri);
+        }
+        return new Rect(0, 0, ImageRequest.UNSPECIFIED_SIZE, ImageRequest.UNSPECIFIED_SIZE);
+    }
+}
diff --git a/src/com/android/messaging/util/ImeUtil.java b/src/com/android/messaging/util/ImeUtil.java
new file mode 100644
index 0000000..3f033d0
--- /dev/null
+++ b/src/com/android/messaging/util/ImeUtil.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class ImeUtil {
+    public interface ImeStateObserver {
+        void onImeStateChanged(boolean imeOpen);
+    }
+
+    public interface ImeStateHost {
+        void onDisplayHeightChanged(int heightMeasureSpec);
+        void registerImeStateObserver(ImeUtil.ImeStateObserver observer);
+        void unregisterImeStateObserver(ImeUtil.ImeStateObserver observer);
+        boolean isImeOpen();
+    }
+
+    private static volatile ImeUtil sInstance;
+
+    // Used to clear the static cached instance of ImeUtil during testing.  This is necessary
+    // because a previous test may have installed a mocked instance (or vice versa).
+    public static void clearInstance() {
+        sInstance = null;
+    }
+    public static ImeUtil get() {
+        if (sInstance == null) {
+            synchronized (ImeUtil.class) {
+                if (sInstance == null) {
+                    sInstance = new ImeUtil();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    @VisibleForTesting
+    public static void set(final ImeUtil imeUtil) {
+        sInstance = imeUtil;
+    }
+
+    public void hideImeKeyboard(@NonNull final Context context, @NonNull final View v) {
+        Assert.notNull(context);
+        Assert.notNull(v);
+
+        final InputMethodManager inputMethodManager =
+                (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (inputMethodManager != null) {
+            inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0 /* flags */);
+        }
+    }
+
+    public void showImeKeyboard(@NonNull final Context context, @NonNull final View v) {
+        Assert.notNull(context);
+        Assert.notNull(v);
+
+        final InputMethodManager inputMethodManager =
+                (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (inputMethodManager != null) {
+            v.requestFocus();
+            inputMethodManager.showSoftInput(v, 0 /* flags */);
+        }
+    }
+
+    public static void hideSoftInput(@NonNull final Context context, @NonNull final View v) {
+        final InputMethodManager inputMethodManager =
+                (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+    }
+}
diff --git a/src/com/android/messaging/util/LogSaver.java b/src/com/android/messaging/util/LogSaver.java
new file mode 100644
index 0000000..7d1f2fd
--- /dev/null
+++ b/src/com/android/messaging/util/LogSaver.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.os.Process;
+import android.util.Log;
+
+import com.android.messaging.Factory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.logging.FileHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Save the app's own log to dump along with adb bugreport
+ */
+public abstract class LogSaver {
+    /**
+     * Writes the accumulated log entries, from oldest to newest, to the specified PrintWriter.
+     * Log lines are emitted in much the same form as logcat -v threadtime -- specifically,
+     * lines will include a timestamp, pid, tid, level, and tag.
+     *
+     * @param writer The PrintWriter to output
+     */
+    public abstract void dump(PrintWriter writer);
+
+    /**
+     * Log a line
+     *
+     * @param level The log level to use
+     * @param tag The log tag
+     * @param msg The message of the log line
+     */
+    public abstract void log(int level, String tag, String msg);
+
+    /**
+     * Check if the LogSaver still matches the current Gservices settings
+     *
+     * @return true if matches, false otherwise
+     */
+    public abstract boolean isCurrent();
+
+    private LogSaver() {
+    }
+
+    public static LogSaver newInstance() {
+        final boolean persistent = BugleGservices.get().getBoolean(
+                BugleGservicesKeys.PERSISTENT_LOGSAVER,
+                BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
+        if (persistent) {
+            final int setSize = BugleGservices.get().getInt(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT);
+            final int fileLimitBytes = BugleGservices.get().getInt(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT);
+            return new DiskLogSaver(setSize, fileLimitBytes);
+        } else {
+            final int size = BugleGservices.get().getInt(
+                    BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT,
+                    BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT);
+            return new MemoryLogSaver(size);
+        }
+    }
+
+    /**
+     * A circular in-memory log to be used to log potentially verbose logs. The logs will be
+     * persisted in memory in the application and can be dumped by various dump() methods.
+     * For example, adb shell dumpsys activity provider com.android.messaging.
+     * The dump will also show up in bugreports.
+     */
+    private static final class MemoryLogSaver extends LogSaver {
+        /**
+         * Record to store a single log entry. Stores timestamp, tid, level, tag, and message.
+         * It can be reused when the circular log rolls over. This avoids creating new objects.
+         */
+        private static class LogRecord {
+            int mTid;
+            String mLevelString;
+            long mTimeMillis;     // from System.currentTimeMillis
+            String mTag;
+            String mMessage;
+
+            LogRecord() {
+            }
+
+            void set(int tid, int level, long time, String tag, String message) {
+                this.mTid = tid;
+                this.mTimeMillis = time;
+                this.mTag = tag;
+                this.mMessage = message;
+                this.mLevelString = getLevelString(level);
+            }
+        }
+
+        private final int mSize;
+        private final CircularArray<LogRecord> mLogList;
+        private final Object mLock;
+
+        private final SimpleDateFormat mSdf = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
+        public MemoryLogSaver(final int size) {
+            mSize = size;
+            mLogList = new CircularArray<LogRecord>(size);
+            mLock = new Object();
+        }
+
+        @Override
+        public void dump(PrintWriter writer) {
+            int pid = Process.myPid();
+            synchronized (mLock) {
+                for (int i = 0; i < mLogList.count(); i++) {
+                    LogRecord rec = mLogList.get(i);
+                    writer.println(String.format("%s %5d %5d %s %s: %s",
+                            mSdf.format(rec.mTimeMillis),
+                            pid, rec.mTid, rec.mLevelString, rec.mTag, rec.mMessage));
+                }
+            }
+        }
+
+        @Override
+        public void log(int level, String tag, String msg) {
+            synchronized (mLock) {
+                LogRecord rec = mLogList.getFree();
+                if (rec == null) {
+                    rec = new LogRecord();
+                }
+                rec.set(Process.myTid(), level, System.currentTimeMillis(), tag, msg);
+                mLogList.add(rec);
+            }
+        }
+
+        @Override
+        public boolean isCurrent() {
+            final boolean persistent = BugleGservices.get().getBoolean(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
+            if (persistent) {
+                return false;
+            }
+            final int size = BugleGservices.get().getInt(
+                    BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT,
+                    BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT);
+            return size == mSize;
+        }
+    }
+
+    /**
+     * A persistent, on-disk log saver. It uses the standard Java util logger along with
+     * a rotation log file set to store the logs in app's local file directory "app_logs".
+     */
+    private static final class DiskLogSaver extends LogSaver {
+        private static final String DISK_LOG_DIR_NAME = "logs";
+
+        private final int mSetSize;
+        private final int mFileLimitBytes;
+        private Logger mDiskLogger;
+
+        public DiskLogSaver(final int setSize, final int fileLimitBytes) {
+            Assert.isTrue(setSize > 0);
+            Assert.isTrue(fileLimitBytes > 0);
+            mSetSize = setSize;
+            mFileLimitBytes = fileLimitBytes;
+            initDiskLog();
+        }
+
+        private static void clearDefaultHandlers(Logger logger) {
+            Assert.notNull(logger);
+            for (Handler handler : logger.getHandlers()) {
+                logger.removeHandler(handler);
+            }
+        }
+
+        private void initDiskLog() {
+            mDiskLogger = Logger.getLogger(LogUtil.BUGLE_TAG);
+            // We don't want the default console handler
+            clearDefaultHandlers(mDiskLogger);
+            // Don't want duplicate print in system log
+            mDiskLogger.setUseParentHandlers(false);
+            // FileHandler manages the log files in a fixed rotation set
+            final File logDir = Factory.get().getApplicationContext().getDir(
+                    DISK_LOG_DIR_NAME, 0/*mode*/);
+            FileHandler handler = null;
+            try {
+                handler = new FileHandler(
+                        logDir + "/%g.log", mFileLimitBytes, mSetSize, true/*append*/);
+            } catch (Exception e) {
+                Log.e(LogUtil.BUGLE_TAG, "LogSaver: fail to init disk logger", e);
+                return;
+            }
+            final Formatter formatter = new Formatter() {
+                @Override
+                public String format(java.util.logging.LogRecord r) {
+                    return r.getMessage();
+                }
+            };
+            handler.setFormatter(formatter);
+            handler.setLevel(Level.ALL);
+            mDiskLogger.addHandler(handler);
+        }
+
+        @Override
+        public void dump(PrintWriter writer) {
+            for (int i = mSetSize - 1; i >= 0; i--) {
+                final File logDir = Factory.get().getApplicationContext().getDir(
+                        DISK_LOG_DIR_NAME, 0/*mode*/);
+                final String logFilePath = logDir + "/" + i + ".log";
+                try {
+                    final File logFile = new File(logFilePath);
+                    if (!logFile.exists()) {
+                        continue;
+                    }
+                    final BufferedReader reader = new BufferedReader(new FileReader(logFile));
+                    for (String line; (line = reader.readLine()) != null;) {
+                        line = line.trim();
+                        writer.println(line);
+                    }
+                } catch (FileNotFoundException e) {
+                    Log.w(LogUtil.BUGLE_TAG, "LogSaver: can not find log file " + logFilePath);
+                } catch (IOException e) {
+                    Log.w(LogUtil.BUGLE_TAG, "LogSaver: can not read log file", e);
+                }
+            }
+        }
+
+        @Override
+        public void log(int level, String tag, String msg) {
+            final SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+            mDiskLogger.info(String.format("%s %5d %5d %s %s: %s\n",
+                    sdf.format(System.currentTimeMillis()),
+                    Process.myPid(), Process.myTid(), getLevelString(level), tag, msg));
+        }
+
+        @Override
+        public boolean isCurrent() {
+            final boolean persistent = BugleGservices.get().getBoolean(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
+            if (!persistent) {
+                return false;
+            }
+            final int setSize = BugleGservices.get().getInt(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT);
+            final int fileLimitBytes = BugleGservices.get().getInt(
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES,
+                    BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT);
+            return setSize == mSetSize && fileLimitBytes == mFileLimitBytes;
+        }
+    }
+
+    private static String getLevelString(final int level) {
+        switch (level) {
+            case android.util.Log.DEBUG:
+                return "D";
+            case android.util.Log.WARN:
+                return "W";
+            case android.util.Log.INFO:
+                return "I";
+            case android.util.Log.VERBOSE:
+                return "V";
+            case android.util.Log.ERROR:
+                return "E";
+            case android.util.Log.ASSERT:
+                return "A";
+            default:
+                return "?";
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/LogUtil.java b/src/com/android/messaging/util/LogUtil.java
new file mode 100644
index 0000000..021f39b
--- /dev/null
+++ b/src/com/android/messaging/util/LogUtil.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+/**
+ * Log utility class.
+ */
+public class LogUtil {
+    public static final String BUGLE_TAG = "MessagingApp";
+    public static final String PROFILE_TAG = "MessagingAppProf";
+    public static final String BUGLE_DATABASE_TAG = "MessagingAppDb";
+    public static final String BUGLE_DATABASE_PERF_TAG = "MessagingAppDbPerf";
+    public static final String BUGLE_DATAMODEL_TAG = "MessagingAppDataModel";
+    public static final String BUGLE_IMAGE_TAG = "MessagingAppImage";
+    public static final String BUGLE_NOTIFICATIONS_TAG = "MessagingAppNotif";
+    public static final String BUGLE_WIDGET_TAG = "MessagingAppWidget";
+
+    public static final int DEBUG = android.util.Log.DEBUG;
+    public static final int WARN = android.util.Log.WARN;
+    public static final int VERBOSE = android.util.Log.VERBOSE;
+    public static final int INFO = android.util.Log.INFO;
+    public static final int ERROR = android.util.Log.ERROR;
+
+    // If this is non-null, DEBUG and higher logs will be tracked in-memory. It will not include
+    // VERBOSE logs.
+    private static LogSaver sDebugLogSaver;
+    private static volatile boolean sCaptureDebugLogs;
+
+    /**
+     * Read Gservices to see if logging should be enabled.
+     */
+    public static void refreshGservices(final BugleGservices gservices) {
+        sCaptureDebugLogs = gservices.getBoolean(
+                BugleGservicesKeys.ENABLE_LOG_SAVER,
+                BugleGservicesKeys.ENABLE_LOG_SAVER_DEFAULT);
+        if (sCaptureDebugLogs && (sDebugLogSaver == null || !sDebugLogSaver.isCurrent())) {
+            // We were not capturing logs before. We are now.
+            sDebugLogSaver = LogSaver.newInstance();
+        } else if (!sCaptureDebugLogs && sDebugLogSaver != null) {
+            // We were capturing logs. We aren't anymore.
+            sDebugLogSaver = null;
+        }
+    }
+
+ // This is called from FactoryImpl once the Gservices class is initialized.
+    public static void initializeGservices (final BugleGservices gservices) {
+        gservices.registerForChanges(new Runnable() {
+            @Override
+            public void run() {
+                refreshGservices(gservices);
+            }
+        });
+        refreshGservices(gservices);
+    }
+
+    /**
+     * Send a {@link #VERBOSE} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void v(final String tag, final String msg) {
+        println(android.util.Log.VERBOSE, tag, msg);
+    }
+
+    /**
+     * Send a {@link #VERBOSE} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void v(final String tag, final String msg, final Throwable tr) {
+        println(android.util.Log.VERBOSE, tag, msg + '\n'
+                + android.util.Log.getStackTraceString(tr));
+    }
+
+    /**
+     * Send a {@link #DEBUG} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void d(final String tag, final String msg) {
+        println(android.util.Log.DEBUG, tag, msg);
+    }
+
+    /**
+     * Send a {@link #DEBUG} log message and log the exception.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void d(final String tag, final String msg, final Throwable tr) {
+        println(android.util.Log.DEBUG, tag, msg + '\n'
+                + android.util.Log.getStackTraceString(tr));
+    }
+
+    /**
+     * Send an {@link #INFO} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void i(final String tag, final String msg) {
+        println(android.util.Log.INFO, tag, msg);
+    }
+
+    /**
+     * Send a {@link #INFO} log message and log the exception.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void i(final String tag, final String msg, final Throwable tr) {
+        println(android.util.Log.INFO, tag, msg + '\n'
+                + android.util.Log.getStackTraceString(tr));
+    }
+
+    /**
+     * Send a {@link #WARN} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void w(final String tag, final String msg) {
+        println(android.util.Log.WARN, tag, msg);
+    }
+
+    /**
+     * Send a {@link #WARN} log message and log the exception.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void w(final String tag, final String msg, final Throwable tr) {
+        println(android.util.Log.WARN, tag, msg);
+        println(android.util.Log.WARN, tag, android.util.Log.getStackTraceString(tr));
+    }
+
+    /**
+     * Send an {@link #ERROR} log message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void e(final String tag, final String msg) {
+        println(android.util.Log.ERROR, tag, msg);
+    }
+
+    /**
+     * Send a {@link #ERROR} log message and log the exception.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void e(final String tag, final String msg, final Throwable tr) {
+        println(android.util.Log.ERROR, tag, msg);
+        println(android.util.Log.ERROR, tag, android.util.Log.getStackTraceString(tr));
+    }
+
+    /**
+     * What a Terrible Failure: Report a condition that should never happen.
+     * The error will always be logged at level ASSERT with the call stack.
+     * Depending on system configuration, a report may be added to the
+     * {@link android.os.DropBoxManager} and/or the process may be terminated
+     * immediately with an error dialog.
+     * @param tag Used to identify the source of a log message.
+     * @param msg The message you would like logged.
+     */
+    public static void wtf(final String tag, final String msg) {
+        // Make sure this goes into our log buffer
+        println(android.util.Log.ASSERT, tag, "wtf\n" + msg);
+        android.util.Log.wtf(tag, msg, new Exception());
+    }
+
+    /**
+     * What a Terrible Failure: Report a condition that should never happen.
+     * The error will always be logged at level ASSERT with the call stack.
+     * Depending on system configuration, a report may be added to the
+     * {@link android.os.DropBoxManager} and/or the process may be terminated
+     * immediately with an error dialog.
+     * @param tag Used to identify the source of a log message.
+     * @param msg The message you would like logged.
+     * @param tr An exception to log
+     */
+    public static void wtf(final String tag, final String msg, final Throwable tr) {
+        // Make sure this goes into our log buffer
+        println(android.util.Log.ASSERT, tag, "wtf\n" + msg + '\n' +
+                android.util.Log.getStackTraceString(tr));
+        android.util.Log.wtf(tag, msg, tr);
+    }
+
+    /**
+     * Low-level logging call.
+     * @param level The priority/type of this log message
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    private static void println(final int level, final String tag, final String msg) {
+        android.util.Log.println(level, tag, msg);
+
+        LogSaver serviceLog = sDebugLogSaver;
+        if (serviceLog != null && level >= android.util.Log.DEBUG) {
+            serviceLog.log(level, tag, msg);
+        }
+    }
+
+    /**
+     * Save logging into LogSaver only, for dumping to bug report
+     *
+     * @param level The priority/type of this log message
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     */
+    public static void save(final int level, final String tag, final String msg) {
+        LogSaver serviceLog = sDebugLogSaver;
+        if (serviceLog != null) {
+            serviceLog.log(level, tag, msg);
+        }
+    }
+
+    /**
+     * Checks to see whether or not a log for the specified tag is loggable at the specified level.
+     * See {@link android.util.Log#isLoggable(String, int)} for more discussion.
+     */
+    public static boolean isLoggable(final String tag, final int level) {
+        return android.util.Log.isLoggable(tag, level);
+    }
+
+    /**
+     * Returns text as is if {@value #BUGLE_TAG}'s log level is set to DEBUG or VERBOSE;
+     * returns "--" otherwise. Useful for log statements where we don't want to log
+     * various strings (e.g., usernames) with default logging to avoid leaking PII in logcat.
+     */
+    public static String sanitizePII(final String text) {
+        if (text == null) {
+            return null;
+        }
+
+        if (android.util.Log.isLoggable(BUGLE_TAG, android.util.Log.DEBUG)) {
+            return text;
+        } else {
+            return "Redacted-" + text.length();
+        }
+    }
+
+    public static void dump(java.io.PrintWriter out) {
+        final LogSaver logsaver = sDebugLogSaver;
+        if (logsaver != null) {
+            logsaver.dump(out);
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/LoggingTimer.java b/src/com/android/messaging/util/LoggingTimer.java
new file mode 100644
index 0000000..d0d41ac
--- /dev/null
+++ b/src/com/android/messaging/util/LoggingTimer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.os.SystemClock;
+
+/**
+ * A utility timer that logs the execution time of operations
+ */
+public class LoggingTimer {
+    private static final int NO_WARN_LIMIT = -1;
+
+    private final String mTag;
+    private final String mName;
+    private final long mWarnLimitMillis;
+    private long mStartMillis;
+
+    public LoggingTimer(final String tag, final String name) {
+        this(tag, name, NO_WARN_LIMIT);
+    }
+
+    public LoggingTimer(final String tag, final String name, final long warnLimitMillis) {
+        mTag = tag;
+        mName = name;
+        mWarnLimitMillis = warnLimitMillis;
+    }
+
+    /**
+     * This method should be called at the start of the operation to be timed.
+     */
+    public void start() {
+        mStartMillis = SystemClock.elapsedRealtime();
+
+        if (LogUtil.isLoggable(mTag, LogUtil.VERBOSE)) {
+            LogUtil.v(mTag, "Timer start for " + mName);
+        }
+    }
+
+    /**
+     * This method should be called at the end of the operation to be timed. It logs the time since
+     * the last call to {@link #start}
+     */
+    public void stopAndLog() {
+        final long elapsedMs = SystemClock.elapsedRealtime() - mStartMillis;
+
+        final String logMessage = String.format("Used %dms for %s", elapsedMs, mName);
+
+        LogUtil.save(LogUtil.DEBUG, mTag, logMessage);
+
+        if (mWarnLimitMillis != NO_WARN_LIMIT && elapsedMs > mWarnLimitMillis) {
+            LogUtil.w(mTag, logMessage);
+        } else if (LogUtil.isLoggable(mTag, LogUtil.VERBOSE)) {
+            LogUtil.v(mTag, logMessage);
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/LongSparseSet.java b/src/com/android/messaging/util/LongSparseSet.java
new file mode 100644
index 0000000..bb3843e
--- /dev/null
+++ b/src/com/android/messaging/util/LongSparseSet.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import androidx.collection.LongSparseArray;
+
+/**
+ * A space saving set for long values using v4 compat LongSparseArray
+ */
+public class LongSparseSet {
+    private static final Object THE_ONLY_VALID_VALUE = new Object();
+    private final LongSparseArray<Object> mSet = new LongSparseArray<Object>();
+
+    public LongSparseSet() {
+    }
+
+    /**
+     * @param key The element to check
+     * @return True if the element is in the set, false otherwise
+     */
+    public boolean contains(long key) {
+        if (mSet.get(key, null/*default*/) == THE_ONLY_VALID_VALUE) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Add an element to the set
+     *
+     * @param key The element to add
+     */
+    public void add(long key) {
+        mSet.put(key, THE_ONLY_VALID_VALUE);
+    }
+
+    /**
+     * Remove an element from the set
+     *
+     * @param key The element to remove
+     */
+    public void remove(long key) {
+        mSet.delete(key);
+    }
+}
diff --git a/src/com/android/messaging/util/MaterialPalette.java b/src/com/android/messaging/util/MaterialPalette.java
new file mode 100644
index 0000000..8dbacbf
--- /dev/null
+++ b/src/com/android/messaging/util/MaterialPalette.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+
+public class MaterialPalette{
+    public final int mPrimaryColor;
+    public final int mSecondaryColor;
+
+    public MaterialPalette(final int primaryColor, final int secondaryColor) {
+        mPrimaryColor = primaryColor;
+        mSecondaryColor = secondaryColor;
+    }
+}
diff --git a/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java b/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java
new file mode 100644
index 0000000..1a93e9d
--- /dev/null
+++ b/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.ContentResolver;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+
+import java.io.IOException;
+
+/**
+ * Convenience wrapper for {@link MediaMetadataRetriever} to help with its eccentric error handling.
+ */
+public class MediaMetadataRetrieverWrapper {
+    private final MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
+
+    public MediaMetadataRetrieverWrapper() {
+    }
+
+    public void setDataSource(Uri uri) throws IOException {
+        ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
+        AssetFileDescriptor fd = resolver.openAssetFileDescriptor(uri, "r");
+        if (fd == null) {
+            throw new IOException("openAssetFileDescriptor returned null for " + uri);
+        }
+        try {
+            mRetriever.setDataSource(fd.getFileDescriptor());
+        } catch (RuntimeException e) {
+            release();
+            throw new IOException(e);
+        } finally {
+            fd.close();
+        }
+    }
+
+    public int extractInteger(final int key, final int defaultValue) {
+        final String s = mRetriever.extractMetadata(key);
+        if (TextUtils.isEmpty(s)) {
+            return defaultValue;
+        }
+        return Integer.parseInt(s);
+    }
+
+    public String extractMetadata(final int key) {
+        return mRetriever.extractMetadata(key);
+    }
+
+    public Bitmap getFrameAtTime() {
+        return mRetriever.getFrameAtTime();
+    }
+
+    public Bitmap getFrameAtTime(final long timeUs) {
+        return mRetriever.getFrameAtTime(timeUs);
+    }
+
+    public void release() {
+        try {
+            mRetriever.release();
+        } catch (RuntimeException | IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "MediaMetadataRetriever.release failed", e);
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/MediaUtil.java b/src/com/android/messaging/util/MediaUtil.java
new file mode 100644
index 0000000..c23ded3
--- /dev/null
+++ b/src/com/android/messaging/util/MediaUtil.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+
+import com.android.messaging.Factory;
+
+public abstract class MediaUtil {
+    public static interface OnCompletionListener {
+        public void onCompletion();
+    }
+
+    public static MediaUtil get() {
+        return Factory.get().getMediaUtil();
+    }
+
+    /**
+     * Play sound from local resources given a resource id.
+     */
+    public abstract void playSound(final Context context, final int resId,
+            final OnCompletionListener completionListener);
+
+    public static boolean canAutoAccessIncomingMedia() {
+        return OsUtil.isAtLeastM();
+    }
+}
diff --git a/src/com/android/messaging/util/MediaUtilImpl.java b/src/com/android/messaging/util/MediaUtilImpl.java
new file mode 100644
index 0000000..272a057
--- /dev/null
+++ b/src/com/android/messaging/util/MediaUtilImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+
+/**
+ * Default implementation of MediaUtil
+ */
+public class MediaUtilImpl extends MediaUtil {
+
+    @Override
+    public void playSound(final Context context, final int resId,
+            final OnCompletionListener completionListener) {
+        // We want to play at the media volume and not the ringer volume, but we do want to
+        // avoid playing sound when the ringer/notifications are silenced. This is used for
+        // in app sounds that are not critical and should not impact running silent but also
+        // shouldn't play at full ring volume if you want to hear your ringer but don't want
+        // to be annoyed with in-app volume.
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        try {
+            final MediaPlayer mediaPlayer = new MediaPlayer();
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
+            final AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
+            mediaPlayer.setDataSource(
+                    afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+            afd.close();
+            mediaPlayer.prepare();
+            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(final MediaPlayer mp) {
+                    if (completionListener != null) {
+                        completionListener.onCompletion();
+                    }
+                    mp.stop();
+                    mp.release();
+                }
+            });
+            mediaPlayer.seekTo(0);
+            mediaPlayer.start();
+           return;
+        } catch (final Exception e) {
+            LogUtil.w("MediaUtilImpl", "Error playing sound id: " + resId, e);
+        }
+        if (completionListener != null) {
+            // Call the completion handler to not block functionality if audio play fails
+            completionListener.onCompletion();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/messaging/util/NotificationPlayer.java b/src/com/android/messaging/util/NotificationPlayer.java
new file mode 100644
index 0000000..a4ed44e
--- /dev/null
+++ b/src/com/android/messaging/util/NotificationPlayer.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.net.Uri;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import com.android.messaging.Factory;
+
+import java.util.LinkedList;
+
+/**
+ * This class is provides the same interface and functionality as android.media.AsyncPlayer
+ * with the following differences:
+ * - whenever audio is played, audio focus is requested,
+ * - whenever audio playback is stopped or the playback completed, audio focus is abandoned.
+ *
+ * This file has been copied from com.android.server.NotificationPlayer. The only modification is
+ * the addition of a volume parameter. Hopefully the framework will adapt AsyncPlayer to support
+ * all the functionality in this class, at which point this one can be deleted.
+ */
+public class NotificationPlayer implements OnCompletionListener {
+    private static final int PLAY = 1;
+    private static final int STOP = 2;
+    private static final boolean mDebug = false;
+
+    private static final class Command {
+        int code;
+        Uri uri;
+        boolean looping;
+        int stream;
+        float volume;
+        long requestTime;
+        boolean releaseFocus;
+
+        @Override
+        public String toString() {
+            return "{ code=" + code + " looping=" + looping + " stream=" + stream
+                    + " uri=" + uri + " }";
+        }
+    }
+
+    private final LinkedList<Command> mCmdQueue = new LinkedList<Command>();
+
+    private Looper mLooper;
+
+    /*
+     * Besides the use of audio focus, the only implementation difference between AsyncPlayer and
+     * NotificationPlayer resides in the creation of the MediaPlayer. For the completion callback,
+     * OnCompletionListener, to be called at the end of the playback, the MediaPlayer needs to
+     * be created with a looper running so its event handler is not null.
+     */
+    private final class CreationAndCompletionThread extends Thread {
+        public Command mCmd;
+        public CreationAndCompletionThread(final Command cmd) {
+            super();
+            mCmd = cmd;
+        }
+
+        @Override
+        public void run() {
+            Looper.prepare();
+            mLooper = Looper.myLooper();
+            synchronized (this) {
+                final AudioManager audioManager =
+                        (AudioManager) Factory.get().getApplicationContext()
+                        .getSystemService(Context.AUDIO_SERVICE);
+                try {
+                    final MediaPlayer player = new MediaPlayer();
+                    player.setAudioStreamType(mCmd.stream);
+                    player.setDataSource(Factory.get().getApplicationContext(), mCmd.uri);
+                    player.setLooping(mCmd.looping);
+                    player.setVolume(mCmd.volume, mCmd.volume);
+                    player.prepare();
+                    if ((mCmd.uri != null) && (mCmd.uri.getEncodedPath() != null)
+                            && (mCmd.uri.getEncodedPath().length() > 0)) {
+                        audioManager.requestAudioFocus(null, mCmd.stream,
+                                mCmd.looping ? AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+                                        : AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
+                    }
+                    player.setOnCompletionListener(NotificationPlayer.this);
+                    player.start();
+                    if (mPlayer != null) {
+                        mPlayer.release();
+                    }
+                    mPlayer = player;
+                } catch (final Exception e) {
+                    LogUtil.w(mTag, "error loading sound for " + mCmd.uri, e);
+                }
+                mAudioManager = audioManager;
+                this.notify();
+            }
+            Looper.loop();
+        }
+    }
+
+    private void startSound(final Command cmd) {
+        // Preparing can be slow, so if there is something else
+        // is playing, let it continue until we're done, so there
+        // is less of a glitch.
+        try {
+            if (mDebug) {
+                LogUtil.d(mTag, "Starting playback");
+            }
+            //-----------------------------------
+            // This is were we deviate from the AsyncPlayer implementation and create the
+            // MediaPlayer in a new thread with which we're synchronized
+            synchronized (mCompletionHandlingLock) {
+                // if another sound was already playing, it doesn't matter we won't get notified
+                // of the completion, since only the completion notification of the last sound
+                // matters
+                if ((mLooper != null)
+                        && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
+                    mLooper.quit();
+                }
+                mCompletionThread = new CreationAndCompletionThread(cmd);
+                synchronized (mCompletionThread) {
+                    mCompletionThread.start();
+                    mCompletionThread.wait();
+                }
+            }
+            //-----------------------------------
+
+            final long delay = SystemClock.elapsedRealtime() - cmd.requestTime;
+            if (delay > 1000) {
+                LogUtil.w(mTag, "Notification sound delayed by " + delay + "msecs");
+            }
+        } catch (final Exception e) {
+            LogUtil.w(mTag, "error loading sound for " + cmd.uri, e);
+        }
+    }
+
+    private void stopSound(final Command cmd) {
+        if (mPlayer == null) {
+            return;
+        }
+        final long delay = SystemClock.elapsedRealtime() - cmd.requestTime;
+        if (delay > 1000) {
+            LogUtil.w(mTag, "Notification stop delayed by " + delay + "msecs");
+        }
+        mPlayer.stop();
+        mPlayer.release();
+        mPlayer = null;
+        if (cmd.releaseFocus && mAudioManager != null) {
+            mAudioManager.abandonAudioFocus(null);
+        }
+        mAudioManager = null;
+        if ((mLooper != null) && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
+            mLooper.quit();
+        }
+    }
+
+    private final class CmdThread extends java.lang.Thread {
+        CmdThread() {
+            super("NotificationPlayer-" + mTag);
+        }
+
+        @Override
+        public void run() {
+            while (true) {
+                Command cmd = null;
+
+                synchronized (mCmdQueue) {
+                    if (mDebug) {
+                        LogUtil.d(mTag, "RemoveFirst");
+                    }
+                    cmd = mCmdQueue.removeFirst();
+                }
+
+                switch (cmd.code) {
+                    case PLAY:
+                        if (mDebug) {
+                            LogUtil.d(mTag, "PLAY");
+                        }
+                        startSound(cmd);
+                        break;
+                    case STOP:
+                        if (mDebug) {
+                            LogUtil.d(mTag, "STOP");
+                        }
+                        stopSound(cmd);
+                        break;
+                }
+
+                synchronized (mCmdQueue) {
+                    if (mCmdQueue.size() == 0) {
+                        // nothing left to do, quit
+                        // doing this check after we're done prevents the case where they
+                        // added it during the operation from spawning two threads and
+                        // trying to do them in parallel.
+                        mThread = null;
+                        releaseWakeLock();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onCompletion(final MediaPlayer mp) {
+        if (mAudioManager != null) {
+            mAudioManager.abandonAudioFocus(null);
+        }
+        // if there are no more sounds to play, end the Looper to listen for media completion
+        synchronized (mCmdQueue) {
+            if (mCmdQueue.size() == 0) {
+                synchronized (mCompletionHandlingLock) {
+                    if (mLooper != null) {
+                        mLooper.quit();
+                    }
+                    mCompletionThread = null;
+                }
+            }
+        }
+    }
+
+    private String mTag;
+    private CmdThread mThread;
+    private CreationAndCompletionThread mCompletionThread;
+    private final Object mCompletionHandlingLock = new Object();
+    private MediaPlayer mPlayer;
+    private PowerManager.WakeLock mWakeLock;
+    private AudioManager mAudioManager;
+
+    // The current state according to the caller.  Reality lags behind
+    // because of the asynchronous nature of this class.
+    private int mState = STOP;
+
+    /**
+     * Construct a NotificationPlayer object.
+     *
+     * @param tag a string to use for debugging
+     */
+    public NotificationPlayer(final String tag) {
+        if (tag != null) {
+            mTag = tag;
+        } else {
+            mTag = "NotificationPlayer";
+        }
+    }
+
+    /**
+     * Start playing the sound.  It will actually start playing at some
+     * point in the future.  There are no guarantees about latency here.
+     * Calling this before another audio file is done playing will stop
+     * that one and start the new one.
+     *
+     * @param uri The URI to play.  (see {@link MediaPlayer#setDataSource(Context, Uri)})
+     * @param looping Whether the audio should loop forever.
+     *          (see {@link MediaPlayer#setLooping(boolean)})
+     * @param stream the AudioStream to use.
+     *          (see {@link MediaPlayer#setAudioStreamType(int)})
+     * @param volume The volume at which to play this sound, as a fraction of the system volume for
+     *          the relevant stream type. A value of 1 is the maximum and means play at the system
+     *          volume with no attenuation.
+     */
+    public void play(final Uri uri, final boolean looping, final int stream, final float volume) {
+        final Command cmd = new Command();
+        cmd.requestTime = SystemClock.elapsedRealtime();
+        cmd.code = PLAY;
+        cmd.uri = uri;
+        cmd.looping = looping;
+        cmd.stream = stream;
+        cmd.volume = volume;
+        synchronized (mCmdQueue) {
+            enqueueLocked(cmd);
+            mState = PLAY;
+        }
+    }
+
+    /** Same as calling stop(true) */
+    public void stop() {
+        stop(true);
+    }
+
+    /**
+     * Stop a previously played sound.  It can't be played again or unpaused
+     * at this point.  Calling this multiple times has no ill effects.
+     * @param releaseAudioFocus whether to release audio focus
+     */
+    public void stop(final boolean releaseAudioFocus) {
+        synchronized (mCmdQueue) {
+            // This check allows stop to be called multiple times without starting
+            // a thread that ends up doing nothing.
+            if (mState != STOP) {
+                final Command cmd = new Command();
+                cmd.requestTime = SystemClock.elapsedRealtime();
+                cmd.code = STOP;
+                cmd.releaseFocus = releaseAudioFocus;
+                enqueueLocked(cmd);
+                mState = STOP;
+            }
+        }
+    }
+
+    private void enqueueLocked(final Command cmd) {
+        mCmdQueue.add(cmd);
+        if (mThread == null) {
+            acquireWakeLock();
+            mThread = new CmdThread();
+            mThread.start();
+        }
+    }
+
+    /**
+     * We want to hold a wake lock while we do the prepare and play.  The stop probably is
+     * optional, but it won't hurt to have it too.  The problem is that if you start a sound
+     * while you're holding a wake lock (e.g. an alarm starting a notification), you want the
+     * sound to play, but if the CPU turns off before mThread gets to work, it won't.  The
+     * simplest way to deal with this is to make it so there is a wake lock held while the
+     * thread is starting or running.  You're going to need the WAKE_LOCK permission if you're
+     * going to call this.
+     *
+     * This must be called before the first time play is called.
+     *
+     * @hide
+     */
+    public void setUsesWakeLock() {
+        if (mWakeLock != null || mThread != null) {
+            // if either of these has happened, we've already played something.
+            // and our releases will be out of sync.
+            throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock
+                    + " mThread=" + mThread);
+        }
+        final PowerManager pm = (PowerManager) Factory.get().getApplicationContext()
+                .getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+    }
+
+    private void acquireWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.acquire();
+        }
+    }
+
+    private void releaseWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+    }
+}
+
diff --git a/src/com/android/messaging/util/OsUtil.java b/src/com/android/messaging/util/OsUtil.java
new file mode 100644
index 0000000..1d9742a
--- /dev/null
+++ b/src/com/android/messaging/util/OsUtil.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+import androidx.core.os.BuildCompat;
+
+import com.android.messaging.Factory;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Set;
+
+/**
+ * Android OS version utilities
+ */
+public class OsUtil {
+    private static boolean sIsAtLeastICS_MR1;
+    private static boolean sIsAtLeastJB;
+    private static boolean sIsAtLeastJB_MR1;
+    private static boolean sIsAtLeastJB_MR2;
+    private static boolean sIsAtLeastKLP;
+    private static boolean sIsAtLeastL;
+    private static boolean sIsAtLeastL_MR1;
+    private static boolean sIsAtLeastM;
+    private static boolean sIsAtLeastN;
+
+    private static Boolean sIsSecondaryUser = null;
+
+    static {
+        final int v = getApiVersion();
+        sIsAtLeastICS_MR1 = v >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
+        sIsAtLeastJB = v >= android.os.Build.VERSION_CODES.JELLY_BEAN;
+        sIsAtLeastJB_MR1 = v >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+        sIsAtLeastJB_MR2 = v >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
+        sIsAtLeastKLP = v >= android.os.Build.VERSION_CODES.KITKAT;
+        sIsAtLeastL = v >= android.os.Build.VERSION_CODES.LOLLIPOP;
+        sIsAtLeastL_MR1 = v >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
+        sIsAtLeastM = v >= android.os.Build.VERSION_CODES.M;
+        sIsAtLeastN = BuildCompat.isAtLeastN();
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least Ice Cream Sandwich
+     *  MR1 (API level 15).
+     */
+    public static boolean isAtLeastICS_MR1() {
+        return sIsAtLeastICS_MR1;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least Jelly Bean
+     *  (API level 16).
+     */
+    public static boolean isAtLeastJB() {
+        return sIsAtLeastJB;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least Jelly Bean MR1
+     *  (API level 17).
+     */
+    public static boolean isAtLeastJB_MR1() {
+        return sIsAtLeastJB_MR1;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least Jelly Bean MR2
+     *  (API level 18).
+     */
+    public static boolean isAtLeastJB_MR2() {
+        return sIsAtLeastJB_MR2;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least KLP
+     *  (API level 19).
+     */
+    public static boolean isAtLeastKLP() {
+        return sIsAtLeastKLP;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least L
+     *  (API level 21).
+     */
+    public static boolean isAtLeastL() {
+        return sIsAtLeastL;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least L MR1
+     *  (API level 22).
+     */
+    public static boolean isAtLeastL_MR1() {
+        return sIsAtLeastL_MR1;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least M
+     *  (API level 23).
+     */
+    public static boolean isAtLeastM() {
+        return sIsAtLeastM;
+    }
+
+    /**
+     * @return True if the version of Android that we're running on is at least N
+     *  (API level 24).
+     */
+    public static boolean isAtLeastN() {
+        return sIsAtLeastN;
+    }
+
+    /**
+     * @return The Android API version of the OS that we're currently running on.
+     */
+    public static int getApiVersion() {
+        return android.os.Build.VERSION.SDK_INT;
+    }
+
+    public static boolean isSecondaryUser() {
+        if (sIsSecondaryUser == null) {
+            final Context context = Factory.get().getApplicationContext();
+            boolean isSecondaryUser = false;
+
+            // Only check for newer devices (but not the nexus 10)
+            if (OsUtil.sIsAtLeastJB_MR1 && !"Nexus 10".equals(Build.MODEL)) {
+                final UserHandle uh = android.os.Process.myUserHandle();
+                final UserManager userManager =
+                        (UserManager) context.getSystemService(Context.USER_SERVICE);
+                if (userManager != null) {
+                    final long userSerialNumber = userManager.getSerialNumberForUser(uh);
+                    isSecondaryUser = (0 != userSerialNumber);
+                }
+            }
+            sIsSecondaryUser = isSecondaryUser;
+        }
+        return sIsSecondaryUser;
+    }
+
+    /**
+     * Creates a joined string from a Set<String> using the given delimiter.
+     * @param values
+     * @param delimiter
+     * @return
+     */
+    public static String joinFromSetWithDelimiter(
+            final Set<String> values, final String delimiter) {
+        if (values != null) {
+            final StringBuilder joinedStringBuilder = new StringBuilder();
+            boolean firstValue = true;
+            for (final String value : values) {
+                if (firstValue) {
+                    firstValue = false;
+                } else {
+                    joinedStringBuilder.append(delimiter);
+                }
+                joinedStringBuilder.append(value);
+            }
+            return joinedStringBuilder.toString();
+        }
+        return null;
+    }
+
+    private static Hashtable<String, Integer> sPermissions = new Hashtable<String, Integer>();
+
+    /**
+     * Check if the app has the specified permission. If it does not, the app needs to use
+     * {@link android.app.Activity#requestPermission}. Note that if it
+     * returns true, it cannot return false in the same process as the OS kills the process when
+     * any permission is revoked.
+     * @param permission A permission from {@link android.Manifest.permission}
+     */
+    public static boolean hasPermission(final String permission) {
+        if (OsUtil.isAtLeastM()) {
+            // It is safe to cache the PERMISSION_GRANTED result as the process gets killed if the
+            // user revokes the permission setting. However, PERMISSION_DENIED should not be
+            // cached as the process does not get killed if the user enables the permission setting.
+            if (!sPermissions.containsKey(permission)
+                    || sPermissions.get(permission) == PackageManager.PERMISSION_DENIED) {
+                final Context context = Factory.get().getApplicationContext();
+                final int permissionState = context.checkSelfPermission(permission);
+                sPermissions.put(permission, permissionState);
+            }
+            return sPermissions.get(permission) == PackageManager.PERMISSION_GRANTED;
+        } else {
+            return true;
+        }
+    }
+
+    /** Does the app have all the specified permissions */
+    public static boolean hasPermissions(final String[] permissions) {
+        for (final String permission : permissions) {
+            if (!hasPermission(permission)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean hasPhonePermission() {
+        return hasPermission(Manifest.permission.READ_PHONE_STATE);
+    }
+
+    public static boolean hasSmsPermission() {
+        return hasPermission(Manifest.permission.READ_SMS);
+    }
+
+    public static boolean hasLocationPermission() {
+        return OsUtil.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION);
+    }
+
+
+    public static boolean hasStoragePermission() {
+        // Note that READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE are granted or denied
+        // together.
+        return OsUtil.hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
+    }
+
+    public static boolean hasRecordAudioPermission() {
+        return OsUtil.hasPermission(Manifest.permission.RECORD_AUDIO);
+    }
+
+    /**
+     * Returns array with the set of permissions that have not been granted from the given set.
+     * The array will be empty if the app has all of the specified permissions. Note that calling
+     * {@link Activity#requestPermissions} for an already granted permission can prompt the user
+     * again, and its up to the app to only request permissions that are missing.
+     */
+    public static String[] getMissingPermissions(final String[] permissions) {
+        final ArrayList<String> missingList = new ArrayList<String>();
+        for (final String permission : permissions) {
+            if (!hasPermission(permission)) {
+                missingList.add(permission);
+            }
+        }
+
+        final String[] missingArray = new String[missingList.size()];
+        missingList.toArray(missingArray);
+        return missingArray;
+    }
+
+    private static String[] sRequiredPermissions = new String[] {
+        // Required to read existing SMS threads
+        Manifest.permission.READ_SMS,
+        // Required for knowing the phone number, number of SIMs, etc.
+        Manifest.permission.READ_PHONE_STATE,
+        // This is not strictly required, but simplifies the contact picker scenarios
+        Manifest.permission.READ_CONTACTS,
+    };
+
+    /** Does the app have the minimum set of permissions required to operate. */
+    public static boolean hasRequiredPermissions() {
+        return hasPermissions(sRequiredPermissions);
+    }
+
+    public static String[] getMissingRequiredPermissions() {
+        return getMissingPermissions(sRequiredPermissions);
+    }
+}
diff --git a/src/com/android/messaging/util/PendingIntentConstants.java b/src/com/android/messaging/util/PendingIntentConstants.java
new file mode 100644
index 0000000..1a594c5
--- /dev/null
+++ b/src/com/android/messaging/util/PendingIntentConstants.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+
+public class PendingIntentConstants {
+    // Notifications
+    public static final int SMS_NOTIFICATION_ID = 0;
+    public static final int SMS_SECONDARY_USER_NOTIFICATION_ID = 1;
+    public static final int MSG_SEND_ERROR = 2;
+    public static final int SMS_STORAGE_LOW_NOTIFICATION_ID = 3;
+
+    // Request codes
+    public static final int UPDATE_NOTIFICATIONS_ALARM_ACTION_ID = 100;
+
+    public static final int MIN_ASSIGNED_REQUEST_CODE = 1001;
+
+    // Logging
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final boolean VERBOSE = false;
+
+    // Internal Constants
+    private static final String NOTIFICATION_REQUEST_CODE_PREFS = "notificationRequestCodes.v1";
+    private static final String REQUEST_CODE_DELIMITER = "|";
+    private static final String MAX_REQUEST_CODE_KEY = "maxRequestCode";
+}
diff --git a/src/com/android/messaging/util/PhoneUtils.java b/src/com/android/messaging/util/PhoneUtils.java
new file mode 100644
index 0000000..08889b8
--- /dev/null
+++ b/src/com/android/messaging/util/PhoneUtils.java
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import androidx.collection.ArrayMap;
+import androidx.core.os.BuildCompat;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.sms.MmsSmsUtils;
+
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * This class abstracts away platform dependency of calling telephony related
+ * platform APIs, mostly involving TelephonyManager, SubscriptionManager and
+ * a bit of SmsManager.
+ *
+ * The class instance can only be obtained via the get(int subId) method parameterized
+ * by a SIM subscription ID. On pre-L_MR1, the subId is not used and it has to be
+ * the default subId (-1).
+ *
+ * A convenient getDefault() method is provided for default subId (-1) on any platform
+ */
+public abstract class PhoneUtils {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private static final int MINIMUM_PHONE_NUMBER_LENGTH_TO_FORMAT = 6;
+
+    private static final List<SubscriptionInfo> EMPTY_SUBSCRIPTION_LIST = new ArrayList<>();
+
+    // The canonical phone number cache
+    // Each country gets its own cache. The following maps from ISO country code to
+    // the country's cache. Each cache maps from original phone number to canonicalized phone
+    private static final ArrayMap<String, ArrayMap<String, String>> sCanonicalPhoneNumberCache =
+            new ArrayMap<>();
+
+    protected final Context mContext;
+    protected final TelephonyManager mTelephonyManager;
+    protected final int mSubId;
+
+    public PhoneUtils(int subId) {
+        mSubId = subId;
+        mContext = Factory.get().getApplicationContext();
+        mTelephonyManager =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    /**
+     * Get the SIM's country code
+     *
+     * @return the country code on the SIM
+     */
+    public abstract String getSimCountry();
+
+    /**
+     * Get number of SIM slots
+     *
+     * @return the SIM slot count
+     */
+    public abstract int getSimSlotCount();
+
+    /**
+     * Get SIM's carrier name
+     *
+     * @return the carrier name of the SIM
+     */
+    public abstract String getCarrierName();
+
+    /**
+     * Check if there is SIM inserted on the device
+     *
+     * @return true if there is SIM inserted, false otherwise
+     */
+    public abstract boolean hasSim();
+
+    /**
+     * Check if the SIM is roaming
+     *
+     * @return true if the SIM is in romaing state, false otherwise
+     */
+    public abstract boolean isRoaming();
+
+    /**
+     * Get the MCC and MNC in integer of the SIM's provider
+     *
+     * @return an array of two ints, [0] is the MCC code and [1] is the MNC code
+     */
+    public abstract int[] getMccMnc();
+
+    /**
+     * Get the mcc/mnc string
+     *
+     * @return the text of mccmnc string
+     */
+    public abstract String getSimOperatorNumeric();
+
+    /**
+     * Get the SIM's self raw number, i.e. not canonicalized
+     *
+     * @param allowOverride Whether to use the app's setting to override the self number
+     * @return the original self number
+     * @throws IllegalStateException if no active subscription on L-MR1+
+     */
+    public abstract String getSelfRawNumber(final boolean allowOverride);
+
+    /**
+     * Returns the "effective" subId, or the subId used in the context of actual messages,
+     * conversations and subscription-specific settings, for the given "nominal" sub id.
+     *
+     * For pre-L-MR1 platform, this should always be
+     * {@value com.android.messaging.datamodel.data.ParticipantData#DEFAULT_SELF_SUB_ID};
+     *
+     * On the other hand, for L-MR1 and above, DEFAULT_SELF_SUB_ID will be mapped to the system
+     * default subscription id for SMS.
+     *
+     * @param subId The input subId
+     * @return the real subId if we can convert
+     */
+    public abstract int getEffectiveSubId(int subId);
+
+    /**
+     * Returns the number of active subscriptions in the device.
+     */
+    public abstract int getActiveSubscriptionCount();
+
+    /**
+     * Get {@link SmsManager} instance
+     *
+     * @return the relevant SmsManager instance based on OS version and subId
+     */
+    public abstract SmsManager getSmsManager();
+
+    /**
+     * Get the default SMS subscription id
+     *
+     * @return the default sub ID
+     */
+    public abstract int getDefaultSmsSubscriptionId();
+
+    /**
+     * Returns if there's currently a system default SIM selected for sending SMS.
+     */
+    public abstract boolean getHasPreferredSmsSim();
+
+    /**
+     * For L_MR1, system may return a negative subId. Convert this into our own
+     * subId, so that we consistently use -1 for invalid or default.
+     *
+     * see b/18629526 and b/18670346
+     *
+     * @param intent The push intent from system
+     * @param extraName The name of the sub id extra
+     * @return the subId that is valid and meaningful for the app
+     */
+    public abstract int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName);
+
+    /**
+     * Get the subscription_id column value from a telephony provider cursor
+     *
+     * @param cursor The database query cursor
+     * @param subIdIndex The index of the subId column in the cursor
+     * @return the subscription_id column value from the cursor
+     */
+    public abstract int getSubIdFromTelephony(Cursor cursor, int subIdIndex);
+
+    /**
+     * Check if data roaming is enabled
+     *
+     * @return true if data roaming is enabled, false otherwise
+     */
+    public abstract boolean isDataRoamingEnabled();
+
+    /**
+     * Check if mobile data is enabled
+     *
+     * @return true if mobile data is enabled, false otherwise
+     */
+    public abstract boolean isMobileDataEnabled();
+
+    /**
+     * Get the set of self phone numbers, all normalized
+     *
+     * @return the set of normalized self phone numbers
+     */
+    public abstract HashSet<String> getNormalizedSelfNumbers();
+
+    /**
+     * This interface packages methods should only compile on L_MR1.
+     * This is needed to make unit tests happy when mockito tries to
+     * mock these methods. Calling on these methods on L_MR1 requires
+     * an extra invocation of toMr1().
+     */
+    public interface LMr1 {
+        /**
+         * Get this SIM's information. Only applies to L_MR1 above
+         *
+         * @return the subscription info of the SIM
+         */
+        public abstract SubscriptionInfo getActiveSubscriptionInfo();
+
+        /**
+         * Get the list of active SIMs in system. Only applies to L_MR1 above
+         *
+         * @return the list of subscription info for all inserted SIMs
+         */
+        public abstract List<SubscriptionInfo> getActiveSubscriptionInfoList();
+
+        /**
+         * Register subscription change listener. Only applies to L_MR1 above
+         *
+         * @param listener The listener to register
+         */
+        public abstract void registerOnSubscriptionsChangedListener(
+                SubscriptionManager.OnSubscriptionsChangedListener listener);
+    }
+
+    /**
+     * The PhoneUtils class for pre L_MR1
+     */
+    public static class PhoneUtilsPreLMR1 extends PhoneUtils {
+        private final ConnectivityManager mConnectivityManager;
+
+        public PhoneUtilsPreLMR1() {
+            super(ParticipantData.DEFAULT_SELF_SUB_ID);
+            mConnectivityManager =
+                    (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        }
+
+        @Override
+        public String getSimCountry() {
+            final String country = mTelephonyManager.getSimCountryIso();
+            if (TextUtils.isEmpty(country)) {
+                return null;
+            }
+            return country.toUpperCase();
+        }
+
+        @Override
+        public int getSimSlotCount() {
+            // Don't support MSIM pre-L_MR1
+            return 1;
+        }
+
+        @Override
+        public String getCarrierName() {
+            return mTelephonyManager.getNetworkOperatorName();
+        }
+
+        @Override
+        public boolean hasSim() {
+            return mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_ABSENT;
+        }
+
+        @Override
+        public boolean isRoaming() {
+            return mTelephonyManager.isNetworkRoaming();
+        }
+
+        @Override
+        public int[] getMccMnc() {
+            final String mccmnc = mTelephonyManager.getSimOperator();
+            int mcc = 0;
+            int mnc = 0;
+            try {
+                mcc = Integer.parseInt(mccmnc.substring(0, 3));
+                mnc = Integer.parseInt(mccmnc.substring(3));
+            } catch (Exception e) {
+                LogUtil.w(TAG, "PhoneUtils.getMccMnc: invalid string " + mccmnc, e);
+            }
+            return new int[]{mcc, mnc};
+        }
+
+        @Override
+        public String getSimOperatorNumeric() {
+            return mTelephonyManager.getSimOperator();
+        }
+
+        @Override
+        public String getSelfRawNumber(final boolean allowOverride) {
+            if (allowOverride) {
+                final String userDefinedNumber = getNumberFromPrefs(mContext,
+                        ParticipantData.DEFAULT_SELF_SUB_ID);
+                if (!TextUtils.isEmpty(userDefinedNumber)) {
+                    return userDefinedNumber;
+                }
+            }
+            return mTelephonyManager.getLine1Number();
+        }
+
+        @Override
+        public int getEffectiveSubId(int subId) {
+            Assert.equals(ParticipantData.DEFAULT_SELF_SUB_ID, subId);
+            return ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+
+        @Override
+        public SmsManager getSmsManager() {
+            return SmsManager.getDefault();
+        }
+
+        @Override
+        public int getDefaultSmsSubscriptionId() {
+            Assert.fail("PhoneUtils.getDefaultSmsSubscriptionId(): not supported before L MR1");
+            return ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+
+        @Override
+        public boolean getHasPreferredSmsSim() {
+            // SIM selection is not supported pre-L_MR1.
+            return true;
+        }
+
+        @Override
+        public int getActiveSubscriptionCount() {
+            return hasSim() ? 1 : 0;
+        }
+
+        @Override
+        public int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName) {
+            // Pre-L_MR1 always returns the default id
+            return ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+
+        @Override
+        public int getSubIdFromTelephony(Cursor cursor, int subIdIndex) {
+            // No subscription_id column before L_MR1
+            return ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+
+        @Override
+        @SuppressWarnings("deprecation")
+        public boolean isDataRoamingEnabled() {
+            if (BuildCompat.isAtLeastT()) {
+                return mTelephonyManager.isDataRoamingEnabled();
+            }
+            boolean dataRoamingEnabled = false;
+            final ContentResolver cr = mContext.getContentResolver();
+            if (OsUtil.isAtLeastJB_MR1()) {
+                dataRoamingEnabled =
+                        (Settings.Global.getInt(cr, Settings.Global.DATA_ROAMING, 0) != 0);
+            } else {
+                dataRoamingEnabled =
+                        (Settings.System.getInt(cr, Settings.System.DATA_ROAMING, 0) != 0);
+            }
+            return dataRoamingEnabled;
+        }
+
+        @Override
+        public boolean isMobileDataEnabled() {
+            boolean mobileDataEnabled = false;
+            try {
+                final Class cmClass = mConnectivityManager.getClass();
+                final Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
+                method.setAccessible(true); // Make the method callable
+                // get the setting for "mobile data"
+                mobileDataEnabled = (Boolean) method.invoke(mConnectivityManager);
+            } catch (final Exception e) {
+                LogUtil.e(TAG, "PhoneUtil.isMobileDataEnabled: system api not found", e);
+            }
+            return mobileDataEnabled;
+        }
+
+        @Override
+        public HashSet<String> getNormalizedSelfNumbers() {
+            final HashSet<String> numbers = new HashSet<>();
+            numbers.add(getCanonicalForSelf(true/*allowOverride*/));
+            return numbers;
+        }
+    }
+
+    /**
+     * The PhoneUtils class for L_MR1
+     */
+    public static class PhoneUtilsLMR1 extends PhoneUtils implements LMr1 {
+        private final SubscriptionManager mSubscriptionManager;
+
+        public PhoneUtilsLMR1(final int subId) {
+            super(subId);
+            mSubscriptionManager = SubscriptionManager.from(Factory.get().getApplicationContext());
+        }
+
+        @Override
+        public String getSimCountry() {
+            final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
+            if (subInfo != null) {
+                final String country = subInfo.getCountryIso();
+                if (TextUtils.isEmpty(country)) {
+                    return null;
+                }
+                return country.toUpperCase();
+            }
+            return null;
+        }
+
+        @Override
+        public int getSimSlotCount() {
+            return mSubscriptionManager.getActiveSubscriptionInfoCountMax();
+        }
+
+        @Override
+        public String getCarrierName() {
+            final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
+            if (subInfo != null) {
+                final CharSequence displayName = subInfo.getDisplayName();
+                if (!TextUtils.isEmpty(displayName)) {
+                    return displayName.toString();
+                }
+                final CharSequence carrierName = subInfo.getCarrierName();
+                if (carrierName != null) {
+                    return carrierName.toString();
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean hasSim() {
+            return mSubscriptionManager.getActiveSubscriptionInfoCount() > 0;
+        }
+
+        @Override
+        public boolean isRoaming() {
+            return mSubscriptionManager.isNetworkRoaming(mSubId);
+        }
+
+        @Override
+        public int[] getMccMnc() {
+            int mcc = 0;
+            int mnc = 0;
+            final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
+            if (subInfo != null) {
+                mcc = subInfo.getMcc();
+                mnc = subInfo.getMnc();
+            }
+            return new int[]{mcc, mnc};
+        }
+
+        @Override
+        public String getSimOperatorNumeric() {
+            // For L_MR1 we return the canonicalized (xxxxxx) string
+            return getMccMncString(getMccMnc());
+        }
+
+        @Override
+        public String getSelfRawNumber(final boolean allowOverride) {
+            if (allowOverride) {
+                final String userDefinedNumber = getNumberFromPrefs(mContext, mSubId);
+                if (!TextUtils.isEmpty(userDefinedNumber)) {
+                    return userDefinedNumber;
+                }
+            }
+
+            final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
+            if (subInfo != null) {
+                String phoneNumber = subInfo.getNumber();
+                if (TextUtils.isEmpty(phoneNumber) && LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                    LogUtil.d(TAG, "SubscriptionInfo phone number for self is empty!");
+                }
+                return phoneNumber;
+            }
+            LogUtil.w(TAG, "PhoneUtils.getSelfRawNumber: subInfo is null for " + mSubId);
+            throw new IllegalStateException("No active subscription");
+        }
+
+        @Override
+        public SubscriptionInfo getActiveSubscriptionInfo() {
+            try {
+                final SubscriptionInfo subInfo =
+                        mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
+                if (subInfo == null) {
+                    if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+                        // This is possible if the sub id is no longer available.
+                        LogUtil.d(TAG, "PhoneUtils.getActiveSubscriptionInfo(): empty sub info for "
+                                + mSubId);
+                    }
+                }
+                return subInfo;
+            } catch (Exception e) {
+                LogUtil.e(TAG, "PhoneUtils.getActiveSubscriptionInfo: system exception for "
+                        + mSubId, e);
+            }
+            return null;
+        }
+
+        @Override
+        public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
+            final List<SubscriptionInfo> subscriptionInfos =
+                    mSubscriptionManager.getActiveSubscriptionInfoList();
+            if (subscriptionInfos != null) {
+                return subscriptionInfos;
+            }
+            return EMPTY_SUBSCRIPTION_LIST;
+        }
+
+        @Override
+        public int getEffectiveSubId(int subId) {
+            if (subId == ParticipantData.DEFAULT_SELF_SUB_ID) {
+                return getDefaultSmsSubscriptionId();
+            }
+            return subId;
+        }
+
+        @Override
+        public void registerOnSubscriptionsChangedListener(
+                SubscriptionManager.OnSubscriptionsChangedListener listener) {
+            mSubscriptionManager.addOnSubscriptionsChangedListener(listener);
+        }
+
+        @Override
+        public SmsManager getSmsManager() {
+            return SmsManager.getSmsManagerForSubscriptionId(mSubId);
+        }
+
+        @Override
+        public int getDefaultSmsSubscriptionId() {
+            final int systemDefaultSubId = SmsManager.getDefaultSmsSubscriptionId();
+            if (systemDefaultSubId < 0) {
+                // Always use -1 for any negative subId from system
+                return ParticipantData.DEFAULT_SELF_SUB_ID;
+            }
+            return systemDefaultSubId;
+        }
+
+        @Override
+        public boolean getHasPreferredSmsSim() {
+            return getDefaultSmsSubscriptionId() != ParticipantData.DEFAULT_SELF_SUB_ID;
+        }
+
+        @Override
+        public int getActiveSubscriptionCount() {
+            return mSubscriptionManager.getActiveSubscriptionInfoCount();
+        }
+
+        @Override
+        public int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName) {
+            return getEffectiveIncomingSubIdFromSystem(intent.getIntExtra(extraName,
+                    ParticipantData.DEFAULT_SELF_SUB_ID));
+        }
+
+        private int getEffectiveIncomingSubIdFromSystem(int subId) {
+            if (subId < 0) {
+                if (mSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
+                    // For multi-SIM device, we can not decide which SIM to use if system
+                    // does not know either. So just make it the invalid sub id.
+                    return ParticipantData.DEFAULT_SELF_SUB_ID;
+                }
+                // For single-SIM device, it must come from the only SIM we have
+                return getDefaultSmsSubscriptionId();
+            }
+            return subId;
+        }
+
+        @Override
+        public int getSubIdFromTelephony(Cursor cursor, int subIdIndex) {
+            return getEffectiveIncomingSubIdFromSystem(cursor.getInt(subIdIndex));
+        }
+
+        @Override
+        public boolean isDataRoamingEnabled() {
+            final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
+            if (subInfo == null) {
+                // There is nothing we can do if system give us empty sub info
+                LogUtil.e(TAG, "PhoneUtils.isDataRoamingEnabled: system return empty sub info for "
+                        + mSubId);
+                return false;
+            }
+            return subInfo.getDataRoaming() != SubscriptionManager.DATA_ROAMING_DISABLE;
+        }
+
+        @Override
+        public boolean isMobileDataEnabled() {
+            boolean mobileDataEnabled = false;
+            try {
+                final Class cmClass = mTelephonyManager.getClass();
+                final Method method = cmClass.getDeclaredMethod("getDataEnabled", Integer.TYPE);
+                method.setAccessible(true); // Make the method callable
+                // get the setting for "mobile data"
+                mobileDataEnabled = (Boolean) method.invoke(
+                        mTelephonyManager, Integer.valueOf(mSubId));
+            } catch (final Exception e) {
+                LogUtil.e(TAG, "PhoneUtil.isMobileDataEnabled: system api not found", e);
+            }
+            return mobileDataEnabled;
+
+        }
+
+        @Override
+        public HashSet<String> getNormalizedSelfNumbers() {
+            final HashSet<String> numbers = new HashSet<>();
+            for (SubscriptionInfo info : getActiveSubscriptionInfoList()) {
+                numbers.add(PhoneUtils.get(info.getSubscriptionId()).getCanonicalForSelf(
+                        true/*allowOverride*/));
+            }
+            return numbers;
+        }
+    }
+
+    /**
+     * A convenient get() method that uses the default SIM. Use this when SIM is
+     * not relevant, e.g. isDefaultSmsApp
+     *
+     * @return an instance of PhoneUtils for default SIM
+     */
+    public static PhoneUtils getDefault() {
+        return Factory.get().getPhoneUtils(ParticipantData.DEFAULT_SELF_SUB_ID);
+    }
+
+    /**
+     * Get an instance of PhoneUtils associated with a specific SIM, which is also platform
+     * specific.
+     *
+     * @param subId The SIM's subscription ID
+     * @return the instance
+     */
+    public static PhoneUtils get(int subId) {
+        return Factory.get().getPhoneUtils(subId);
+    }
+
+    public LMr1 toLMr1() {
+        if (OsUtil.isAtLeastL_MR1()) {
+            return (LMr1) this;
+        } else {
+            Assert.fail("PhoneUtils.toLMr1(): invalid OS version");
+            return null;
+        }
+    }
+
+    /**
+     * Check if this device supports SMS
+     *
+     * @return true if SMS is supported, false otherwise
+     */
+    public boolean isSmsCapable() {
+        return mTelephonyManager.isSmsCapable();
+    }
+
+    /**
+     * Check if this device supports voice calling
+     *
+     * @return true if voice calling is supported, false otherwise
+     */
+    public boolean isVoiceCapable() {
+        return mTelephonyManager.isVoiceCapable();
+    }
+
+    /**
+     * Get the ISO country code from system locale setting
+     *
+     * @return the ISO country code from system locale
+     */
+    private static String getLocaleCountry() {
+        final String country = Locale.getDefault().getCountry();
+        if (TextUtils.isEmpty(country)) {
+            return null;
+        }
+        return country.toUpperCase();
+    }
+
+    /**
+     * Get ISO country code from the SIM, if not available, fall back to locale
+     *
+     * @return SIM or locale ISO country code
+     */
+    public String getSimOrDefaultLocaleCountry() {
+        String country = getSimCountry();
+        if (country == null) {
+            country = getLocaleCountry();
+        }
+        return country;
+    }
+
+    // Get or set the cache of canonicalized phone numbers for a specific country
+    private static ArrayMap<String, String> getOrAddCountryMapInCacheLocked(String country) {
+        if (country == null) {
+            country = "";
+        }
+        ArrayMap<String, String> countryMap = sCanonicalPhoneNumberCache.get(country);
+        if (countryMap == null) {
+            countryMap = new ArrayMap<>();
+            sCanonicalPhoneNumberCache.put(country, countryMap);
+        }
+        return countryMap;
+    }
+
+    // Get canonicalized phone number from cache
+    private static String getCanonicalFromCache(final String phoneText, String country) {
+        synchronized (sCanonicalPhoneNumberCache) {
+            final ArrayMap<String, String> countryMap = getOrAddCountryMapInCacheLocked(country);
+            return countryMap.get(phoneText);
+        }
+    }
+
+    // Put canonicalized phone number into cache
+    private static void putCanonicalToCache(final String phoneText, String country,
+            final String canonical) {
+        synchronized (sCanonicalPhoneNumberCache) {
+            final ArrayMap<String, String> countryMap = getOrAddCountryMapInCacheLocked(country);
+            countryMap.put(phoneText, canonical);
+        }
+    }
+
+    /**
+     * Utility method to parse user input number into standard E164 number.
+     *
+     * @param phoneText Phone number text as input by user.
+     * @param country ISO country code based on which to parse the number.
+     * @return E164 phone number. Returns null in case parsing failed.
+     */
+    private static String getValidE164Number(final String phoneText, final String country) {
+        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+        try {
+            final PhoneNumber phoneNumber = phoneNumberUtil.parse(phoneText, country);
+            if (phoneNumber != null && phoneNumberUtil.isValidNumber(phoneNumber)) {
+                return phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
+            }
+        } catch (final NumberParseException e) {
+            LogUtil.e(TAG, "PhoneUtils.getValidE164Number(): Not able to parse phone number "
+                        + LogUtil.sanitizePII(phoneText) + " for country " + country);
+        }
+        return null;
+    }
+
+    /**
+     * Canonicalize phone number using system locale country
+     *
+     * @param phoneText The phone number to canonicalize
+     * @return the canonicalized number
+     */
+    public String getCanonicalBySystemLocale(final String phoneText) {
+        return getCanonicalByCountry(phoneText, getLocaleCountry());
+    }
+
+    /**
+     * Canonicalize phone number using SIM's country, may fall back to system locale country
+     * if SIM country can not be obtained
+     *
+     * @param phoneText The phone number to canonicalize
+     * @return the canonicalized number
+     */
+    public String getCanonicalBySimLocale(final String phoneText) {
+        return getCanonicalByCountry(phoneText, getSimOrDefaultLocaleCountry());
+    }
+
+    /**
+     * Canonicalize phone number using a country code.
+     * This uses an internal cache per country to speed up.
+     *
+     * @param phoneText The phone number to canonicalize
+     * @param country The ISO country code to use
+     * @return the canonicalized number, or the original number if can't be parsed
+     */
+    private String getCanonicalByCountry(final String phoneText, final String country) {
+        Assert.notNull(phoneText);
+
+        String canonicalNumber = getCanonicalFromCache(phoneText, country);
+        if (canonicalNumber != null) {
+            return canonicalNumber;
+        }
+        canonicalNumber = getValidE164Number(phoneText, country);
+        if (canonicalNumber == null) {
+            // If we can't normalize this number, we just use the display string number.
+            // This is possible for short codes and other non-localizable numbers.
+            canonicalNumber = phoneText;
+        }
+        putCanonicalToCache(phoneText, country, canonicalNumber);
+        return canonicalNumber;
+    }
+
+    /**
+     * Canonicalize the self (per SIM) phone number
+     *
+     * @param allowOverride whether to use the override number in app settings
+     * @return the canonicalized self phone number
+     */
+    public String getCanonicalForSelf(final boolean allowOverride) {
+        String selfNumber = null;
+        try {
+            selfNumber = getSelfRawNumber(allowOverride);
+        } catch (IllegalStateException e) {
+            // continue;
+        }
+        if (selfNumber == null) {
+            return "";
+        }
+        return getCanonicalBySimLocale(selfNumber);
+    }
+
+    /**
+     * Get the SIM's phone number in NATIONAL format with only digits, used in sending
+     * as LINE1NOCOUNTRYCODE macro in mms_config
+     *
+     * @return all digits national format number of the SIM
+     */
+    public String getSimNumberNoCountryCode() {
+        String selfNumber = null;
+        try {
+            selfNumber = getSelfRawNumber(false/*allowOverride*/);
+        } catch (IllegalStateException e) {
+            // continue
+        }
+        if (selfNumber == null) {
+            selfNumber = "";
+        }
+        final String country = getSimCountry();
+        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+        try {
+            final PhoneNumber phoneNumber = phoneNumberUtil.parse(selfNumber, country);
+            if (phoneNumber != null && phoneNumberUtil.isValidNumber(phoneNumber)) {
+                return phoneNumberUtil
+                        .format(phoneNumber, PhoneNumberFormat.NATIONAL)
+                        .replaceAll("\\D", "");
+            }
+        } catch (final NumberParseException e) {
+            LogUtil.e(TAG, "PhoneUtils.getSimNumberNoCountryCode(): Not able to parse phone number "
+                    + LogUtil.sanitizePII(selfNumber) + " for country " + country);
+        }
+        return selfNumber;
+
+    }
+
+    /**
+     * Format a phone number for displaying, using system locale country.
+     * If the country code matches between the system locale and the input phone number,
+     * it will be formatted into NATIONAL format, otherwise, the INTERNATIONAL format
+     *
+     * @param phoneText The original phone text
+     * @return formatted number
+     */
+    public String formatForDisplay(final String phoneText) {
+        // Only format a valid number which length >=6
+        if (TextUtils.isEmpty(phoneText) ||
+                phoneText.replaceAll("\\D", "").length() < MINIMUM_PHONE_NUMBER_LENGTH_TO_FORMAT) {
+            return phoneText;
+        }
+        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+        final String systemCountry = getLocaleCountry();
+        final int systemCountryCode = phoneNumberUtil.getCountryCodeForRegion(systemCountry);
+        try {
+            final PhoneNumber parsedNumber = phoneNumberUtil.parse(phoneText, systemCountry);
+            final PhoneNumberFormat phoneNumberFormat =
+                    (systemCountryCode > 0 && parsedNumber.getCountryCode() == systemCountryCode) ?
+                            PhoneNumberFormat.NATIONAL : PhoneNumberFormat.INTERNATIONAL;
+            return phoneNumberUtil.format(parsedNumber, phoneNumberFormat);
+        } catch (NumberParseException e) {
+            LogUtil.e(TAG, "PhoneUtils.formatForDisplay: invalid phone number "
+                    + LogUtil.sanitizePII(phoneText) + " with country " + systemCountry);
+            return phoneText;
+        }
+    }
+
+    /**
+     * Is Messaging the default SMS app?
+     * - On KLP+ this checks the system setting.
+     * - On JB (and below) this always returns true, since the setting was added in KLP.
+     */
+    public boolean isDefaultSmsApp() {
+        if (OsUtil.isAtLeastKLP()) {
+            final String configuredApplication = Telephony.Sms.getDefaultSmsPackage(mContext);
+            return  mContext.getPackageName().equals(configuredApplication);
+        }
+        return true;
+    }
+
+    /**
+     * Get default SMS app package name
+     *
+     * @return the package name of default SMS app
+     */
+    public String getDefaultSmsApp() {
+        if (OsUtil.isAtLeastKLP()) {
+            return Telephony.Sms.getDefaultSmsPackage(mContext);
+        }
+        return null;
+    }
+
+    /**
+     * Determines if SMS is currently enabled on this device.
+     * - Device must support SMS
+     * - On KLP+ we must be set as the default SMS app
+     */
+    public boolean isSmsEnabled() {
+        return isSmsCapable() && isDefaultSmsApp();
+    }
+
+    /**
+     * Returns the name of the default SMS app, or the empty string if there is
+     * an error or there is no default app (e.g. JB and below).
+     */
+    public String getDefaultSmsAppLabel() {
+        if (OsUtil.isAtLeastKLP()) {
+            final String packageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+            final PackageManager pm = mContext.getPackageManager();
+            try {
+                final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
+                return pm.getApplicationLabel(appInfo).toString();
+            } catch (NameNotFoundException e) {
+                // Fall through and return empty string
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Gets the state of Airplane Mode.
+     *
+     * @return true if enabled.
+     */
+    @SuppressWarnings("deprecation")
+    public boolean isAirplaneModeOn() {
+        if (OsUtil.isAtLeastJB_MR1()) {
+            return Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+        } else {
+            return Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.AIRPLANE_MODE_ON, 0) != 0;
+        }
+    }
+
+    public static String getMccMncString(int[] mccmnc) {
+        if (mccmnc == null || mccmnc.length != 2) {
+            return "000000";
+        }
+        return String.format("%03d%03d", mccmnc[0], mccmnc[1]);
+    }
+
+    public static String canonicalizeMccMnc(final String mcc, final String mnc) {
+        try {
+            return String.format("%03d%03d", Integer.parseInt(mcc), Integer.parseInt(mnc));
+        } catch (final NumberFormatException e) {
+            // Return invalid as is
+            LogUtil.w(TAG, "canonicalizeMccMnc: invalid mccmnc:" + mcc + " ," + mnc);
+        }
+        return mcc + mnc;
+    }
+
+    /**
+     * Returns whether the given destination is valid for sending SMS/MMS message.
+     */
+    public static boolean isValidSmsMmsDestination(final String destination) {
+        return PhoneNumberUtils.isWellFormedSmsAddress(destination) ||
+                MmsSmsUtils.isEmailAddress(destination);
+    }
+
+    public interface SubscriptionRunnable {
+        void runForSubscription(int subId);
+    }
+
+    /**
+     * A convenience method for iterating through all active subscriptions
+     *
+     * @param runnable a {@link SubscriptionRunnable} for performing work on each subscription.
+     */
+    public static void forEachActiveSubscription(final SubscriptionRunnable runnable) {
+        if (OsUtil.isAtLeastL_MR1()) {
+            final List<SubscriptionInfo> subscriptionList =
+                    getDefault().toLMr1().getActiveSubscriptionInfoList();
+            for (final SubscriptionInfo subscriptionInfo : subscriptionList) {
+                runnable.runForSubscription(subscriptionInfo.getSubscriptionId());
+            }
+        } else {
+            runnable.runForSubscription(ParticipantData.DEFAULT_SELF_SUB_ID);
+        }
+    }
+
+    private static String getNumberFromPrefs(final Context context, final int subId) {
+        final BuglePrefs prefs = BuglePrefs.getSubscriptionPrefs(subId);
+        final String mmsPhoneNumberPrefKey =
+                context.getString(R.string.mms_phone_number_pref_key);
+        final String userDefinedNumber = prefs.getString(mmsPhoneNumberPrefKey, null);
+        if (!TextUtils.isEmpty(userDefinedNumber)) {
+            return userDefinedNumber;
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/messaging/util/RingtoneUtil.java b/src/com/android/messaging/util/RingtoneUtil.java
new file mode 100644
index 0000000..a7facfb
--- /dev/null
+++ b/src/com/android/messaging/util/RingtoneUtil.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.net.Uri;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+
+public class RingtoneUtil {
+    /**
+     * Return a ringtone Uri for the string representation passed in. Use the app
+     * and system defaults as fallbacks
+     * @param ringtoneString is the ringtone to resolve
+     * @return the Uri of the ringtone or the fallback ringtone
+     */
+    public static Uri getNotificationRingtoneUri(String ringtoneString) {
+        if (ringtoneString == null) {
+            // No override specified, fall back to system-wide setting.
+            final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
+            final Context context = Factory.get().getApplicationContext();
+            final String prefKey = context.getString(R.string.notification_sound_pref_key);
+            ringtoneString = prefs.getString(prefKey, null);
+        }
+
+        if (!TextUtils.isEmpty(ringtoneString)) {
+            // We have set a value, even if it is the default Uri at some point
+            return Uri.parse(ringtoneString);
+        } else if (ringtoneString == null) {
+            // We have no setting specified (== null), so we default to the system default
+            return Settings.System.DEFAULT_NOTIFICATION_URI;
+        } else {
+            // An empty string (== "") here is the result of selecting "None" as the ringtone
+            return null;
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/SafeAsyncTask.java b/src/com/android/messaging/util/SafeAsyncTask.java
new file mode 100644
index 0000000..1cce6e9
--- /dev/null
+++ b/src/com/android/messaging/util/SafeAsyncTask.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Debug;
+import android.os.SystemClock;
+
+import com.android.messaging.Factory;
+import com.android.messaging.util.Assert.RunsOnAnyThread;
+
+/**
+ * Wrapper class which provides explicit API for:
+ * <ol>
+ *   <li>Threading policy choice - Users of this class should use the explicit API instead of
+ *       {@link #execute} which uses different threading policy on different OS versions.
+ *   <li>Enforce creation on main thread as required by AsyncTask
+ *   <li>Enforce that the background task does not take longer than expected.
+ * </ol>
+ */
+public abstract class SafeAsyncTask<Params, Progress, Result>
+        extends AsyncTask<Params, Progress, Result> {
+    private static final long DEFAULT_MAX_EXECUTION_TIME_MILLIS = 10 * 1000; // 10 seconds
+
+    /** This is strongly discouraged as it can block other AsyncTasks indefinitely. */
+    public static final long UNBOUNDED_TIME = Long.MAX_VALUE;
+
+    private static final String WAKELOCK_ID = "bugle_safe_async_task_wakelock";
+    protected static final int WAKELOCK_OP = 1000;
+    private static WakeLockHelper sWakeLock = new WakeLockHelper(WAKELOCK_ID);
+
+    private final long mMaxExecutionTimeMillis;
+    private final boolean mCancelExecutionOnTimeout;
+    private boolean mThreadPoolRequested;
+
+    public SafeAsyncTask() {
+        this(DEFAULT_MAX_EXECUTION_TIME_MILLIS, false);
+    }
+
+    public SafeAsyncTask(final long maxTimeMillis) {
+        this(maxTimeMillis, false);
+    }
+
+    /**
+     * @param maxTimeMillis maximum expected time for the background operation. This is just
+     *        a diagnostic tool to catch unexpectedly long operations. If an operation does take
+     *        longer than expected, it is fine to increase this argument. If the value is larger
+     *        than a minute, you should consider using a dedicated thread so as not to interfere
+     *        with other AsyncTasks.
+     *
+     *        <p>Use {@link #UNBOUNDED_TIME} if you do not know the maximum expected time. This
+     *        is strongly discouraged as it can block other AsyncTasks indefinitely.
+     *
+     * @param cancelExecutionOnTimeout whether to attempt to cancel the task execution on timeout.
+     *        If this is set, at execution timeout we will call cancel(), so doInBackgroundTimed()
+     *        should periodically check if the task is to be cancelled and finish promptly if
+     *        possible, and handle the cancel event in onCancelled(). Also, at the end of execution
+     *        we will not crash the execution if it went over limit since we explicitly canceled it.
+     */
+    public SafeAsyncTask(final long maxTimeMillis, final boolean cancelExecutionOnTimeout) {
+        Assert.isMainThread(); // AsyncTask has to be created on the main thread
+        mMaxExecutionTimeMillis = maxTimeMillis;
+        mCancelExecutionOnTimeout = cancelExecutionOnTimeout;
+    }
+
+    public final SafeAsyncTask<Params, Progress, Result> executeOnThreadPool(
+            final Params... params) {
+        Assert.isMainThread(); // AsyncTask requires this
+        mThreadPoolRequested = true;
+        executeOnExecutor(THREAD_POOL_EXECUTOR, params);
+        return this;
+    }
+
+    protected abstract Result doInBackgroundTimed(final Params... params);
+
+    @Override
+    protected final Result doInBackground(final Params... params) {
+        // This enforces that executeOnThreadPool was called, not execute. Ideally, we would
+        // make execute throw an exception, but since it is final, we cannot override it.
+        Assert.isTrue(mThreadPoolRequested);
+
+        if (mCancelExecutionOnTimeout) {
+            ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    if (getStatus() == Status.RUNNING) {
+                        // Cancel the task if it's still running.
+                        LogUtil.w(LogUtil.BUGLE_TAG, String.format("%s timed out and is canceled",
+                                this));
+                        cancel(true /* mayInterruptIfRunning */);
+                    }
+                }
+            }, mMaxExecutionTimeMillis);
+        }
+
+        final long startTime = SystemClock.elapsedRealtime();
+        try {
+            return doInBackgroundTimed(params);
+        } finally {
+            final long executionTime = SystemClock.elapsedRealtime() - startTime;
+            if (executionTime > mMaxExecutionTimeMillis) {
+                LogUtil.w(LogUtil.BUGLE_TAG, String.format("%s took %dms", this, executionTime));
+                // Don't crash if debugger is attached or if we are asked to cancel on timeout.
+                if (!Debug.isDebuggerConnected() && !mCancelExecutionOnTimeout) {
+                    Assert.fail(this + " took too long");
+                }
+            }
+        }
+
+    }
+
+    @Override
+    protected void onPostExecute(final Result result) {
+        // No need to use AsyncTask at all if there is no onPostExecute
+        Assert.fail("Use SafeAsyncTask.executeOnThreadPool");
+    }
+
+    /**
+     * This provides a way for people to run async tasks but without onPostExecute.
+     * This can be called on any thread.
+     *
+     * Run code in a thread using AsyncTask's thread pool.
+     *
+     * To enable wakelock during the execution, see {@link #executeOnThreadPool(Runnable, boolean)}
+     *
+     * @param runnable The Runnable to execute asynchronously
+     */
+    @RunsOnAnyThread
+    public static void executeOnThreadPool(final Runnable runnable) {
+        executeOnThreadPool(runnable, false);
+    }
+
+    /**
+     * This provides a way for people to run async tasks but without onPostExecute.
+     * This can be called on any thread.
+     *
+     * Run code in a thread using AsyncTask's thread pool.
+     *
+     * @param runnable The Runnable to execute asynchronously
+     * @param withWakeLock when set, a wake lock will be held for the duration of the runnable
+     *        execution
+     */
+    public static void executeOnThreadPool(final Runnable runnable, final boolean withWakeLock) {
+        if (withWakeLock) {
+            final Intent intent = new Intent();
+            sWakeLock.acquire(Factory.get().getApplicationContext(), intent, WAKELOCK_OP);
+            THREAD_POOL_EXECUTOR.execute(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        runnable.run();
+                    } finally {
+                        sWakeLock.release(intent, WAKELOCK_OP);
+                    }
+                }
+            });
+        } else {
+            THREAD_POOL_EXECUTOR.execute(runnable);
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/SwitchCompatUtils.java b/src/com/android/messaging/util/SwitchCompatUtils.java
new file mode 100644
index 0000000..9c920f6
--- /dev/null
+++ b/src/com/android/messaging/util/SwitchCompatUtils.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import androidx.appcompat.graphics.drawable.DrawableWrapperCompat;
+import androidx.appcompat.widget.SwitchCompat;
+import android.util.TypedValue;
+
+/* Most methods in this file are copied from
+ * v7/appcompat/src/androidx.appcompat.internal/widget/TintManager.java. It would be better if
+ * we could have just extended the TintManager but this is a final class that we do not have
+ * access to. */
+
+/**
+ * Util methods for the SwitchCompat widget
+ */
+public class SwitchCompatUtils {
+    /**
+     * Given a color and a SwitchCompat view, updates the SwitchCompat to appear with the appropiate
+     * color when enabled and checked
+     */
+    public static void updateSwitchCompatColor(SwitchCompat switchCompat, final int color) {
+        final Context context = switchCompat.getContext();
+        final TypedValue typedValue = new TypedValue();
+
+        switchCompat.setThumbDrawable(getColorTintedDrawable(switchCompat.getThumbDrawable(),
+                getSwitchThumbColorStateList(context, color, typedValue),
+                PorterDuff.Mode.MULTIPLY));
+
+        switchCompat.setTrackDrawable(getColorTintedDrawable(switchCompat.getTrackDrawable(),
+                getSwitchTrackColorStateList(context, color, typedValue), PorterDuff.Mode.SRC_IN));
+    }
+
+    private static Drawable getColorTintedDrawable(Drawable oldDrawable,
+            final ColorStateList colorStateList, final PorterDuff.Mode mode) {
+        final int[] thumbState = oldDrawable.isStateful() ? oldDrawable.getState() : null;
+        if (oldDrawable instanceof DrawableWrapperCompat) {
+            oldDrawable = ((DrawableWrapperCompat) oldDrawable).getDrawable();
+        }
+        final Drawable newDrawable = new TintDrawableWrapper(oldDrawable, colorStateList, mode);
+        if (thumbState != null) {
+            newDrawable.setState(thumbState);
+        }
+        return newDrawable;
+    }
+
+    private static ColorStateList getSwitchThumbColorStateList(final Context context,
+            final int color, final TypedValue typedValue) {
+        final int[][] states = new int[3][];
+        final int[] colors = new int[3];
+        int i = 0;
+        // Disabled state
+        states[i] = new int[] { -android.R.attr.state_enabled };
+        colors[i] = getColor(Color.parseColor("#ffbdbdbd"), 1f);
+        i++;
+        states[i] = new int[] { android.R.attr.state_checked };
+        colors[i] = color;
+        i++;
+        // Default enabled state
+        states[i] = new int[0];
+        colors[i] = getThemeAttrColor(context, typedValue,
+                androidx.appcompat.R.attr.colorSwitchThumbNormal);
+        i++;
+        return new ColorStateList(states, colors);
+    }
+
+    private static ColorStateList getSwitchTrackColorStateList(final Context context,
+            final int color, final TypedValue typedValue) {
+        final int[][] states = new int[3][];
+        final int[] colors = new int[3];
+        int i = 0;
+        // Disabled state
+        states[i] = new int[] { -android.R.attr.state_enabled };
+        colors[i] = getThemeAttrColor(context, typedValue, android.R.attr.colorForeground, 0.1f);
+        i++;
+        states[i] = new int[] { android.R.attr.state_checked };
+        colors[i] = getColor(color, 0.3f);
+        i++;
+        // Default enabled state
+        states[i] = new int[0];
+        colors[i] = getThemeAttrColor(context, typedValue, android.R.attr.colorForeground, 0.3f);
+        i++;
+        return new ColorStateList(states, colors);
+    }
+
+    private static int getThemeAttrColor(final Context context, final TypedValue typedValue,
+            final int attr) {
+        if (context.getTheme().resolveAttribute(attr, typedValue, true)) {
+            if (typedValue.type >= TypedValue.TYPE_FIRST_INT
+                    && typedValue.type <= TypedValue.TYPE_LAST_INT) {
+                return typedValue.data;
+            } else if (typedValue.type == TypedValue.TYPE_STRING) {
+                return context.getResources().getColor(typedValue.resourceId);
+            }
+        }
+        return 0;
+    }
+
+    private static int getThemeAttrColor(final Context context, final TypedValue typedValue,
+            final int attr, final float alpha) {
+        final int color = getThemeAttrColor(context, typedValue, attr);
+        return getColor(color, alpha);
+    }
+
+    private static int getColor(int color, float alpha) {
+        final int originalAlpha = Color.alpha(color);
+        // Return the color, multiplying the original alpha by the disabled value
+        return (color & 0x00ffffff) | (Math.round(originalAlpha * alpha) << 24);
+    }
+}
diff --git a/src/com/android/messaging/util/TextUtil.java b/src/com/android/messaging/util/TextUtil.java
new file mode 100644
index 0000000..f715551
--- /dev/null
+++ b/src/com/android/messaging/util/TextUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import androidx.annotation.Nullable;
+
+public class TextUtil {
+    /**
+     * Returns true if the string is empty, null or only whitespace.
+     */
+    public static boolean isAllWhitespace(@Nullable String string) {
+      if (string == null || string.isEmpty()) {
+        return true;
+      }
+
+      for (int i = 0; i < string.length(); ++i) {
+        if (!Character.isWhitespace(string.charAt(i))) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
+    /**
+     * Taken from PhoneNumberUtils, where it is only available in API 21+ Replaces all unicode
+     * (e.g. Arabic, Persian) digits with their decimal digit equivalents.
+     *
+     * @param number the number to perform the replacement on.
+     * @return the replaced number.
+     */
+    public static String replaceUnicodeDigits(String number) {
+        StringBuilder normalizedDigits = new StringBuilder(number.length());
+        for (char c : number.toCharArray()) {
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                normalizedDigits.append(digit);
+            } else {
+                normalizedDigits.append(c);
+            }
+        }
+        return normalizedDigits.toString();
+    }
+
+    /**
+     * Appends text to the stringBuilder.
+     * If stringBuilder already has content, separator is prepended to create a separator between
+     * entries.
+     * @param stringBuilder The stringBuilder to add to
+     * @param text The text to append
+     * @param separator The separator to add if there is already text, typically "," or "\n"
+     */
+    public static void appendWithSeparator(final StringBuilder stringBuilder, final String text,
+            final String separator) {
+        if (stringBuilder.length() > 0) {
+            stringBuilder.append(separator);
+        }
+        stringBuilder.append(text);
+    }
+}
diff --git a/src/com/android/messaging/util/ThreadUtil.java b/src/com/android/messaging/util/ThreadUtil.java
new file mode 100644
index 0000000..3b935d8
--- /dev/null
+++ b/src/com/android/messaging/util/ThreadUtil.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.os.Handler;
+import android.os.Looper;
+
+public class ThreadUtil {
+    private static final Handler sHandler = new Handler(Looper.getMainLooper());
+
+    public static Handler getMainThreadHandler() {
+        return sHandler;
+    }
+}
diff --git a/src/com/android/messaging/util/TintDrawableWrapper.java b/src/com/android/messaging/util/TintDrawableWrapper.java
new file mode 100644
index 0000000..b426f8c
--- /dev/null
+++ b/src/com/android/messaging/util/TintDrawableWrapper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import androidx.appcompat.graphics.drawable.DrawableWrapperCompat;
+
+/*
+ * This is directly copied from v7/appcompat/src/androidx.appcompat.internal/widget/TintManager.java
+ */
+
+/**
+ * A {@link DrawableWrapperCompat} which updates it's color filter using a {@link ColorStateList}.
+ */
+class TintDrawableWrapper extends DrawableWrapperCompat {
+    private final ColorStateList mTintStateList;
+    private final PorterDuff.Mode mTintMode;
+    private int mCurrentColor;
+    public TintDrawableWrapper(Drawable drawable, ColorStateList tintStateList) {
+        this(drawable, tintStateList, PorterDuff.Mode.SRC_IN);
+    }
+    public TintDrawableWrapper(Drawable drawable, ColorStateList tintStateList,
+            PorterDuff.Mode tintMode) {
+        super(drawable);
+        mTintStateList = tintStateList;
+        mTintMode = tintMode;
+    }
+    @Override
+    public boolean isStateful() {
+        return (mTintStateList != null && mTintStateList.isStateful()) || super.isStateful();
+    }
+    @Override
+    public boolean setState(int[] stateSet) {
+        boolean handled = super.setState(stateSet);
+        handled = updateTint(stateSet) || handled;
+        return handled;
+    }
+    private boolean updateTint(int[] state) {
+        if (mTintStateList != null) {
+            final int color = mTintStateList.getColorForState(state, mCurrentColor);
+            if (color != mCurrentColor) {
+                if (color != Color.TRANSPARENT) {
+                    setColorFilter(color, mTintMode);
+                } else {
+                    clearColorFilter();
+                }
+                mCurrentColor = color;
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/messaging/util/Trace.java b/src/com/android/messaging/util/Trace.java
new file mode 100644
index 0000000..69910f7
--- /dev/null
+++ b/src/com/android/messaging/util/Trace.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+
+import android.annotation.TargetApi;
+import android.os.Build;
+
+/**
+ * Helper class for systrace (see http://developer.android.com/tools/help/systrace.html).<p>
+ * To enable, set log.tag.Bugle_Trace (defined by {@link #TAG} to VERBOSE before
+ * the process starts.<p>
+ * Note that this will run only on JBMR2 or later; on earlier platforms or if the log
+ * tag isn't set, calls to {@link #beginSection(String)} or {@link #endSection()} are no-ops. <p>
+ * Internally, calls dispatch to either a class that actually does work or a class that doesn't.
+ * This avoids Dalvik complaining when it loads the class on earlier platforms that the
+ * opcodes aren't available, and, according to the Dalvik team, using vtable dispatching for
+ * something like this should be faster than if (OsUtil.isAtLeast...()) on each call.
+ */
+public final class Trace {
+    private static final String TAG = "Bugle_Trace";
+    private abstract static class AbstractTrace {
+        abstract void beginSection(String sectionName);
+        abstract void endSection();
+    }
+
+    private static final AbstractTrace sTrace;
+
+    // Static initializer to pick the correct trace class to handle tracing.
+    static {
+        // Use android.util.Log instead of LogUtil here to avoid pulling in Gservices
+        // too early in app startup.
+        if (OsUtil.isAtLeastJB_MR2() &&
+                android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE)) {
+            sTrace = new TraceJBMR2();
+        } else {
+            sTrace = new TraceShim();
+        }
+    }
+
+    /**
+     * Writes a trace message to indicate that a given section of code has begun. This call must
+     * be followed by a corresponding call to {@link #endSection()} on the same thread.
+     *
+     * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
+     * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
+     * these characters they will be replaced with a space character in the trace.
+     *
+     * @param sectionName The name of the code section to appear in the trace.  This may be at
+     * most 127 Unicode code units long.
+     */
+    public static void beginSection(String sectionName) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "beginSection() " + sectionName);
+        }
+        sTrace.beginSection(sectionName);
+    }
+
+    /**
+     * Writes a trace message to indicate that a given section of code has ended. This call must
+     * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method
+     * will mark the end of the most recently begun section of code, so care must be taken to
+     * ensure that beginSection / endSection pairs are properly nested and called from the same
+     * thread.
+     */
+    public static void endSection() {
+        sTrace.endSection();
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "endSection()");
+        }
+    }
+
+    /**
+     * Internal class that we use if we really did enable tracing.
+     */
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+    private static final class TraceJBMR2 extends AbstractTrace {
+        @Override
+        void beginSection(String sectionName) {
+            android.os.Trace.beginSection(sectionName);
+        }
+
+        @Override
+        void endSection() {
+            android.os.Trace.endSection();
+        }
+    }
+
+    /**
+     * Placeholder class that we use if we aren't really tracing.
+     */
+    private static final class TraceShim extends AbstractTrace {
+        @Override
+        void beginSection(String sectionName) {
+        }
+
+        @Override
+        void endSection() {
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/Typefaces.java b/src/com/android/messaging/util/Typefaces.java
new file mode 100644
index 0000000..eb8562c
--- /dev/null
+++ b/src/com/android/messaging/util/Typefaces.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.graphics.Typeface;
+
+/**
+ * Provides access to typefaces used by code. Specially important for typefaces coming from assets,
+ * which appear (from platform code inspection) to not be cached.
+ * Note: Considered making this a singleton provided by factory/appcontext, but seemed too simple,
+ * not worth stubbing.
+ */
+public class Typefaces {
+    private static Typeface sRobotoBold;
+    private static Typeface sRobotoNormal;
+
+    public static Typeface getRobotoBold() {
+        Assert.isMainThread();
+        if (sRobotoBold == null) {
+            sRobotoBold = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
+        }
+        return sRobotoBold;
+    }
+
+    public static Typeface getRobotoNormal() {
+        Assert.isMainThread();
+        if (sRobotoNormal == null) {
+            sRobotoNormal = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
+        }
+        return sRobotoNormal;
+    }
+}
diff --git a/src/com/android/messaging/util/UiUtils.java b/src/com/android/messaging/util/UiUtils.java
new file mode 100644
index 0000000..6e0c16e
--- /dev/null
+++ b/src/com/android/messaging/util/UiUtils.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.URLSpan;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.Interpolator;
+import android.view.animation.ScaleAnimation;
+import android.widget.RemoteViews;
+import android.widget.Toast;
+
+import com.android.messaging.Factory;
+import com.android.messaging.R;
+import com.android.messaging.ui.SnackBar;
+import com.android.messaging.ui.SnackBar.Placement;
+import com.android.messaging.ui.conversationlist.ConversationListActivity;
+import com.android.messaging.ui.SnackBarInteraction;
+import com.android.messaging.ui.SnackBarManager;
+import com.android.messaging.ui.UIIntents;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+public class UiUtils {
+    /** MediaPicker transition duration in ms */
+    public static final int MEDIAPICKER_TRANSITION_DURATION =
+            getApplicationContext().getResources().getInteger(
+                    R.integer.mediapicker_transition_duration);
+    /** Short transition duration in ms */
+    public static final int ASYNCIMAGE_TRANSITION_DURATION =
+            getApplicationContext().getResources().getInteger(
+                    R.integer.asyncimage_transition_duration);
+    /** Compose transition duration in ms */
+    public static final int COMPOSE_TRANSITION_DURATION =
+            getApplicationContext().getResources().getInteger(
+                    R.integer.compose_transition_duration);
+    /** Generic duration for revealing/hiding a view */
+    public static final int REVEAL_ANIMATION_DURATION =
+            getApplicationContext().getResources().getInteger(
+                    R.integer.reveal_view_animation_duration);
+
+    public static final Interpolator DEFAULT_INTERPOLATOR = new CubicBezierInterpolator(
+            0.4f, 0.0f, 0.2f, 1.0f);
+
+    public static final Interpolator EASE_IN_INTERPOLATOR = new CubicBezierInterpolator(
+            0.4f, 0.0f, 0.8f, 0.5f);
+
+    public static final Interpolator EASE_OUT_INTERPOLATOR = new CubicBezierInterpolator(
+            0.0f, 0.0f, 0.2f, 1f);
+
+    /** Show a simple toast at the bottom */
+    public static void showToastAtBottom(final int messageId) {
+        UiUtils.showToastAtBottom(getApplicationContext().getString(messageId));
+    }
+
+    /** Show a simple toast at the bottom */
+    public static void showToastAtBottom(final String message) {
+        final Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
+        toast.show();
+    }
+
+    /** Show a simple toast at the default position */
+    public static void showToast(final int messageId) {
+        final Toast toast = Toast.makeText(getApplicationContext(),
+                getApplicationContext().getString(messageId), Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
+        toast.show();
+    }
+
+    /** Show a simple toast at the default position */
+    public static void showToast(final int pluralsMessageId, final int count) {
+        final Toast toast = Toast.makeText(getApplicationContext(),
+                getApplicationContext().getResources().getQuantityString(pluralsMessageId, count),
+                Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
+        toast.show();
+    }
+
+    public static void showSnackBar(final Context context, @NonNull final View parentView,
+            final String message, @Nullable final Runnable runnable, final int runnableLabel,
+            @Nullable final List<SnackBarInteraction> interactions) {
+        Assert.notNull(context);
+        SnackBar.Action action = null;
+        switch (runnableLabel) {
+            case SnackBar.Action.SNACK_BAR_UNDO:
+                action = SnackBar.Action.createUndoAction(runnable);
+                break;
+            case SnackBar.Action.SNACK_BAR_RETRY:
+                action =  SnackBar.Action.createRetryAction(runnable);
+                break;
+            default :
+                break;
+        }
+
+        showSnackBarWithCustomAction(context, parentView, message, action, interactions,
+                                        null /* placement */);
+    }
+
+    public static void showSnackBarWithCustomAction(final Context context,
+            @NonNull final View parentView,
+            @NonNull final String message,
+            @NonNull final SnackBar.Action action,
+            @Nullable final List<SnackBarInteraction> interactions,
+            @Nullable final Placement placement) {
+        Assert.notNull(context);
+        Assert.isTrue(!TextUtils.isEmpty(message));
+        Assert.notNull(action);
+        SnackBarManager.get()
+            .newBuilder(parentView)
+            .setText(message)
+            .setAction(action)
+            .withInteractions(interactions)
+            .withPlacement(placement)
+            .show();
+    }
+
+    /**
+     * Run the given runnable once after the next layout pass of the view.
+     */
+    public static void doOnceAfterLayoutChange(final View view, final Runnable runnable) {
+        final OnLayoutChangeListener listener = new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(final View v, final int left, final int top, final int right,
+                    final int bottom, final int oldLeft, final int oldTop, final int oldRight,
+                    final int oldBottom) {
+                // Call the runnable outside the layout pass because very few actions are allowed in
+                // the layout pass
+                ThreadUtil.getMainThreadHandler().post(runnable);
+                view.removeOnLayoutChangeListener(this);
+            }
+        };
+        view.addOnLayoutChangeListener(listener);
+    }
+
+    public static boolean isLandscapeMode() {
+        return Factory.get().getApplicationContext().getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    private static Context getApplicationContext() {
+        return Factory.get().getApplicationContext();
+    }
+
+    public static CharSequence commaEllipsize(
+            final String text,
+            final TextPaint paint,
+            final int width,
+            final String oneMore,
+            final String more) {
+        CharSequence ellipsized = TextUtils.commaEllipsize(
+                text,
+                paint,
+                width,
+                oneMore,
+                more);
+        if (TextUtils.isEmpty(ellipsized)) {
+            ellipsized = text;
+        }
+        return ellipsized;
+    }
+
+    /**
+     * Reveals/Hides a view with a scale animation from view center.
+     * @param view the view to animate
+     * @param desiredVisibility desired visibility (e.g. View.GONE) for the animated view.
+     * @param onFinishRunnable an optional runnable called at the end of the animation
+     */
+    public static void revealOrHideViewWithAnimation(final View view, final int desiredVisibility,
+            @Nullable final Runnable onFinishRunnable) {
+        final boolean needAnimation = view.getVisibility() != desiredVisibility;
+        if (needAnimation) {
+            final float fromScale = desiredVisibility == View.VISIBLE ? 0F : 1F;
+            final float toScale = desiredVisibility == View.VISIBLE ? 1F : 0F;
+            final ScaleAnimation showHideAnimation =
+                    new ScaleAnimation(fromScale, toScale, fromScale, toScale,
+                            ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
+                            ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
+            showHideAnimation.setDuration(REVEAL_ANIMATION_DURATION);
+            showHideAnimation.setInterpolator(DEFAULT_INTERPOLATOR);
+            showHideAnimation.setAnimationListener(new AnimationListener() {
+                @Override
+                public void onAnimationStart(final Animation animation) {
+                }
+
+                @Override
+                public void onAnimationRepeat(final Animation animation) {
+                }
+
+                @Override
+                public void onAnimationEnd(final Animation animation) {
+                    if (onFinishRunnable != null) {
+                        // Rather than running this immediately, we post it to happen next so that
+                        // the animation will be completed so that the view can be detached from
+                        // it's window.  Otherwise, we may leak memory.
+                        ThreadUtil.getMainThreadHandler().post(onFinishRunnable);
+                    }
+                }
+            });
+            view.clearAnimation();
+            view.startAnimation(showHideAnimation);
+            // We are playing a view Animation; unlike view property animations, we can commit the
+            // visibility immediately instead of waiting for animation end.
+            view.setVisibility(desiredVisibility);
+        } else if (onFinishRunnable != null) {
+            // Make sure onFinishRunnable is always executed.
+            ThreadUtil.getMainThreadHandler().post(onFinishRunnable);
+        }
+    }
+
+    public static Rect getMeasuredBoundsOnScreen(final View view) {
+        final int[] location = new int[2];
+        view.getLocationOnScreen(location);
+        return new Rect(location[0], location[1],
+                location[0] + view.getMeasuredWidth(), location[1] + view.getMeasuredHeight());
+    }
+
+    public static void setStatusBarColor(final Activity activity, final int color) {
+        if (OsUtil.isAtLeastL()) {
+            // To achieve the appearance of an 80% opacity blend against a black background,
+            // each color channel is reduced in value by 20%.
+            final int blendedRed = (int) Math.floor(0.8 * Color.red(color));
+            final int blendedGreen = (int) Math.floor(0.8 * Color.green(color));
+            final int blendedBlue = (int) Math.floor(0.8 * Color.blue(color));
+
+            activity.getWindow().setStatusBarColor(
+                    Color.rgb(blendedRed, blendedGreen, blendedBlue));
+        }
+    }
+
+    public static void lockOrientation(final Activity activity) {
+        final int orientation = activity.getResources().getConfiguration().orientation;
+        final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+
+        // rotation tracks the rotation of the device from its natural orientation
+        // orientation tracks whether the screen is landscape or portrait.
+        // It is possible to have a rotation of 0 (device in its natural orientation) in portrait
+        // (phone), or in landscape (tablet), so we have to check both values to determine what to
+        // pass to setRequestedOrientation.
+        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
+            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+            } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+            }
+        } else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) {
+            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
+            } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+            }
+        }
+    }
+
+    public static void unlockOrientation(final Activity activity) {
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
+    }
+
+    public static int getPaddingStart(final View view) {
+        return OsUtil.isAtLeastJB_MR1() ? view.getPaddingStart() : view.getPaddingLeft();
+    }
+
+    public static int getPaddingEnd(final View view) {
+        return OsUtil.isAtLeastJB_MR1() ? view.getPaddingEnd() : view.getPaddingRight();
+    }
+
+    public static boolean isRtlMode() {
+        return OsUtil.isAtLeastJB_MR2() && Factory.get().getApplicationContext().getResources()
+                .getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+    }
+
+    /**
+     * Check if the activity needs to be redirected to permission check
+     * @return true if {@link Activity#finish()} was called because redirection was performed
+     */
+    public static boolean redirectToPermissionCheckIfNeeded(final Activity activity) {
+        if (!OsUtil.hasRequiredPermissions()) {
+            UIIntents.get().launchPermissionCheckActivity(activity);
+        } else {
+            // No redirect performed
+            return false;
+        }
+
+        // Redirect performed
+        activity.finish();
+        return true;
+    }
+
+    /**
+     * Called to check if all conditions are nominal and a "go" for some action, such as deleting
+     * a message, that requires this app to be the default app. This is also a precondition
+     * required for sending a draft.
+     * @return true if all conditions are nominal and we're ready to send a message
+     */
+    public static boolean isReadyForAction() {
+        final PhoneUtils phoneUtils = PhoneUtils.getDefault();
+
+        // Have all the conditions been met:
+        // Supports SMS?
+        // Has a preferred sim?
+        // Is the default sms app?
+        return phoneUtils.isSmsCapable() &&
+                phoneUtils.getHasPreferredSmsSim() &&
+                phoneUtils.isDefaultSmsApp();
+    }
+
+    /*
+     * Removes all html markup from the text and replaces links with the the text and a text version
+     * of the href.
+     * @param htmlText HTML markup text
+     * @return Sanitized string with link hrefs inlined
+     */
+    public static String stripHtml(final String htmlText) {
+        final StringBuilder result = new StringBuilder();
+        final Spanned markup = Html.fromHtml(htmlText);
+        final String strippedText = markup.toString();
+
+        final URLSpan[] links = markup.getSpans(0, markup.length() - 1, URLSpan.class);
+        int currentIndex = 0;
+        for (final URLSpan link : links) {
+            final int spanStart = markup.getSpanStart(link);
+            final int spanEnd = markup.getSpanEnd(link);
+            if (spanStart > currentIndex) {
+                result.append(strippedText, currentIndex, spanStart);
+            }
+            final String displayText = strippedText.substring(spanStart, spanEnd);
+            final String linkText = link.getURL();
+            result.append(getApplicationContext().getString(R.string.link_display_format,
+                    displayText, linkText));
+            currentIndex = spanEnd;
+        }
+        if (strippedText.length() > currentIndex) {
+            result.append(strippedText, currentIndex, strippedText.length());
+        }
+        return result.toString();
+    }
+
+    public static void setActionBarShadowVisibility(final AppCompatActivity activity, final boolean visible) {
+        final ActionBar actionBar = activity.getSupportActionBar();
+        actionBar.setElevation(visible ?
+                activity.getResources().getDimensionPixelSize(R.dimen.action_bar_elevation) :
+                0);
+        final View actionBarView = activity.getWindow().getDecorView().findViewById(
+                androidx.appcompat.R.id.decor_content_parent);
+        if (actionBarView != null) {
+            // AppCompatActionBar has one drawable Field, which is the shadow for the action bar
+            // set the alpha on that drawable manually
+            final Field[] fields = actionBarView.getClass().getDeclaredFields();
+            try {
+                for (final Field field : fields) {
+                    if (field.getType().equals(Drawable.class)) {
+                        field.setAccessible(true);
+                        final Drawable shadowDrawable = (Drawable) field.get(actionBarView);
+                        if (shadowDrawable != null) {
+                            shadowDrawable.setAlpha(visible ? 255 : 0);
+                            actionBarView.invalidate();
+                            return;
+                        }
+                    }
+                }
+            } catch (final IllegalAccessException ex) {
+                // Not expected, we should avoid this via field.setAccessible(true) above
+                LogUtil.e(LogUtil.BUGLE_TAG, "Error setting shadow visibility", ex);
+            }
+        }
+    }
+
+    /**
+     * Get the activity that's hosting the view, typically casting view.getContext() as an Activity
+     * is sufficient, but sometimes the context is a context wrapper, in which case we need to case
+     * the base context
+     */
+    public static Activity getActivity(final View view) {
+        if (view == null) {
+            return null;
+        }
+        return getActivity(view.getContext());
+    }
+
+    /**
+     * Get the activity for the supplied context, typically casting context as an Activity
+     * is sufficient, but sometimes the context is a context wrapper, in which case we need to case
+     * the base context
+     */
+    public static Activity getActivity(final Context context) {
+        if (context == null) {
+            return null;
+        }
+        if (context instanceof Activity) {
+            return (Activity) context;
+        }
+        if (context instanceof ContextWrapper) {
+            return getActivity(((ContextWrapper) context).getBaseContext());
+        }
+
+        // We've hit a non-activity context such as an app-context
+        return null;
+    }
+
+    public static RemoteViews getWidgetMissingPermissionView(final Context context) {
+        return new RemoteViews(context.getPackageName(), R.layout.widget_missing_permission);
+    }
+}
diff --git a/src/com/android/messaging/util/UriUtil.java b/src/com/android/messaging/util/UriUtil.java
new file mode 100644
index 0000000..f92155f
--- /dev/null
+++ b/src/com/android/messaging/util/UriUtil.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.provider.MediaStore;
+import androidx.annotation.NonNull;
+import android.text.TextUtils;
+
+import com.android.messaging.Factory;
+import com.android.messaging.datamodel.GalleryBoundCursorLoader;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
+import com.google.common.io.ByteStreams;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import java.util.HashSet;
+
+public class UriUtil {
+    private static final String SCHEME_SMS = "sms";
+    private static final String SCHEME_SMSTO = "smsto";
+    private static final String SCHEME_MMS = "mms";
+    private static final String SCHEME_MMSTO = "smsto";
+    public static final HashSet<String> SMS_MMS_SCHEMES = new HashSet<String>(
+        Arrays.asList(SCHEME_SMS, SCHEME_MMS, SCHEME_SMSTO, SCHEME_MMSTO));
+    private static final String SCHEME_HTTP = "http";
+    private static final String SCHEME_HTTPS = "https";
+
+    public static final String SCHEME_BUGLE = "bugle";
+    public static final HashSet<String> SUPPORTED_SCHEME = new HashSet<String>(
+        Arrays.asList(ContentResolver.SCHEME_ANDROID_RESOURCE,
+            ContentResolver.SCHEME_CONTENT,
+            ContentResolver.SCHEME_FILE,
+            SCHEME_BUGLE));
+
+    public static final String SCHEME_TEL = "tel:";
+
+    /**
+     * Get a Uri representation of the file path of a resource file.
+     */
+    public static Uri getUriForResourceFile(final String path) {
+        return TextUtils.isEmpty(path) ? null : Uri.fromFile(new File(path));
+    }
+
+    /**
+     * Extract the path from a file:// Uri, or null if the uri is of other scheme.
+     */
+    public static String getFilePathFromUri(final Uri uri) {
+        if (!isFileUri(uri)) {
+            return null;
+        }
+        return uri.getPath();
+    }
+
+    /**
+     * Returns whether the given Uri is local or remote.
+     */
+    public static boolean isLocalResourceUri(final Uri uri) {
+        final String scheme = uri.getScheme();
+        return TextUtils.equals(scheme, ContentResolver.SCHEME_ANDROID_RESOURCE) ||
+                TextUtils.equals(scheme, ContentResolver.SCHEME_CONTENT) ||
+                TextUtils.equals(scheme, ContentResolver.SCHEME_FILE);
+    }
+
+    /**
+     * Returns whether the given Uri is part of Bugle's app package
+     */
+    public static boolean isBugleAppResource(final Uri uri) {
+        final String scheme = uri.getScheme();
+        return TextUtils.equals(scheme, ContentResolver.SCHEME_ANDROID_RESOURCE);
+    }
+
+    /** Returns whether the given Uri is a file. */
+    public static boolean isFileUri(final Uri uri) {
+        return uri != null &&
+                uri.getScheme() != null &&
+                uri.getScheme().trim().toLowerCase().contains(ContentResolver.SCHEME_FILE);
+    }
+
+    /**
+     * Constructs an android.resource:// uri for the given resource id.
+     */
+    public static Uri getUriForResourceId(final Context context, final int resId) {
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(context.getPackageName())
+                .appendPath(String.valueOf(resId))
+                .build();
+    }
+
+    /**
+     * Returns whether the given Uri string is local.
+     */
+    public static boolean isLocalUri(@NonNull final Uri uri) {
+        Assert.notNull(uri);
+        return SUPPORTED_SCHEME.contains(uri.getScheme());
+    }
+
+    private static final String MEDIA_STORE_URI_KLP = "com.android.providers.media.documents";
+
+    /**
+     * Check if a URI is from the MediaStore
+     */
+    public static boolean isMediaStoreUri(final Uri uri) {
+        final String uriAuthority = uri.getAuthority();
+        return TextUtils.equals(ContentResolver.SCHEME_CONTENT, uri.getScheme())
+                && (TextUtils.equals(MediaStore.AUTHORITY, uriAuthority) ||
+                // KK changed the media store authority name
+                TextUtils.equals(MEDIA_STORE_URI_KLP, uriAuthority));
+    }
+
+    /**
+     * Gets the content:// style URI for the given MediaStore row Id in the files table on the
+     * external volume.
+     *
+     * @param id the MediaStore row Id to get the URI for
+     * @return the URI to the files table on the external storage.
+     */
+    public static Uri getContentUriForMediaStoreId(final long id) {
+        return MediaStore.Files.getContentUri(
+                GalleryBoundCursorLoader.MEDIA_SCANNER_VOLUME_EXTERNAL, id);
+    }
+
+    /**
+     * Gets the size in bytes for the content uri. Currently we only support content in the
+     * scratch space.
+     */
+    @DoesNotRunOnMainThread
+    public static long getContentSize(final Uri uri) {
+        Assert.isNotMainThread();
+        if (isLocalResourceUri(uri)) {
+            ParcelFileDescriptor pfd = null;
+            try {
+                pfd = Factory.get().getApplicationContext()
+                        .getContentResolver().openFileDescriptor(uri, "r");
+                return Math.max(pfd.getStatSize(), 0);
+            } catch (final FileNotFoundException e) {
+                LogUtil.e(LogUtil.BUGLE_TAG, "Error getting content size", e);
+            } finally {
+                if (pfd != null) {
+                    try {
+                        pfd.close();
+                    } catch (final IOException e) {
+                        // Do nothing.
+                    }
+                }
+            }
+        } else {
+            Assert.fail("Unsupported uri type!");
+        }
+        return 0;
+    }
+
+    /** @return duration in milliseconds or 0 if not able to determine */
+    public static int getMediaDurationMs(final Uri uri) {
+        final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
+        try {
+            retriever.setDataSource(uri);
+            return retriever.extractInteger(MediaMetadataRetriever.METADATA_KEY_DURATION, 0);
+        } catch (final IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Unable extract duration from media file: " + uri, e);
+            return 0;
+        } finally {
+            retriever.release();
+        }
+    }
+
+    /**
+     * Persist a piece of content from the given input stream, byte by byte to the scratch
+     * directory.
+     * @return the output Uri if the operation succeeded, or null if failed.
+     */
+    @DoesNotRunOnMainThread
+    public static Uri persistContentToScratchSpace(final InputStream inputStream) {
+        final Context context = Factory.get().getApplicationContext();
+        final Uri scratchSpaceUri = MediaScratchFileProvider.buildMediaScratchSpaceUri(null);
+        return copyContent(context, inputStream, scratchSpaceUri);
+    }
+
+    /**
+     * Persist a piece of content from the given sourceUri, byte by byte to the scratch
+     * directory.
+     * @return the output Uri if the operation succeeded, or null if failed.
+     */
+    @DoesNotRunOnMainThread
+    public static Uri persistContentToScratchSpace(final Uri sourceUri) {
+        InputStream inputStream = null;
+        final Context context = Factory.get().getApplicationContext();
+        try {
+            if (UriUtil.isLocalResourceUri(sourceUri)) {
+                inputStream = context.getContentResolver().openInputStream(sourceUri);
+            } else {
+                // The content is remote. Download it.
+                inputStream = getInputStreamFromRemoteUri(sourceUri);
+                if (inputStream == null) {
+                    return null;
+                }
+            }
+            return persistContentToScratchSpace(inputStream);
+        } catch (final Exception ex) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error while retrieving media ", ex);
+            return null;
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (final IOException e) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "error trying to close the inputStream", e);
+                }
+            }
+        }
+    }
+
+    @DoesNotRunOnMainThread
+    private static InputStream getInputStreamFromRemoteUri(final Uri sourceUri)
+            throws IOException {
+        if (isRemoteUri(sourceUri)) {
+            final URL url = new URL(sourceUri.toString());
+            final URLConnection ucon = url.openConnection();
+            return new BufferedInputStream(ucon.getInputStream());
+        } else {
+            return null;
+        }
+    }
+
+    private static boolean isRemoteUri(final Uri sourceUri) {
+        return sourceUri.getScheme().equals(SCHEME_HTTP)
+            || sourceUri.getScheme().equals(SCHEME_HTTPS);
+    }
+
+    /**
+     * Persist a piece of content from the given input stream, byte by byte to the specified
+     * directory.
+     * @return the output Uri if the operation succeeded, or null if failed.
+     */
+    @DoesNotRunOnMainThread
+    public static Uri persistContent(
+            final InputStream inputStream, final File outputDir, final String contentType) {
+        if (!outputDir.exists() && !outputDir.mkdirs()) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error creating " + outputDir.getAbsolutePath());
+            return null;
+        }
+
+        final Context context = Factory.get().getApplicationContext();
+        try {
+            final Uri targetUri = Uri.fromFile(FileUtil.getNewFile(outputDir, contentType));
+            return copyContent(context, inputStream, targetUri);
+        } catch (final IOException e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error creating file in " + outputDir.getAbsolutePath());
+            return null;
+        }
+    }
+
+    /**
+     * Persist a piece of content from the given sourceUri, byte by byte to the
+     * specified output directory.
+     * @return the output Uri if the operation succeeded, or null if failed.
+     */
+    @DoesNotRunOnMainThread
+    public static Uri persistContent(
+            final Uri sourceUri, final File outputDir, final String contentType) {
+        InputStream inputStream = null;
+        final Context context = Factory.get().getApplicationContext();
+        try {
+            if (UriUtil.isLocalResourceUri(sourceUri)) {
+                inputStream = context.getContentResolver().openInputStream(sourceUri);
+            } else {
+                // The content is remote. Download it.
+                inputStream = getInputStreamFromRemoteUri(sourceUri);
+                if (inputStream == null) {
+                    return null;
+                }
+            }
+            return persistContent(inputStream, outputDir, contentType);
+        } catch (final Exception ex) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error while retrieving media ", ex);
+            return null;
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (final IOException e) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "error trying to close the inputStream", e);
+                }
+            }
+        }
+    }
+
+    /** @return uri of target file, or null on error */
+    @DoesNotRunOnMainThread
+    private static Uri copyContent(
+            final Context context, final InputStream inputStream, final Uri targetUri) {
+        Assert.isNotMainThread();
+        OutputStream outputStream = null;
+        try {
+            outputStream = context.getContentResolver().openOutputStream(targetUri);
+            ByteStreams.copy(inputStream, outputStream);
+        } catch (final Exception ex) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Error while copying content ", ex);
+            return null;
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.flush();
+                } catch (final IOException e) {
+                    LogUtil.e(LogUtil.BUGLE_TAG, "error trying to flush the outputStream", e);
+                    return null;
+                } finally {
+                    try {
+                        outputStream.close();
+                    } catch (final IOException e) {
+                        // Do nothing.
+                    }
+                }
+            }
+        }
+        return targetUri;
+    }
+
+    public static boolean isSmsMmsUri(final Uri uri) {
+        return uri != null && SMS_MMS_SCHEMES.contains(uri.getScheme());
+    }
+
+    /**
+     * Extract recipient destinations from Uri of form SCHEME:destination[,destination]?otherstuff
+     * where SCHEME is one of the supported sms/mms schemes.
+     *
+     * @param uri sms/mms uri
+     * @return a comma-separated list of recipient destinations or null.
+     */
+    public static String parseRecipientsFromSmsMmsUri(final Uri uri) {
+        if (!isSmsMmsUri(uri)) {
+            return null;
+        }
+        final String[] parts = uri.getSchemeSpecificPart().split("\\?");
+        if (TextUtils.isEmpty(parts[0])) {
+            return null;
+        }
+        // replaceUnicodeDigits will replace digits typed in other languages (i.e. Egyptian) with
+        // the usual ascii equivalents.
+        return TextUtil.replaceUnicodeDigits(parts[0]).replace(';', ',');
+    }
+
+    /**
+     * Return the length of the file to which contentUri refers
+     *
+     * @param contentUri URI for the file of which we want the length
+     * @return Length of the file or AssetFileDescriptor.UNKNOWN_LENGTH
+     */
+    public static long getUriContentLength(final Uri contentUri) {
+        final Context context = Factory.get().getApplicationContext();
+        AssetFileDescriptor afd = null;
+        try {
+            afd = context.getContentResolver().openAssetFileDescriptor(contentUri, "r");
+            return afd.getLength();
+        } catch (final FileNotFoundException e) {
+            LogUtil.w(LogUtil.BUGLE_TAG, "Failed to query length of " + contentUri);
+        } finally {
+            if (afd != null) {
+                try {
+                    afd.close();
+                } catch (final IOException e) {
+                    LogUtil.w(LogUtil.BUGLE_TAG, "Failed to close afd for " + contentUri);
+                }
+            }
+        }
+        return AssetFileDescriptor.UNKNOWN_LENGTH;
+    }
+
+    /** @return string representation of URI or null if URI was null */
+    public static String stringFromUri(final Uri uri) {
+        return uri == null ? null : uri.toString();
+    }
+
+    /** @return URI created from string or null if string was null or empty */
+    public static Uri uriFromString(final String uriString) {
+        return TextUtils.isEmpty(uriString) ? null : Uri.parse(uriString);
+     }
+}
diff --git a/src/com/android/messaging/util/VersionUtil.java b/src/com/android/messaging/util/VersionUtil.java
new file mode 100644
index 0000000..b87aa55
--- /dev/null
+++ b/src/com/android/messaging/util/VersionUtil.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+import java.util.Locale;
+
+public final class VersionUtil {
+    private static final Object sLock = new Object();
+    private static VersionUtil sInstance;
+    private final String mSimpleVersionName;
+    private final int mVersionCode;
+
+    public static VersionUtil getInstance(final Context context) {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                sInstance = new VersionUtil(context);
+            }
+        }
+        return sInstance;
+    }
+
+    private VersionUtil(final Context context) {
+        int versionCode;
+        try {
+            PackageInfo pi = context.getPackageManager().getPackageInfo(
+                    context.getPackageName(), 0);
+            versionCode = pi.versionCode;
+        } catch (final NameNotFoundException exception) {
+            Assert.fail("couldn't get package info " + exception);
+            versionCode = -1;
+        }
+        mVersionCode = versionCode;
+        final int majorBuildNumber = versionCode / 1000;
+        // Use US locale to format version number so that other language characters don't
+        // show up in version string.
+        mSimpleVersionName = String.format(Locale.US, "%d.%d.%03d",
+                majorBuildNumber / 10000,
+                (majorBuildNumber / 1000) % 10,
+                majorBuildNumber % 1000);
+    }
+
+    public int getVersionCode() {
+        return mVersionCode;
+    }
+
+    public String getSimpleName() {
+        return mSimpleVersionName;
+    }
+}
diff --git a/src/com/android/messaging/util/WakeLockHelper.java b/src/com/android/messaging/util/WakeLockHelper.java
new file mode 100644
index 0000000..c9a9152
--- /dev/null
+++ b/src/com/android/messaging/util/WakeLockHelper.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Debug;
+import android.os.PowerManager;
+import android.os.Process;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Helper class used to manage wakelock state
+ */
+public class WakeLockHelper {
+    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
+    private static final boolean VERBOSE = false;
+
+    @VisibleForTesting
+    public static final String EXTRA_CALLING_PID = "pid";
+
+    private final Object mLock = new Object();
+    private final String mWakeLockId;
+    private final int mMyPid;
+
+    private PowerManager.WakeLock mWakeLock;
+
+    public WakeLockHelper(final String wakeLockId) {
+        mWakeLockId = wakeLockId;
+        mMyPid = Process.myPid();
+    }
+
+    /**
+     * Acquire the wakelock
+     */
+    public void acquire(final Context context, final Intent intent, final int opcode) {
+        synchronized (mLock) {
+            if (mWakeLock == null) {
+                if (VERBOSE) {
+                    LogUtil.v(TAG, "initializing wakelock");
+                }
+                final PowerManager pm = (PowerManager)
+                        context.getSystemService(Context.POWER_SERVICE);
+                mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mWakeLockId);
+            }
+        }
+        if (VERBOSE) {
+            LogUtil.v(TAG, "acquiring " + mWakeLockId + " for opcode " + opcode);
+        }
+        mWakeLock.acquire();
+        intent.putExtra(EXTRA_CALLING_PID, mMyPid);
+    }
+
+    /**
+     * Check if wakelock held by this process
+     */
+    public boolean isHeld(final Intent intent) {
+        final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1));
+        return (respectWakeLock && mWakeLock.isHeld());
+    }
+
+    /**
+     * Ensure that wakelock is held by this process
+     */
+    public boolean ensure(final Intent intent, final int opcode) {
+        final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1));
+        if (VERBOSE) {
+            LogUtil.v(TAG, "WakeLockHelper.ensure Intent " + intent + " "
+                    + intent.getAction() + " opcode: " + opcode
+                    + " respectWakeLock " + respectWakeLock);
+        }
+
+        if (respectWakeLock) {
+            final boolean isHeld = (respectWakeLock && isHeld(intent));
+            if (!isHeld) {
+                LogUtil.e(TAG, "WakeLockHelper.ensure called " + intent + " " + intent.getAction()
+                        + " opcode: " + opcode + " sWakeLock: " + mWakeLock + " isHeld: "
+                        + ((mWakeLock == null) ? "(null)" : mWakeLock.isHeld()));
+                if (!Debug.isDebuggerConnected()) {
+                    Assert.fail("WakeLock dropped prior to service starting");
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Release wakelock (if it is held by this process)
+     */
+    public void release(final Intent intent, final int opcode) {
+        final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1));
+        if (respectWakeLock) {
+            try {
+                mWakeLock.release();
+            } catch (final RuntimeException ex) {
+                LogUtil.e(TAG, "KeepAliveService.onHandleIntent exit crash " + intent + " "
+                        + intent.getAction() + " opcode: " + opcode + " sWakeLock: " + mWakeLock
+                        + " isHeld: " + ((mWakeLock == null) ? "(null)" : mWakeLock.isHeld()));
+                if (!Debug.isDebuggerConnected()) {
+                    Assert.fail("WakeLock no longer held at end of handler");
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/YouTubeUtil.java b/src/com/android/messaging/util/YouTubeUtil.java
new file mode 100644
index 0000000..203a666
--- /dev/null
+++ b/src/com/android/messaging/util/YouTubeUtil.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+public class YouTubeUtil {
+    private static final String YOUTUBE_HOST_1 = "www.youtube.com";
+    private static final String YOUTUBE_HOST_2 = "youtube.com";
+    private static final String YOUTUBE_HOST_3 = "m.youtube.com";
+    private static final String YOUTUBE_HOST_4 = "youtube.googleapis.com";
+    private static final String YOUTUBE_HOST_5 = "youtu.be";
+
+    private static final String YOUTUBE_PATH_1 = "/watch";
+    private static final String YOUTUBE_PATH_2 = "/embed/";
+    private static final String YOUTUBE_PATH_3 = "/v/";
+    private static final String YOUTUBE_PATH_4 = "/apiplayer";
+
+    public static final String YOUTUBE_STATIC_THUMBNAIL_PREFIX = "https://img.youtube.com/vi/";
+    public static final String YOUTUBE_STATIC_THUMBNAIL_END = "/hqdefault.jpg";
+
+    public static String getYoutubePreviewImageLink(String urlString) {
+        // Types of youtube urls:
+        // 1.) http://www.youtube.com/watch?v=VIDEOID
+        // 2.) http://www.youtube.com/embed/VIDEOID
+        // 3.) http://www.youtube.com/v/VIDEOID
+        // 3a.) https://youtube.googleapis.com/v/VIDEOID
+        // 4.) http://www.youtube.com/apiplayer?video_id=VIDEO_ID
+        // 5.) http://youtu.be/VIDEOID
+        if (!urlString.startsWith("http")) {
+            // Apparently the url is not an RFC 2396 compliant uri without the port
+            urlString = "http://" + urlString;
+        }
+        final Uri uri = Uri.parse(urlString);
+        final String host = uri.getHost();
+        if (YOUTUBE_HOST_1.equalsIgnoreCase(host)
+                || YOUTUBE_HOST_2.equalsIgnoreCase(host)
+                || YOUTUBE_HOST_3.equalsIgnoreCase(host)
+                || YOUTUBE_HOST_4.equalsIgnoreCase(host)
+                || YOUTUBE_HOST_5.equalsIgnoreCase(host)) {
+            final String videoId = getYouTubeVideoId(uri);
+            if (!TextUtils.isEmpty(videoId)) {
+                return YOUTUBE_STATIC_THUMBNAIL_PREFIX + videoId + YOUTUBE_STATIC_THUMBNAIL_END;
+            }
+            return null;
+        }
+        return null;
+    }
+
+    private static String getYouTubeVideoId(Uri uri) {
+        final String urlPath = uri.getPath();
+
+        if (TextUtils.isEmpty(urlPath)) {
+            // There is no path so no need to continue.
+            return null;
+        }
+        // Case 1
+        if (urlPath.startsWith(YOUTUBE_PATH_1)) {
+            return uri.getQueryParameter("v");
+        }
+        // Case 2
+        if (urlPath.startsWith(YOUTUBE_PATH_2)) {
+            return getVideoIdFromPath(YOUTUBE_PATH_2, urlPath);
+        }
+        // Case 3
+        if (urlPath.startsWith(YOUTUBE_PATH_3)) {
+            return getVideoIdFromPath(YOUTUBE_PATH_3, urlPath);
+        }
+        // Case 4
+        if (urlPath.startsWith(YOUTUBE_PATH_4)) {
+            return uri.getQueryParameter("video_id");
+        }
+        // Case 5
+        if (YOUTUBE_HOST_5.equalsIgnoreCase(uri.getHost())) {
+            return getVideoIdFromPath("/", urlPath);
+        }
+        return null;
+    }
+
+    private static String getVideoIdFromPath(String prefixSubstring, String urlPath) {
+        return urlPath.substring(prefixSubstring.length());
+    }
+
+}
diff --git a/src/com/android/messaging/util/exif/ByteBufferInputStream.java b/src/com/android/messaging/util/exif/ByteBufferInputStream.java
new file mode 100644
index 0000000..9db92ef
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ByteBufferInputStream.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+class ByteBufferInputStream extends InputStream {
+
+    private final ByteBuffer mBuf;
+
+    public ByteBufferInputStream(ByteBuffer buf) {
+        mBuf = buf;
+    }
+
+    @Override
+    public int read() {
+        if (!mBuf.hasRemaining()) {
+            return -1;
+        }
+        return mBuf.get() & 0xFF;
+    }
+
+    @Override
+    public int read(byte[] bytes, int off, int len) {
+        if (!mBuf.hasRemaining()) {
+            return -1;
+        }
+
+        len = Math.min(len, mBuf.remaining());
+        mBuf.get(bytes, off, len);
+        return len;
+    }
+}
diff --git a/src/com/android/messaging/util/exif/CountedDataInputStream.java b/src/com/android/messaging/util/exif/CountedDataInputStream.java
new file mode 100644
index 0000000..ce766d9
--- /dev/null
+++ b/src/com/android/messaging/util/exif/CountedDataInputStream.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+class CountedDataInputStream extends FilterInputStream {
+
+    private int mCount = 0;
+
+    // allocate a byte buffer for a long value;
+    private final byte mByteArray[] = new byte[8];
+    private final ByteBuffer mByteBuffer = ByteBuffer.wrap(mByteArray);
+
+    protected CountedDataInputStream(InputStream in) {
+        super(in);
+    }
+
+    public int getReadByteCount() {
+        return mCount;
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+        int r = in.read(b);
+        mCount += (r >= 0) ? r : 0;
+        return r;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        int r = in.read(b, off, len);
+        mCount += (r >= 0) ? r : 0;
+        return r;
+    }
+
+    @Override
+    public int read() throws IOException {
+        int r = in.read();
+        mCount += (r >= 0) ? 1 : 0;
+        return r;
+    }
+
+    @Override
+    public long skip(long length) throws IOException {
+        long skip = in.skip(length);
+        mCount += skip;
+        return skip;
+    }
+
+    public void skipOrThrow(long length) throws IOException {
+        if (skip(length) != length) {
+            throw new EOFException();
+        }
+    }
+
+    public void skipTo(long target) throws IOException {
+        long cur = mCount;
+        long diff = target - cur;
+        assert(diff >= 0);
+        skipOrThrow(diff);
+    }
+
+    public void readOrThrow(byte[] b, int off, int len) throws IOException {
+        int r = read(b, off, len);
+        if (r != len) {
+            throw new EOFException();
+        }
+    }
+
+    public void readOrThrow(byte[] b) throws IOException {
+        readOrThrow(b, 0, b.length);
+    }
+
+    public void setByteOrder(ByteOrder order) {
+        mByteBuffer.order(order);
+    }
+
+    public ByteOrder getByteOrder() {
+        return mByteBuffer.order();
+    }
+
+    public short readShort() throws IOException {
+        readOrThrow(mByteArray, 0 , 2);
+        mByteBuffer.rewind();
+        return mByteBuffer.getShort();
+    }
+
+    public int readUnsignedShort() throws IOException {
+        return readShort() & 0xffff;
+    }
+
+    public int readInt() throws IOException {
+        readOrThrow(mByteArray, 0 , 4);
+        mByteBuffer.rewind();
+        return mByteBuffer.getInt();
+    }
+
+    public long readUnsignedInt() throws IOException {
+        return readInt() & 0xffffffffL;
+    }
+
+    public long readLong() throws IOException {
+        readOrThrow(mByteArray, 0 , 8);
+        mByteBuffer.rewind();
+        return mByteBuffer.getLong();
+    }
+
+    public String readString(int n) throws IOException {
+        byte buf[] = new byte[n];
+        readOrThrow(buf);
+        return new String(buf, "UTF8");
+    }
+
+    public String readString(int n, Charset charset) throws IOException {
+        byte buf[] = new byte[n];
+        readOrThrow(buf);
+        return new String(buf, charset);
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifData.java b/src/com/android/messaging/util/exif/ExifData.java
new file mode 100644
index 0000000..77ba4e9
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifData.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.util.Log;
+import com.android.messaging.util.LogUtil;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class stores the EXIF header in IFDs according to the JPEG
+ * specification. It is the result produced by {@link ExifReader}.
+ *
+ * @see ExifReader
+ * @see IfdData
+ */
+class ExifData {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final byte[] USER_COMMENT_ASCII = {
+            0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00
+    };
+    private static final byte[] USER_COMMENT_JIS = {
+            0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+    private static final byte[] USER_COMMENT_UNICODE = {
+            0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00
+    };
+
+    private final IfdData[] mIfdDatas = new IfdData[IfdId.TYPE_IFD_COUNT];
+    private byte[] mThumbnail;
+    private final ArrayList<byte[]> mStripBytes = new ArrayList<byte[]>();
+    private final ByteOrder mByteOrder;
+
+    ExifData(ByteOrder order) {
+        mByteOrder = order;
+    }
+
+    /**
+     * Gets the compressed thumbnail. Returns null if there is no compressed
+     * thumbnail.
+     *
+     * @see #hasCompressedThumbnail()
+     */
+    protected byte[] getCompressedThumbnail() {
+        return mThumbnail;
+    }
+
+    /**
+     * Sets the compressed thumbnail.
+     */
+    protected void setCompressedThumbnail(byte[] thumbnail) {
+        mThumbnail = thumbnail;
+    }
+
+    /**
+     * Returns true it this header contains a compressed thumbnail.
+     */
+    protected boolean hasCompressedThumbnail() {
+        return mThumbnail != null;
+    }
+
+    /**
+     * Adds an uncompressed strip.
+     */
+    protected void setStripBytes(int index, byte[] strip) {
+        if (index < mStripBytes.size()) {
+            mStripBytes.set(index, strip);
+        } else {
+            for (int i = mStripBytes.size(); i < index; i++) {
+                mStripBytes.add(null);
+            }
+            mStripBytes.add(strip);
+        }
+    }
+
+    /**
+     * Gets the strip count.
+     */
+    protected int getStripCount() {
+        return mStripBytes.size();
+    }
+
+    /**
+     * Gets the strip at the specified index.
+     *
+     * @exceptions #IndexOutOfBoundException
+     */
+    protected byte[] getStrip(int index) {
+        return mStripBytes.get(index);
+    }
+
+    /**
+     * Returns true if this header contains uncompressed strip.
+     */
+    protected boolean hasUncompressedStrip() {
+        return mStripBytes.size() != 0;
+    }
+
+    /**
+     * Gets the byte order.
+     */
+    protected ByteOrder getByteOrder() {
+        return mByteOrder;
+    }
+
+    /**
+     * Returns the {@link IfdData} object corresponding to a given IFD if it
+     * exists or null.
+     */
+    protected IfdData getIfdData(int ifdId) {
+        if (ExifTag.isValidIfd(ifdId)) {
+            return mIfdDatas[ifdId];
+        }
+        return null;
+    }
+
+    /**
+     * Adds IFD data. If IFD data of the same type already exists, it will be
+     * replaced by the new data.
+     */
+    protected void addIfdData(IfdData data) {
+        mIfdDatas[data.getId()] = data;
+    }
+
+    /**
+     * Returns the {@link IfdData} object corresponding to a given IFD or
+     * generates one if none exist.
+     */
+    protected IfdData getOrCreateIfdData(int ifdId) {
+        IfdData ifdData = mIfdDatas[ifdId];
+        if (ifdData == null) {
+            ifdData = new IfdData(ifdId);
+            mIfdDatas[ifdId] = ifdData;
+        }
+        return ifdData;
+    }
+
+    /**
+     * Returns the tag with a given TID in the given IFD if the tag exists.
+     * Otherwise returns null.
+     */
+    protected ExifTag getTag(short tag, int ifd) {
+        IfdData ifdData = mIfdDatas[ifd];
+        return (ifdData == null) ? null : ifdData.getTag(tag);
+    }
+
+    /**
+     * Adds the given ExifTag to its default IFD and returns an existing ExifTag
+     * with the same TID or null if none exist.
+     */
+    protected ExifTag addTag(ExifTag tag) {
+        if (tag != null) {
+            int ifd = tag.getIfd();
+            return addTag(tag, ifd);
+        }
+        return null;
+    }
+
+    /**
+     * Adds the given ExifTag to the given IFD and returns an existing ExifTag
+     * with the same TID or null if none exist.
+     */
+    protected ExifTag addTag(ExifTag tag, int ifdId) {
+        if (tag != null && ExifTag.isValidIfd(ifdId)) {
+            IfdData ifdData = getOrCreateIfdData(ifdId);
+            return ifdData.setTag(tag);
+        }
+        return null;
+    }
+
+    protected void clearThumbnailAndStrips() {
+        mThumbnail = null;
+        mStripBytes.clear();
+    }
+
+    /**
+     * Removes the thumbnail and its related tags. IFD1 will be removed.
+     */
+    protected void removeThumbnailData() {
+        clearThumbnailAndStrips();
+        mIfdDatas[IfdId.TYPE_IFD_1] = null;
+    }
+
+    /**
+     * Removes the tag with a given TID and IFD.
+     */
+    protected void removeTag(short tagId, int ifdId) {
+        IfdData ifdData = mIfdDatas[ifdId];
+        if (ifdData == null) {
+            return;
+        }
+        ifdData.removeTag(tagId);
+    }
+
+    /**
+     * Decodes the user comment tag into string as specified in the EXIF
+     * standard. Returns null if decoding failed.
+     */
+    protected String getUserComment() {
+        IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_0];
+        if (ifdData == null) {
+            return null;
+        }
+        ExifTag tag = ifdData.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT));
+        if (tag == null) {
+            return null;
+        }
+        if (tag.getComponentCount() < 8) {
+            return null;
+        }
+
+        byte[] buf = new byte[tag.getComponentCount()];
+        tag.getBytes(buf);
+
+        byte[] code = new byte[8];
+        System.arraycopy(buf, 0, code, 0, 8);
+
+        try {
+            if (Arrays.equals(code, USER_COMMENT_ASCII)) {
+                return new String(buf, 8, buf.length - 8, "US-ASCII");
+            } else if (Arrays.equals(code, USER_COMMENT_JIS)) {
+                return new String(buf, 8, buf.length - 8, "EUC-JP");
+            } else if (Arrays.equals(code, USER_COMMENT_UNICODE)) {
+                return new String(buf, 8, buf.length - 8, "UTF-16");
+            } else {
+                return null;
+            }
+        } catch (UnsupportedEncodingException e) {
+            Log.w(TAG, "Failed to decode the user comment");
+            return null;
+        }
+    }
+
+    /**
+     * Returns a list of all {@link ExifTag}s in the ExifData or null if there
+     * are none.
+     */
+    protected List<ExifTag> getAllTags() {
+        ArrayList<ExifTag> ret = new ArrayList<ExifTag>();
+        for (IfdData d : mIfdDatas) {
+            if (d != null) {
+                ExifTag[] tags = d.getAllTags();
+                if (tags != null) {
+                    for (ExifTag t : tags) {
+                        ret.add(t);
+                    }
+                }
+            }
+        }
+        if (ret.size() == 0) {
+            return null;
+        }
+        return ret;
+    }
+
+    /**
+     * Returns a list of all {@link ExifTag}s in a given IFD or null if there
+     * are none.
+     */
+    protected List<ExifTag> getAllTagsForIfd(int ifd) {
+        IfdData d = mIfdDatas[ifd];
+        if (d == null) {
+            return null;
+        }
+        ExifTag[] tags = d.getAllTags();
+        if (tags == null) {
+            return null;
+        }
+        ArrayList<ExifTag> ret = new ArrayList<ExifTag>(tags.length);
+        for (ExifTag t : tags) {
+            ret.add(t);
+        }
+        if (ret.size() == 0) {
+            return null;
+        }
+        return ret;
+    }
+
+    /**
+     * Returns a list of all {@link ExifTag}s with a given TID or null if there
+     * are none.
+     */
+    protected List<ExifTag> getAllTagsForTagId(short tag) {
+        ArrayList<ExifTag> ret = new ArrayList<ExifTag>();
+        for (IfdData d : mIfdDatas) {
+            if (d != null) {
+                ExifTag t = d.getTag(tag);
+                if (t != null) {
+                    ret.add(t);
+                }
+            }
+        }
+        if (ret.size() == 0) {
+            return null;
+        }
+        return ret;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof ExifData) {
+            ExifData data = (ExifData) obj;
+            if (data.mByteOrder != mByteOrder ||
+                    data.mStripBytes.size() != mStripBytes.size() ||
+                    !Arrays.equals(data.mThumbnail, mThumbnail)) {
+                return false;
+            }
+            for (int i = 0; i < mStripBytes.size(); i++) {
+                if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) {
+                    return false;
+                }
+            }
+            for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
+                IfdData ifd1 = data.getIfdData(i);
+                IfdData ifd2 = getIfdData(i);
+                if (ifd1 != ifd2 && ifd1 != null && !ifd1.equals(ifd2)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/src/com/android/messaging/util/exif/ExifInterface.java b/src/com/android/messaging/util/exif/ExifInterface.java
new file mode 100644
index 0000000..b556748
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifInterface.java
@@ -0,0 +1,2448 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.SparseIntArray;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel.MapMode;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.TimeZone;
+
+/**
+ * This class provides methods and constants for reading and writing jpeg file
+ * metadata. It contains a collection of ExifTags, and a collection of
+ * definitions for creating valid ExifTags. The collection of ExifTags can be
+ * updated by: reading new ones from a file, deleting or adding existing ones,
+ * or building new ExifTags from a tag definition. These ExifTags can be written
+ * to a valid jpeg image as exif metadata.
+ * <p>
+ * Each ExifTag has a tag ID (TID) and is stored in a specific image file
+ * directory (IFD) as specified by the exif standard. A tag definition can be
+ * looked up with a constant that is a combination of TID and IFD. This
+ * definition has information about the type, number of components, and valid
+ * IFDs for a tag.
+ *
+ * @see ExifTag
+ */
+public class ExifInterface {
+    public static final int TAG_NULL = -1;
+    public static final int IFD_NULL = -1;
+    public static final int DEFINITION_NULL = 0;
+
+    /**
+     * Tag constants for Jeita EXIF 2.2
+     */
+
+    // IFD 0
+    public static final int TAG_IMAGE_WIDTH =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0100);
+    public static final int TAG_IMAGE_LENGTH =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0101); // Image height
+    public static final int TAG_BITS_PER_SAMPLE =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0102);
+    public static final int TAG_COMPRESSION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0103);
+    public static final int TAG_PHOTOMETRIC_INTERPRETATION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0106);
+    public static final int TAG_IMAGE_DESCRIPTION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x010E);
+    public static final int TAG_MAKE =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x010F);
+    public static final int TAG_MODEL =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0110);
+    public static final int TAG_STRIP_OFFSETS =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0111);
+    public static final int TAG_ORIENTATION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0112);
+    public static final int TAG_SAMPLES_PER_PIXEL =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0115);
+    public static final int TAG_ROWS_PER_STRIP =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0116);
+    public static final int TAG_STRIP_BYTE_COUNTS =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0117);
+    public static final int TAG_X_RESOLUTION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x011A);
+    public static final int TAG_Y_RESOLUTION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x011B);
+    public static final int TAG_PLANAR_CONFIGURATION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x011C);
+    public static final int TAG_RESOLUTION_UNIT =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0128);
+    public static final int TAG_TRANSFER_FUNCTION =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x012D);
+    public static final int TAG_SOFTWARE =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0131);
+    public static final int TAG_DATE_TIME =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0132);
+    public static final int TAG_ARTIST =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x013B);
+    public static final int TAG_WHITE_POINT =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x013E);
+    public static final int TAG_PRIMARY_CHROMATICITIES =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x013F);
+    public static final int TAG_Y_CB_CR_COEFFICIENTS =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0211);
+    public static final int TAG_Y_CB_CR_SUB_SAMPLING =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0212);
+    public static final int TAG_Y_CB_CR_POSITIONING =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0213);
+    public static final int TAG_REFERENCE_BLACK_WHITE =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x0214);
+    public static final int TAG_COPYRIGHT =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x8298);
+    public static final int TAG_EXIF_IFD =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x8769);
+    public static final int TAG_GPS_IFD =
+        defineTag(IfdId.TYPE_IFD_0, (short) 0x8825);
+    // IFD 1
+    public static final int TAG_JPEG_INTERCHANGE_FORMAT =
+        defineTag(IfdId.TYPE_IFD_1, (short) 0x0201);
+    public static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH =
+        defineTag(IfdId.TYPE_IFD_1, (short) 0x0202);
+    // IFD Exif Tags
+    public static final int TAG_EXPOSURE_TIME =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829A);
+    public static final int TAG_F_NUMBER =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829D);
+    public static final int TAG_EXPOSURE_PROGRAM =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8822);
+    public static final int TAG_SPECTRAL_SENSITIVITY =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8824);
+    public static final int TAG_ISO_SPEED_RATINGS =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8827);
+    public static final int TAG_OECF =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8828);
+    public static final int TAG_EXIF_VERSION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9000);
+    public static final int TAG_DATE_TIME_ORIGINAL =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9003);
+    public static final int TAG_DATE_TIME_DIGITIZED =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9004);
+    public static final int TAG_COMPONENTS_CONFIGURATION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9101);
+    public static final int TAG_COMPRESSED_BITS_PER_PIXEL =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9102);
+    public static final int TAG_SHUTTER_SPEED_VALUE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9201);
+    public static final int TAG_APERTURE_VALUE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9202);
+    public static final int TAG_BRIGHTNESS_VALUE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9203);
+    public static final int TAG_EXPOSURE_BIAS_VALUE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9204);
+    public static final int TAG_MAX_APERTURE_VALUE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9205);
+    public static final int TAG_SUBJECT_DISTANCE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9206);
+    public static final int TAG_METERING_MODE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9207);
+    public static final int TAG_LIGHT_SOURCE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9208);
+    public static final int TAG_FLASH =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9209);
+    public static final int TAG_FOCAL_LENGTH =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x920A);
+    public static final int TAG_SUBJECT_AREA =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9214);
+    public static final int TAG_MAKER_NOTE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x927C);
+    public static final int TAG_USER_COMMENT =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9286);
+    public static final int TAG_SUB_SEC_TIME =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9290);
+    public static final int TAG_SUB_SEC_TIME_ORIGINAL =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9291);
+    public static final int TAG_SUB_SEC_TIME_DIGITIZED =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9292);
+    public static final int TAG_FLASHPIX_VERSION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA000);
+    public static final int TAG_COLOR_SPACE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA001);
+    public static final int TAG_PIXEL_X_DIMENSION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA002);
+    public static final int TAG_PIXEL_Y_DIMENSION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA003);
+    public static final int TAG_RELATED_SOUND_FILE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA004);
+    public static final int TAG_INTEROPERABILITY_IFD =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA005);
+    public static final int TAG_FLASH_ENERGY =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20B);
+    public static final int TAG_SPATIAL_FREQUENCY_RESPONSE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20C);
+    public static final int TAG_FOCAL_PLANE_X_RESOLUTION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20E);
+    public static final int TAG_FOCAL_PLANE_Y_RESOLUTION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20F);
+    public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA210);
+    public static final int TAG_SUBJECT_LOCATION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA214);
+    public static final int TAG_EXPOSURE_INDEX =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA215);
+    public static final int TAG_SENSING_METHOD =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA217);
+    public static final int TAG_FILE_SOURCE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA300);
+    public static final int TAG_SCENE_TYPE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA301);
+    public static final int TAG_CFA_PATTERN =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA302);
+    public static final int TAG_CUSTOM_RENDERED =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA401);
+    public static final int TAG_EXPOSURE_MODE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA402);
+    public static final int TAG_WHITE_BALANCE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA403);
+    public static final int TAG_DIGITAL_ZOOM_RATIO =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA404);
+    public static final int TAG_FOCAL_LENGTH_IN_35_MM_FILE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA405);
+    public static final int TAG_SCENE_CAPTURE_TYPE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA406);
+    public static final int TAG_GAIN_CONTROL =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA407);
+    public static final int TAG_CONTRAST =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA408);
+    public static final int TAG_SATURATION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA409);
+    public static final int TAG_SHARPNESS =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40A);
+    public static final int TAG_DEVICE_SETTING_DESCRIPTION =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40B);
+    public static final int TAG_SUBJECT_DISTANCE_RANGE =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40C);
+    public static final int TAG_IMAGE_UNIQUE_ID =
+        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA420);
+    // IFD GPS tags
+    public static final int TAG_GPS_VERSION_ID =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 0);
+    public static final int TAG_GPS_LATITUDE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 1);
+    public static final int TAG_GPS_LATITUDE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 2);
+    public static final int TAG_GPS_LONGITUDE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 3);
+    public static final int TAG_GPS_LONGITUDE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 4);
+    public static final int TAG_GPS_ALTITUDE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 5);
+    public static final int TAG_GPS_ALTITUDE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 6);
+    public static final int TAG_GPS_TIME_STAMP =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 7);
+    public static final int TAG_GPS_SATTELLITES =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 8);
+    public static final int TAG_GPS_STATUS =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 9);
+    public static final int TAG_GPS_MEASURE_MODE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 10);
+    public static final int TAG_GPS_DOP =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 11);
+    public static final int TAG_GPS_SPEED_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 12);
+    public static final int TAG_GPS_SPEED =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 13);
+    public static final int TAG_GPS_TRACK_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 14);
+    public static final int TAG_GPS_TRACK =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 15);
+    public static final int TAG_GPS_IMG_DIRECTION_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 16);
+    public static final int TAG_GPS_IMG_DIRECTION =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 17);
+    public static final int TAG_GPS_MAP_DATUM =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 18);
+    public static final int TAG_GPS_DEST_LATITUDE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 19);
+    public static final int TAG_GPS_DEST_LATITUDE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 20);
+    public static final int TAG_GPS_DEST_LONGITUDE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 21);
+    public static final int TAG_GPS_DEST_LONGITUDE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 22);
+    public static final int TAG_GPS_DEST_BEARING_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 23);
+    public static final int TAG_GPS_DEST_BEARING =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 24);
+    public static final int TAG_GPS_DEST_DISTANCE_REF =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 25);
+    public static final int TAG_GPS_DEST_DISTANCE =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 26);
+    public static final int TAG_GPS_PROCESSING_METHOD =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 27);
+    public static final int TAG_GPS_AREA_INFORMATION =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 28);
+    public static final int TAG_GPS_DATE_STAMP =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 29);
+    public static final int TAG_GPS_DIFFERENTIAL =
+        defineTag(IfdId.TYPE_IFD_GPS, (short) 30);
+    // IFD Interoperability tags
+    public static final int TAG_INTEROPERABILITY_INDEX =
+        defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 1);
+
+    /**
+     * Tags that contain offset markers. These are included in the banned
+     * defines.
+     */
+    private static HashSet<Short> sOffsetTags = new HashSet<Short>();
+    static {
+        sOffsetTags.add(getTrueTagKey(TAG_GPS_IFD));
+        sOffsetTags.add(getTrueTagKey(TAG_EXIF_IFD));
+        sOffsetTags.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT));
+        sOffsetTags.add(getTrueTagKey(TAG_INTEROPERABILITY_IFD));
+        sOffsetTags.add(getTrueTagKey(TAG_STRIP_OFFSETS));
+    }
+
+    /**
+     * Tags with definitions that cannot be overridden (banned defines).
+     */
+    protected static HashSet<Short> sBannedDefines = new HashSet<Short>(sOffsetTags);
+    static {
+        sBannedDefines.add(getTrueTagKey(TAG_NULL));
+        sBannedDefines.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH));
+        sBannedDefines.add(getTrueTagKey(TAG_STRIP_BYTE_COUNTS));
+    }
+
+    /**
+     * Returns the constant representing a tag with a given TID and default IFD.
+     */
+    public static int defineTag(int ifdId, short tagId) {
+        return (tagId & 0x0000ffff) | (ifdId << 16);
+    }
+
+    /**
+     * Returns the TID for a tag constant.
+     */
+    public static short getTrueTagKey(int tag) {
+        // Truncate
+        return (short) tag;
+    }
+
+    /**
+     * Returns the default IFD for a tag constant.
+     */
+    public static int getTrueIfd(int tag) {
+        return tag >>> 16;
+    }
+
+    /**
+     * Constants for {@link TAG_ORIENTATION}. They can be interpreted as
+     * follows:
+     * <ul>
+     * <li>TOP_LEFT is the normal orientation.</li>
+     * <li>TOP_RIGHT is a left-right mirror.</li>
+     * <li>BOTTOM_LEFT is a 180 degree rotation.</li>
+     * <li>BOTTOM_RIGHT is a top-bottom mirror.</li>
+     * <li>LEFT_TOP is mirrored about the top-left<->bottom-right axis.</li>
+     * <li>RIGHT_TOP is a 90 degree clockwise rotation.</li>
+     * <li>LEFT_BOTTOM is mirrored about the top-right<->bottom-left axis.</li>
+     * <li>RIGHT_BOTTOM is a 270 degree clockwise rotation.</li>
+     * </ul>
+     */
+    public static interface Orientation {
+        public static final short TOP_LEFT = 1;
+        public static final short TOP_RIGHT = 2;
+        public static final short BOTTOM_LEFT = 3;
+        public static final short BOTTOM_RIGHT = 4;
+        public static final short LEFT_TOP = 5;
+        public static final short RIGHT_TOP = 6;
+        public static final short LEFT_BOTTOM = 7;
+        public static final short RIGHT_BOTTOM = 8;
+    }
+
+    /**
+     * Constants for {@link TAG_Y_CB_CR_POSITIONING}
+     */
+    public static interface YCbCrPositioning {
+        public static final short CENTERED = 1;
+        public static final short CO_SITED = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_COMPRESSION}
+     */
+    public static interface Compression {
+        public static final short UNCOMPRESSION = 1;
+        public static final short JPEG = 6;
+    }
+
+    /**
+     * Constants for {@link TAG_RESOLUTION_UNIT}
+     */
+    public static interface ResolutionUnit {
+        public static final short INCHES = 2;
+        public static final short CENTIMETERS = 3;
+    }
+
+    /**
+     * Constants for {@link TAG_PHOTOMETRIC_INTERPRETATION}
+     */
+    public static interface PhotometricInterpretation {
+        public static final short RGB = 2;
+        public static final short YCBCR = 6;
+    }
+
+    /**
+     * Constants for {@link TAG_PLANAR_CONFIGURATION}
+     */
+    public static interface PlanarConfiguration {
+        public static final short CHUNKY = 1;
+        public static final short PLANAR = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_EXPOSURE_PROGRAM}
+     */
+    public static interface ExposureProgram {
+        public static final short NOT_DEFINED = 0;
+        public static final short MANUAL = 1;
+        public static final short NORMAL_PROGRAM = 2;
+        public static final short APERTURE_PRIORITY = 3;
+        public static final short SHUTTER_PRIORITY = 4;
+        public static final short CREATIVE_PROGRAM = 5;
+        public static final short ACTION_PROGRAM = 6;
+        public static final short PROTRAIT_MODE = 7;
+        public static final short LANDSCAPE_MODE = 8;
+    }
+
+    /**
+     * Constants for {@link TAG_METERING_MODE}
+     */
+    public static interface MeteringMode {
+        public static final short UNKNOWN = 0;
+        public static final short AVERAGE = 1;
+        public static final short CENTER_WEIGHTED_AVERAGE = 2;
+        public static final short SPOT = 3;
+        public static final short MULTISPOT = 4;
+        public static final short PATTERN = 5;
+        public static final short PARTAIL = 6;
+        public static final short OTHER = 255;
+    }
+
+    /**
+     * Constants for {@link TAG_FLASH} As the definition in Jeita EXIF 2.2
+     * standard, we can treat this constant as bitwise flag.
+     * <p>
+     * e.g.
+     * <p>
+     * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED |
+     * MODE_AUTO_MODE
+     */
+    public static interface Flash {
+        // LSB
+        public static final short DID_NOT_FIRED = 0;
+        public static final short FIRED = 1;
+        // 1st~2nd bits
+        public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1;
+        public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1;
+        public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1;
+        // 3rd~4th bits
+        public static final short MODE_UNKNOWN = 0 << 3;
+        public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3;
+        public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3;
+        public static final short MODE_AUTO_MODE = 3 << 3;
+        // 5th bit
+        public static final short FUNCTION_PRESENT = 0 << 5;
+        public static final short FUNCTION_NO_FUNCTION = 1 << 5;
+        // 6th bit
+        public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
+        public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
+    }
+
+    /**
+     * Constants for {@link TAG_COLOR_SPACE}
+     */
+    public static interface ColorSpace {
+        public static final short SRGB = 1;
+        public static final short UNCALIBRATED = (short) 0xFFFF;
+    }
+
+    /**
+     * Constants for {@link TAG_EXPOSURE_MODE}
+     */
+    public static interface ExposureMode {
+        public static final short AUTO_EXPOSURE = 0;
+        public static final short MANUAL_EXPOSURE = 1;
+        public static final short AUTO_BRACKET = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_WHITE_BALANCE}
+     */
+    public static interface WhiteBalance {
+        public static final short AUTO = 0;
+        public static final short MANUAL = 1;
+    }
+
+    /**
+     * Constants for {@link TAG_SCENE_CAPTURE_TYPE}
+     */
+    public static interface SceneCapture {
+        public static final short STANDARD = 0;
+        public static final short LANDSCAPE = 1;
+        public static final short PROTRAIT = 2;
+        public static final short NIGHT_SCENE = 3;
+    }
+
+    /**
+     * Constants for {@link TAG_COMPONENTS_CONFIGURATION}
+     */
+    public static interface ComponentsConfiguration {
+        public static final short NOT_EXIST = 0;
+        public static final short Y = 1;
+        public static final short CB = 2;
+        public static final short CR = 3;
+        public static final short R = 4;
+        public static final short G = 5;
+        public static final short B = 6;
+    }
+
+    /**
+     * Constants for {@link TAG_LIGHT_SOURCE}
+     */
+    public static interface LightSource {
+        public static final short UNKNOWN = 0;
+        public static final short DAYLIGHT = 1;
+        public static final short FLUORESCENT = 2;
+        public static final short TUNGSTEN = 3;
+        public static final short FLASH = 4;
+        public static final short FINE_WEATHER = 9;
+        public static final short CLOUDY_WEATHER = 10;
+        public static final short SHADE = 11;
+        public static final short DAYLIGHT_FLUORESCENT = 12;
+        public static final short DAY_WHITE_FLUORESCENT = 13;
+        public static final short COOL_WHITE_FLUORESCENT = 14;
+        public static final short WHITE_FLUORESCENT = 15;
+        public static final short STANDARD_LIGHT_A = 17;
+        public static final short STANDARD_LIGHT_B = 18;
+        public static final short STANDARD_LIGHT_C = 19;
+        public static final short D55 = 20;
+        public static final short D65 = 21;
+        public static final short D75 = 22;
+        public static final short D50 = 23;
+        public static final short ISO_STUDIO_TUNGSTEN = 24;
+        public static final short OTHER = 255;
+    }
+
+    /**
+     * Constants for {@link TAG_SENSING_METHOD}
+     */
+    public static interface SensingMethod {
+        public static final short NOT_DEFINED = 1;
+        public static final short ONE_CHIP_COLOR = 2;
+        public static final short TWO_CHIP_COLOR = 3;
+        public static final short THREE_CHIP_COLOR = 4;
+        public static final short COLOR_SEQUENTIAL_AREA = 5;
+        public static final short TRILINEAR = 7;
+        public static final short COLOR_SEQUENTIAL_LINEAR = 8;
+    }
+
+    /**
+     * Constants for {@link TAG_FILE_SOURCE}
+     */
+    public static interface FileSource {
+        public static final short DSC = 3;
+    }
+
+    /**
+     * Constants for {@link TAG_SCENE_TYPE}
+     */
+    public static interface SceneType {
+        public static final short DIRECT_PHOTOGRAPHED = 1;
+    }
+
+    /**
+     * Constants for {@link TAG_GAIN_CONTROL}
+     */
+    public static interface GainControl {
+        public static final short NONE = 0;
+        public static final short LOW_UP = 1;
+        public static final short HIGH_UP = 2;
+        public static final short LOW_DOWN = 3;
+        public static final short HIGH_DOWN = 4;
+    }
+
+    /**
+     * Constants for {@link TAG_CONTRAST}
+     */
+    public static interface Contrast {
+        public static final short NORMAL = 0;
+        public static final short SOFT = 1;
+        public static final short HARD = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_SATURATION}
+     */
+    public static interface Saturation {
+        public static final short NORMAL = 0;
+        public static final short LOW = 1;
+        public static final short HIGH = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_SHARPNESS}
+     */
+    public static interface Sharpness {
+        public static final short NORMAL = 0;
+        public static final short SOFT = 1;
+        public static final short HARD = 2;
+    }
+
+    /**
+     * Constants for {@link TAG_SUBJECT_DISTANCE}
+     */
+    public static interface SubjectDistance {
+        public static final short UNKNOWN = 0;
+        public static final short MACRO = 1;
+        public static final short CLOSE_VIEW = 2;
+        public static final short DISTANT_VIEW = 3;
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_LATITUDE_REF},
+     * {@link TAG_GPS_DEST_LATITUDE_REF}
+     */
+    public static interface GpsLatitudeRef {
+        public static final String NORTH = "N";
+        public static final String SOUTH = "S";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_LONGITUDE_REF},
+     * {@link TAG_GPS_DEST_LONGITUDE_REF}
+     */
+    public static interface GpsLongitudeRef {
+        public static final String EAST = "E";
+        public static final String WEST = "W";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_ALTITUDE_REF}
+     */
+    public static interface GpsAltitudeRef {
+        public static final short SEA_LEVEL = 0;
+        public static final short SEA_LEVEL_NEGATIVE = 1;
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_STATUS}
+     */
+    public static interface GpsStatus {
+        public static final String IN_PROGRESS = "A";
+        public static final String INTEROPERABILITY = "V";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_MEASURE_MODE}
+     */
+    public static interface GpsMeasureMode {
+        public static final String MODE_2_DIMENSIONAL = "2";
+        public static final String MODE_3_DIMENSIONAL = "3";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_SPEED_REF},
+     * {@link TAG_GPS_DEST_DISTANCE_REF}
+     */
+    public static interface GpsSpeedRef {
+        public static final String KILOMETERS = "K";
+        public static final String MILES = "M";
+        public static final String KNOTS = "N";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_TRACK_REF},
+     * {@link TAG_GPS_IMG_DIRECTION_REF}, {@link TAG_GPS_DEST_BEARING_REF}
+     */
+    public static interface GpsTrackRef {
+        public static final String TRUE_DIRECTION = "T";
+        public static final String MAGNETIC_DIRECTION = "M";
+    }
+
+    /**
+     * Constants for {@link TAG_GPS_DIFFERENTIAL}
+     */
+    public static interface GpsDifferential {
+        public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
+        public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
+    }
+
+    private static final String NULL_ARGUMENT_STRING = "Argument is null";
+    private ExifData mData = new ExifData(DEFAULT_BYTE_ORDER);
+    public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN;
+
+    public ExifInterface() {
+        mGPSDateStampFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+    }
+
+    /**
+     * Reads the exif tags from a byte array, clearing this ExifInterface
+     * object's existing exif tags.
+     *
+     * @param jpeg a byte array containing a jpeg compressed image.
+     * @throws java.io.IOException
+     */
+    public void readExif(byte[] jpeg) throws IOException {
+        readExif(new ByteArrayInputStream(jpeg));
+    }
+
+    /**
+     * Reads the exif tags from an InputStream, clearing this ExifInterface
+     * object's existing exif tags.
+     *
+     * @param inStream an InputStream containing a jpeg compressed image.
+     * @throws java.io.IOException
+     */
+    public void readExif(InputStream inStream) throws IOException {
+        if (inStream == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        ExifData d = null;
+        try {
+            d = new ExifReader(this).read(inStream);
+        } catch (ExifInvalidFormatException e) {
+            throw new IOException("Invalid exif format : " + e);
+        }
+        mData = d;
+    }
+
+    /**
+     * Reads the exif tags from a file, clearing this ExifInterface object's
+     * existing exif tags.
+     *
+     * @param inFileName a string representing the filepath to jpeg file.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public void readExif(String inFileName) throws FileNotFoundException, IOException {
+        if (inFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        InputStream is = null;
+        try {
+            is = new BufferedInputStream(new FileInputStream(inFileName));
+            readExif(is);
+        } catch (IOException e) {
+            closeSilently(is);
+            throw e;
+        }
+        is.close();
+    }
+
+    /**
+     * Sets the exif tags, clearing this ExifInterface object's existing exif
+     * tags.
+     *
+     * @param tags a collection of exif tags to set.
+     */
+    public void setExif(Collection<ExifTag> tags) {
+        clearExif();
+        setTags(tags);
+    }
+
+    /**
+     * Clears this ExifInterface object's existing exif tags.
+     */
+    public void clearExif() {
+        mData = new ExifData(DEFAULT_BYTE_ORDER);
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg image,
+     * removing prior exif tags.
+     *
+     * @param jpeg a byte array containing a jpeg compressed image.
+     * @param exifOutStream an OutputStream to which the jpeg image with added
+     *            exif tags will be written.
+     * @throws java.io.IOException
+     */
+    public void writeExif(byte[] jpeg, OutputStream exifOutStream) throws IOException {
+        if (jpeg == null || exifOutStream == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = getExifWriterStream(exifOutStream);
+        s.write(jpeg, 0, jpeg.length);
+        s.flush();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg compressed
+     * bitmap, removing prior exif tags.
+     *
+     * @param bmap a bitmap to compress and write exif into.
+     * @param exifOutStream the OutputStream to which the jpeg image with added
+     *            exif tags will be written.
+     * @throws java.io.IOException
+     */
+    public void writeExif(Bitmap bmap, OutputStream exifOutStream) throws IOException {
+        if (bmap == null || exifOutStream == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = getExifWriterStream(exifOutStream);
+        bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
+        s.flush();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg stream,
+     * removing prior exif tags.
+     *
+     * @param jpegStream an InputStream containing a jpeg compressed image.
+     * @param exifOutStream an OutputStream to which the jpeg image with added
+     *            exif tags will be written.
+     * @throws java.io.IOException
+     */
+    public void writeExif(InputStream jpegStream, OutputStream exifOutStream) throws IOException {
+        if (jpegStream == null || exifOutStream == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = getExifWriterStream(exifOutStream);
+        doExifStreamIO(jpegStream, s);
+        s.flush();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg image,
+     * removing prior exif tags.
+     *
+     * @param jpeg a byte array containing a jpeg compressed image.
+     * @param exifOutFileName a String containing the filepath to which the jpeg
+     *            image with added exif tags will be written.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public void writeExif(byte[] jpeg, String exifOutFileName) throws FileNotFoundException,
+            IOException {
+        if (jpeg == null || exifOutFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = null;
+        try {
+            s = getExifWriterStream(exifOutFileName);
+            s.write(jpeg, 0, jpeg.length);
+            s.flush();
+        } catch (IOException e) {
+            closeSilently(s);
+            throw e;
+        }
+        s.close();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg compressed
+     * bitmap, removing prior exif tags.
+     *
+     * @param bmap a bitmap to compress and write exif into.
+     * @param exifOutFileName a String containing the filepath to which the jpeg
+     *            image with added exif tags will be written.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public void writeExif(Bitmap bmap, String exifOutFileName) throws FileNotFoundException,
+            IOException {
+        if (bmap == null || exifOutFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = null;
+        try {
+            s = getExifWriterStream(exifOutFileName);
+            bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
+            s.flush();
+        } catch (IOException e) {
+            closeSilently(s);
+            throw e;
+        }
+        s.close();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg stream,
+     * removing prior exif tags.
+     *
+     * @param jpegStream an InputStream containing a jpeg compressed image.
+     * @param exifOutFileName a String containing the filepath to which the jpeg
+     *            image with added exif tags will be written.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public void writeExif(InputStream jpegStream, String exifOutFileName)
+            throws FileNotFoundException, IOException {
+        if (jpegStream == null || exifOutFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream s = null;
+        try {
+            s = getExifWriterStream(exifOutFileName);
+            doExifStreamIO(jpegStream, s);
+            s.flush();
+        } catch (IOException e) {
+            closeSilently(s);
+            throw e;
+        }
+        s.close();
+    }
+
+    /**
+     * Writes the tags from this ExifInterface object into a jpeg file, removing
+     * prior exif tags.
+     *
+     * @param jpegFileName a String containing the filepath for a jpeg file.
+     * @param exifOutFileName a String containing the filepath to which the jpeg
+     *            image with added exif tags will be written.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public void writeExif(String jpegFileName, String exifOutFileName)
+            throws FileNotFoundException, IOException {
+        if (jpegFileName == null || exifOutFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        InputStream is = null;
+        try {
+            is = new FileInputStream(jpegFileName);
+            writeExif(is, exifOutFileName);
+        } catch (IOException e) {
+            closeSilently(is);
+            throw e;
+        }
+        is.close();
+    }
+
+    /**
+     * Wraps an OutputStream object with an ExifOutputStream. Exif tags in this
+     * ExifInterface object will be added to a jpeg image written to this
+     * stream, removing prior exif tags. Other methods of this ExifInterface
+     * object should not be called until the returned OutputStream has been
+     * closed.
+     *
+     * @param outStream an OutputStream to wrap.
+     * @return an OutputStream that wraps the outStream parameter, and adds exif
+     *         metadata. A jpeg image should be written to this stream.
+     */
+    public OutputStream getExifWriterStream(OutputStream outStream) {
+        if (outStream == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        ExifOutputStream eos = new ExifOutputStream(outStream, this);
+        eos.setExifData(mData);
+        return eos;
+    }
+
+    /**
+     * Returns an OutputStream object that writes to a file. Exif tags in this
+     * ExifInterface object will be added to a jpeg image written to this
+     * stream, removing prior exif tags. Other methods of this ExifInterface
+     * object should not be called until the returned OutputStream has been
+     * closed.
+     *
+     * @param exifOutFileName an String containing a filepath for a jpeg file.
+     * @return an OutputStream that writes to the exifOutFileName file, and adds
+     *         exif metadata. A jpeg image should be written to this stream.
+     * @throws java.io.FileNotFoundException
+     */
+    public OutputStream getExifWriterStream(String exifOutFileName) throws FileNotFoundException {
+        if (exifOutFileName == null) {
+            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
+        }
+        OutputStream out = null;
+        try {
+            out = new FileOutputStream(exifOutFileName);
+        } catch (FileNotFoundException e) {
+            closeSilently(out);
+            throw e;
+        }
+        return getExifWriterStream(out);
+    }
+
+    /**
+     * Attempts to do an in-place rewrite the exif metadata in a file for the
+     * given tags. If tags do not exist or do not have the same size as the
+     * existing exif tags, this method will fail.
+     *
+     * @param filename a String containing a filepath for a jpeg file with exif
+     *            tags to rewrite.
+     * @param tags tags that will be written into the jpeg file over existing
+     *            tags if possible.
+     * @return true if success, false if could not overwrite. If false, no
+     *         changes are made to the file.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     */
+    public boolean rewriteExif(String filename, Collection<ExifTag> tags)
+            throws FileNotFoundException, IOException {
+        RandomAccessFile file = null;
+        InputStream is = null;
+        boolean ret;
+        try {
+            File temp = new File(filename);
+            is = new BufferedInputStream(new FileInputStream(temp));
+
+            // Parse beginning of APP1 in exif to find size of exif header.
+            ExifParser parser = null;
+            try {
+                parser = ExifParser.parse(is, this);
+            } catch (ExifInvalidFormatException e) {
+                throw new IOException("Invalid exif format : ", e);
+            }
+            long exifSize = parser.getOffsetToExifEndFromSOF();
+
+            // Free up resources
+            is.close();
+            is = null;
+
+            // Open file for memory mapping.
+            file = new RandomAccessFile(temp, "rw");
+            long fileLength = file.length();
+            if (fileLength < exifSize) {
+                throw new IOException("Filesize changed during operation");
+            }
+
+            // Map only exif header into memory.
+            ByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize);
+
+            // Attempt to overwrite tag values without changing lengths (avoids
+            // file copy).
+            ret = rewriteExif(buf, tags);
+        } catch (IOException e) {
+            closeSilently(file);
+            throw e;
+        } finally {
+            closeSilently(is);
+        }
+        file.close();
+        return ret;
+    }
+
+    /**
+     * Attempts to do an in-place rewrite the exif metadata in a ByteBuffer for
+     * the given tags. If tags do not exist or do not have the same size as the
+     * existing exif tags, this method will fail.
+     *
+     * @param buf a ByteBuffer containing a jpeg file with existing exif tags to
+     *            rewrite.
+     * @param tags tags that will be written into the jpeg ByteBuffer over
+     *            existing tags if possible.
+     * @return true if success, false if could not overwrite. If false, no
+     *         changes are made to the ByteBuffer.
+     * @throws java.io.IOException
+     */
+    public boolean rewriteExif(ByteBuffer buf, Collection<ExifTag> tags) throws IOException {
+        ExifModifier mod = null;
+        try {
+            mod = new ExifModifier(buf, this);
+            for (ExifTag t : tags) {
+                mod.modifyTag(t);
+            }
+            return mod.commit();
+        } catch (ExifInvalidFormatException e) {
+            throw new IOException("Invalid exif format : " + e);
+        }
+    }
+
+    /**
+     * Attempts to do an in-place rewrite of the exif metadata. If this fails,
+     * fall back to overwriting file. This preserves tags that are not being
+     * rewritten.
+     *
+     * @param filename a String containing a filepath for a jpeg file.
+     * @param tags tags that will be written into the jpeg file over existing
+     *            tags if possible.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     * @see #rewriteExif
+     */
+    public void forceRewriteExif(String filename, Collection<ExifTag> tags)
+            throws FileNotFoundException,
+            IOException {
+        // Attempt in-place write
+        if (!rewriteExif(filename, tags)) {
+            // Fall back to doing a copy
+            ExifData tempData = mData;
+            mData = new ExifData(DEFAULT_BYTE_ORDER);
+            FileInputStream is = null;
+            ByteArrayOutputStream bytes = null;
+            try {
+                is = new FileInputStream(filename);
+                bytes = new ByteArrayOutputStream();
+                doExifStreamIO(is, bytes);
+                byte[] imageBytes = bytes.toByteArray();
+                readExif(imageBytes);
+                setTags(tags);
+                writeExif(imageBytes, filename);
+            } catch (IOException e) {
+                closeSilently(is);
+                throw e;
+            } finally {
+                is.close();
+                // Prevent clobbering of mData
+                mData = tempData;
+            }
+        }
+    }
+
+    /**
+     * Attempts to do an in-place rewrite of the exif metadata using the tags in
+     * this ExifInterface object. If this fails, fall back to overwriting file.
+     * This preserves tags that are not being rewritten.
+     *
+     * @param filename a String containing a filepath for a jpeg file.
+     * @throws java.io.FileNotFoundException
+     * @throws java.io.IOException
+     * @see #rewriteExif
+     */
+    public void forceRewriteExif(String filename) throws FileNotFoundException, IOException {
+        forceRewriteExif(filename, getAllTags());
+    }
+
+    /**
+     * Get the exif tags in this ExifInterface object or null if none exist.
+     *
+     * @return a List of {@link ExifTag}s.
+     */
+    public List<ExifTag> getAllTags() {
+        return mData.getAllTags();
+    }
+
+    /**
+     * Returns a list of ExifTags that share a TID (which can be obtained by
+     * calling {@link #getTrueTagKey} on a defined tag constant) or null if none
+     * exist.
+     *
+     * @param tagId a TID as defined in the exif standard (or with
+     *            {@link #defineTag}).
+     * @return a List of {@link ExifTag}s.
+     */
+    public List<ExifTag> getTagsForTagId(short tagId) {
+        return mData.getAllTagsForTagId(tagId);
+    }
+
+    /**
+     * Returns a list of ExifTags that share an IFD (which can be obtained by
+     * calling {@link #getTrueIFD} on a defined tag constant) or null if none
+     * exist.
+     *
+     * @param ifdId an IFD as defined in the exif standard (or with
+     *            {@link #defineTag}).
+     * @return a List of {@link ExifTag}s.
+     */
+    public List<ExifTag> getTagsForIfdId(int ifdId) {
+        return mData.getAllTagsForIfd(ifdId);
+    }
+
+    /**
+     * Gets an ExifTag for an IFD other than the tag's default.
+     *
+     * @see #getTag
+     */
+    public ExifTag getTag(int tagId, int ifdId) {
+        if (!ExifTag.isValidIfd(ifdId)) {
+            return null;
+        }
+        return mData.getTag(getTrueTagKey(tagId), ifdId);
+    }
+
+    /**
+     * Returns the ExifTag in that tag's default IFD for a defined tag constant
+     * or null if none exists.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return an {@link ExifTag} or null if none exists.
+     */
+    public ExifTag getTag(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTag(tagId, ifdId);
+    }
+
+    /**
+     * Gets a tag value for an IFD other than the tag's default.
+     *
+     * @see #getTagValue
+     */
+    public Object getTagValue(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        return (t == null) ? null : t.getValue();
+    }
+
+    /**
+     * Returns the value of the ExifTag in that tag's default IFD for a defined
+     * tag constant or null if none exists or the value could not be cast into
+     * the return type.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return the value of the ExifTag or null if none exists.
+     */
+    public Object getTagValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagValue(tagId, ifdId);
+    }
+
+    /*
+     * Getter methods that are similar to getTagValue. Null is returned if the
+     * tag value cannot be cast into the return type.
+     */
+
+    /**
+     * @see #getTagValue
+     */
+    public String getTagStringValue(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return null;
+        }
+        return t.getValueAsString();
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public String getTagStringValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagStringValue(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Long getTagLongValue(int tagId, int ifdId) {
+        long[] l = getTagLongValues(tagId, ifdId);
+        if (l == null || l.length <= 0) {
+            return null;
+        }
+        return new Long(l[0]);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Long getTagLongValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagLongValue(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Integer getTagIntValue(int tagId, int ifdId) {
+        int[] l = getTagIntValues(tagId, ifdId);
+        if (l == null || l.length <= 0) {
+            return null;
+        }
+        return new Integer(l[0]);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Integer getTagIntValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagIntValue(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Byte getTagByteValue(int tagId, int ifdId) {
+        byte[] l = getTagByteValues(tagId, ifdId);
+        if (l == null || l.length <= 0) {
+            return null;
+        }
+        return new Byte(l[0]);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Byte getTagByteValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagByteValue(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Rational getTagRationalValue(int tagId, int ifdId) {
+        Rational[] l = getTagRationalValues(tagId, ifdId);
+        if (l == null || l.length == 0) {
+            return null;
+        }
+        return new Rational(l[0]);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Rational getTagRationalValue(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagRationalValue(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public long[] getTagLongValues(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return null;
+        }
+        return t.getValueAsLongs();
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public long[] getTagLongValues(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagLongValues(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public int[] getTagIntValues(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return null;
+        }
+        return t.getValueAsInts();
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public int[] getTagIntValues(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagIntValues(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public byte[] getTagByteValues(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return null;
+        }
+        return t.getValueAsBytes();
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public byte[] getTagByteValues(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagByteValues(tagId, ifdId);
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Rational[] getTagRationalValues(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return null;
+        }
+        return t.getValueAsRationals();
+    }
+
+    /**
+     * @see #getTagValue
+     */
+    public Rational[] getTagRationalValues(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return getTagRationalValues(tagId, ifdId);
+    }
+
+    /**
+     * Checks whether a tag has a defined number of elements.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return true if the tag has a defined number of elements.
+     */
+    public boolean isTagCountDefined(int tagId) {
+        int info = getTagInfo().get(tagId);
+        // No value in info can be zero, as all tags have a non-zero type
+        if (info == 0) {
+            return false;
+        }
+        return getComponentCountFromInfo(info) != ExifTag.SIZE_UNDEFINED;
+    }
+
+    /**
+     * Gets the defined number of elements for a tag.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return the number of elements or {@link ExifTag#SIZE_UNDEFINED} if the
+     *         tag or the number of elements is not defined.
+     */
+    public int getDefinedTagCount(int tagId) {
+        int info = getTagInfo().get(tagId);
+        if (info == 0) {
+            return ExifTag.SIZE_UNDEFINED;
+        }
+        return getComponentCountFromInfo(info);
+    }
+
+    /**
+     * Gets the number of elements for an ExifTag in a given IFD.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param ifdId the IFD containing the ExifTag to check.
+     * @return the number of elements in the ExifTag, if the tag's size is
+     *         undefined this will return the actual number of elements that is
+     *         in the ExifTag's value.
+     */
+    public int getActualTagCount(int tagId, int ifdId) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return 0;
+        }
+        return t.getComponentCount();
+    }
+
+    /**
+     * Gets the default IFD for a tag.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return the default IFD for a tag definition or {@link #IFD_NULL} if no
+     *         definition exists.
+     */
+    public int getDefinedTagDefaultIfd(int tagId) {
+        int info = getTagInfo().get(tagId);
+        if (info == DEFINITION_NULL) {
+            return IFD_NULL;
+        }
+        return getTrueIfd(tagId);
+    }
+
+    /**
+     * Gets the defined type for a tag.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @return the type.
+     * @see ExifTag#getDataType()
+     */
+    public short getDefinedTagType(int tagId) {
+        int info = getTagInfo().get(tagId);
+        if (info == 0) {
+            return -1;
+        }
+        return getTypeFromInfo(info);
+    }
+
+    /**
+     * Returns true if tag TID is one of the following: {@link TAG_EXIF_IFD},
+     * {@link TAG_GPS_IFD}, {@link TAG_JPEG_INTERCHANGE_FORMAT},
+     * {@link TAG_STRIP_OFFSETS}, {@link TAG_INTEROPERABILITY_IFD}
+     * <p>
+     * Note: defining tags with these TID's is disallowed.
+     *
+     * @param tag a tag's TID (can be obtained from a defined tag constant with
+     *            {@link #getTrueTagKey}).
+     * @return true if the TID is that of an offset tag.
+     */
+    protected static boolean isOffsetTag(short tag) {
+        return sOffsetTags.contains(tag);
+    }
+
+    /**
+     * Creates a tag for a defined tag constant in a given IFD if that IFD is
+     * allowed for the tag.  This method will fail anytime the appropriate
+     * {@link ExifTag#setValue} for this tag's datatype would fail.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param ifdId the IFD that the tag should be in.
+     * @param val the value of the tag to set.
+     * @return an ExifTag object or null if one could not be constructed.
+     * @see #buildTag
+     */
+    public ExifTag buildTag(int tagId, int ifdId, Object val) {
+        int info = getTagInfo().get(tagId);
+        if (info == 0 || val == null) {
+            return null;
+        }
+        short type = getTypeFromInfo(info);
+        int definedCount = getComponentCountFromInfo(info);
+        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
+        if (!ExifInterface.isIfdAllowed(info, ifdId)) {
+            return null;
+        }
+        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
+        if (!t.setValue(val)) {
+            return null;
+        }
+        return t;
+    }
+
+    /**
+     * Creates a tag for a defined tag constant in the tag's default IFD.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param val the tag's value.
+     * @return an ExifTag object.
+     */
+    public ExifTag buildTag(int tagId, Object val) {
+        int ifdId = getTrueIfd(tagId);
+        return buildTag(tagId, ifdId, val);
+    }
+
+    protected ExifTag buildUninitializedTag(int tagId) {
+        int info = getTagInfo().get(tagId);
+        if (info == 0) {
+            return null;
+        }
+        short type = getTypeFromInfo(info);
+        int definedCount = getComponentCountFromInfo(info);
+        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
+        int ifdId = getTrueIfd(tagId);
+        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
+        return t;
+    }
+
+    /**
+     * Sets the value of an ExifTag if it exists in the given IFD. The value
+     * must be the correct type and length for that ExifTag.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param ifdId the IFD that the ExifTag is in.
+     * @param val the value to set.
+     * @return true if success, false if the ExifTag doesn't exist or the value
+     *         is the wrong type/length.
+     * @see #setTagValue
+     */
+    public boolean setTagValue(int tagId, int ifdId, Object val) {
+        ExifTag t = getTag(tagId, ifdId);
+        if (t == null) {
+            return false;
+        }
+        return t.setValue(val);
+    }
+
+    /**
+     * Sets the value of an ExifTag if it exists it's default IFD. The value
+     * must be the correct type and length for that ExifTag.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param val the value to set.
+     * @return true if success, false if the ExifTag doesn't exist or the value
+     *         is the wrong type/length.
+     */
+    public boolean setTagValue(int tagId, Object val) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        return setTagValue(tagId, ifdId, val);
+    }
+
+    /**
+     * Puts an ExifTag into this ExifInterface object's tags, removing a
+     * previous ExifTag with the same TID and IFD. The IFD it is put into will
+     * be the one the tag was created with in {@link #buildTag}.
+     *
+     * @param tag an ExifTag to put into this ExifInterface's tags.
+     * @return the previous ExifTag with the same TID and IFD or null if none
+     *         exists.
+     */
+    public ExifTag setTag(ExifTag tag) {
+        return mData.addTag(tag);
+    }
+
+    /**
+     * Puts a collection of ExifTags into this ExifInterface objects's tags. Any
+     * previous ExifTags with the same TID and IFDs will be removed.
+     *
+     * @param tags a Collection of ExifTags.
+     * @see #setTag
+     */
+    public void setTags(Collection<ExifTag> tags) {
+        for (ExifTag t : tags) {
+            setTag(t);
+        }
+    }
+
+    /**
+     * Removes the ExifTag for a tag constant from the given IFD.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     * @param ifdId the IFD of the ExifTag to remove.
+     */
+    public void deleteTag(int tagId, int ifdId) {
+        mData.removeTag(getTrueTagKey(tagId), ifdId);
+    }
+
+    /**
+     * Removes the ExifTag for a tag constant from that tag's default IFD.
+     *
+     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     */
+    public void deleteTag(int tagId) {
+        int ifdId = getDefinedTagDefaultIfd(tagId);
+        deleteTag(tagId, ifdId);
+    }
+
+    /**
+     * Creates a new tag definition in this ExifInterface object for a given TID
+     * and default IFD. Creating a definition with the same TID and default IFD
+     * as a previous definition will override it.
+     *
+     * @param tagId the TID for the tag.
+     * @param defaultIfd the default IFD for the tag.
+     * @param tagType the type of the tag (see {@link ExifTag#getDataType()}).
+     * @param defaultComponentCount the number of elements of this tag's type in
+     *            the tags value.
+     * @param allowedIfds the IFD's this tag is allowed to be put in.
+     * @return the defined tag constant (e.g. {@link #TAG_IMAGE_WIDTH}) or
+     *         {@link #TAG_NULL} if the definition could not be made.
+     */
+    public int setTagDefinition(short tagId, int defaultIfd, short tagType,
+            short defaultComponentCount, int[] allowedIfds) {
+        if (sBannedDefines.contains(tagId)) {
+            return TAG_NULL;
+        }
+        if (ExifTag.isValidType(tagType) && ExifTag.isValidIfd(defaultIfd)) {
+            int tagDef = defineTag(defaultIfd, tagId);
+            if (tagDef == TAG_NULL) {
+                return TAG_NULL;
+            }
+            int[] otherDefs = getTagDefinitionsForTagId(tagId);
+            SparseIntArray infos = getTagInfo();
+            // Make sure defaultIfd is in allowedIfds
+            boolean defaultCheck = false;
+            for (int i : allowedIfds) {
+                if (defaultIfd == i) {
+                    defaultCheck = true;
+                }
+                if (!ExifTag.isValidIfd(i)) {
+                    return TAG_NULL;
+                }
+            }
+            if (!defaultCheck) {
+                return TAG_NULL;
+            }
+
+            int ifdFlags = getFlagsFromAllowedIfds(allowedIfds);
+            // Make sure no identical tags can exist in allowedIfds
+            if (otherDefs != null) {
+                for (int def : otherDefs) {
+                    int tagInfo = infos.get(def);
+                    int allowedFlags = getAllowedIfdFlagsFromInfo(tagInfo);
+                    if ((ifdFlags & allowedFlags) != 0) {
+                        return TAG_NULL;
+                    }
+                }
+            }
+            getTagInfo().put(tagDef, ifdFlags << 24 | (tagType << 16) | defaultComponentCount);
+            return tagDef;
+        }
+        return TAG_NULL;
+    }
+
+    protected int getTagDefinition(short tagId, int defaultIfd) {
+        return getTagInfo().get(defineTag(defaultIfd, tagId));
+    }
+
+    protected int[] getTagDefinitionsForTagId(short tagId) {
+        int[] ifds = IfdData.getIfds();
+        int[] defs = new int[ifds.length];
+        int counter = 0;
+        SparseIntArray infos = getTagInfo();
+        for (int i : ifds) {
+            int def = defineTag(i, tagId);
+            if (infos.get(def) != DEFINITION_NULL) {
+                defs[counter++] = def;
+            }
+        }
+        if (counter == 0) {
+            return null;
+        }
+
+        return Arrays.copyOfRange(defs, 0, counter);
+    }
+
+    protected int getTagDefinitionForTag(ExifTag tag) {
+        short type = tag.getDataType();
+        int count = tag.getComponentCount();
+        int ifd = tag.getIfd();
+        return getTagDefinitionForTag(tag.getTagId(), type, count, ifd);
+    }
+
+    protected int getTagDefinitionForTag(short tagId, short type, int count, int ifd) {
+        int[] defs = getTagDefinitionsForTagId(tagId);
+        if (defs == null) {
+            return TAG_NULL;
+        }
+        SparseIntArray infos = getTagInfo();
+        int ret = TAG_NULL;
+        for (int i : defs) {
+            int info = infos.get(i);
+            short defType = getTypeFromInfo(info);
+            int defCount = getComponentCountFromInfo(info);
+            int[] defIfds = getAllowedIfdsFromInfo(info);
+            boolean validIfd = false;
+            for (int j : defIfds) {
+                if (j == ifd) {
+                    validIfd = true;
+                    break;
+                }
+            }
+            if (validIfd && type == defType
+                    && (count == defCount || defCount == ExifTag.SIZE_UNDEFINED)) {
+                ret = i;
+                break;
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Removes a tag definition for given defined tag constant.
+     *
+     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
+     */
+    public void removeTagDefinition(int tagId) {
+        getTagInfo().delete(tagId);
+    }
+
+    /**
+     * Resets tag definitions to the default ones.
+     */
+    public void resetTagDefinitions() {
+        mTagInfo = null;
+    }
+
+    /**
+     * Returns the thumbnail from IFD1 as a bitmap, or null if none exists.
+     *
+     * @return the thumbnail as a bitmap.
+     */
+    public Bitmap getThumbnailBitmap() {
+        if (mData.hasCompressedThumbnail()) {
+            byte[] thumb = mData.getCompressedThumbnail();
+            return BitmapFactory.decodeByteArray(thumb, 0, thumb.length);
+        } else if (mData.hasUncompressedStrip()) {
+            // TODO: implement uncompressed
+        }
+        return null;
+    }
+
+    /**
+     * Returns the thumbnail from IFD1 as a byte array, or null if none exists.
+     * The bytes may either be an uncompressed strip as specified in the exif
+     * standard or a jpeg compressed image.
+     *
+     * @return the thumbnail as a byte array.
+     */
+    public byte[] getThumbnailBytes() {
+        if (mData.hasCompressedThumbnail()) {
+            return mData.getCompressedThumbnail();
+        } else if (mData.hasUncompressedStrip()) {
+            // TODO: implement this
+        }
+        return null;
+    }
+
+    /**
+     * Returns the thumbnail if it is jpeg compressed, or null if none exists.
+     *
+     * @return the thumbnail as a byte array.
+     */
+    public byte[] getThumbnail() {
+        return mData.getCompressedThumbnail();
+    }
+
+    /**
+     * Check if thumbnail is compressed.
+     *
+     * @return true if the thumbnail is compressed.
+     */
+    public boolean isThumbnailCompressed() {
+        return mData.hasCompressedThumbnail();
+    }
+
+    /**
+     * Check if thumbnail exists.
+     *
+     * @return true if a compressed thumbnail exists.
+     */
+    public boolean hasThumbnail() {
+        // TODO: add back in uncompressed strip
+        return mData.hasCompressedThumbnail();
+    }
+
+    // TODO: uncompressed thumbnail setters
+
+    /**
+     * Sets the thumbnail to be a jpeg compressed image. Clears any prior
+     * thumbnail.
+     *
+     * @param thumb a byte array containing a jpeg compressed image.
+     * @return true if the thumbnail was set.
+     */
+    public boolean setCompressedThumbnail(byte[] thumb) {
+        mData.clearThumbnailAndStrips();
+        mData.setCompressedThumbnail(thumb);
+        return true;
+    }
+
+    /**
+     * Sets the thumbnail to be a jpeg compressed bitmap. Clears any prior
+     * thumbnail.
+     *
+     * @param thumb a bitmap to compress to a jpeg thumbnail.
+     * @return true if the thumbnail was set.
+     */
+    public boolean setCompressedThumbnail(Bitmap thumb) {
+        ByteArrayOutputStream thumbnail = new ByteArrayOutputStream();
+        if (!thumb.compress(Bitmap.CompressFormat.JPEG, 90, thumbnail)) {
+            return false;
+        }
+        return setCompressedThumbnail(thumbnail.toByteArray());
+    }
+
+    /**
+     * Clears the compressed thumbnail if it exists.
+     */
+    public void removeCompressedThumbnail() {
+        mData.setCompressedThumbnail(null);
+    }
+
+    // Convenience methods:
+
+    /**
+     * Decodes the user comment tag into string as specified in the EXIF
+     * standard. Returns null if decoding failed.
+     */
+    public String getUserComment() {
+        return mData.getUserComment();
+    }
+
+    /**
+     * Returns the Orientation ExifTag value for a given number of degrees.
+     *
+     * @param degrees the amount an image is rotated in degrees.
+     */
+    public static short getOrientationValueForRotation(int degrees) {
+        degrees %= 360;
+        if (degrees < 0) {
+            degrees += 360;
+        }
+        if (degrees < 90) {
+            return Orientation.TOP_LEFT; // 0 degrees
+        } else if (degrees < 180) {
+            return Orientation.RIGHT_TOP; // 90 degrees cw
+        } else if (degrees < 270) {
+            return Orientation.BOTTOM_LEFT; // 180 degrees
+        } else {
+            return Orientation.RIGHT_BOTTOM; // 270 degrees cw
+        }
+    }
+
+    /**
+     * Returns the rotation degrees corresponding to an ExifTag Orientation
+     * value.
+     *
+     * @param orientation the ExifTag Orientation value.
+     */
+    public static int getRotationForOrientationValue(short orientation) {
+        switch (orientation) {
+            case Orientation.TOP_LEFT:
+                return 0;
+            case Orientation.RIGHT_TOP:
+                return 90;
+            case Orientation.BOTTOM_LEFT:
+                return 180;
+            case Orientation.RIGHT_BOTTOM:
+                return 270;
+            default:
+                return 0;
+        }
+    }
+
+    public static OrientationParams getOrientationParams(int orientation) {
+        OrientationParams params = new OrientationParams();
+        switch (orientation) {
+            case Orientation.TOP_RIGHT:     // Flip horizontal
+                params.scaleX = -1;
+                break;
+            case Orientation.BOTTOM_RIGHT:  // Flip vertical
+                params.scaleY = -1;
+                break;
+            case Orientation.BOTTOM_LEFT:   // Rotate 180
+                params.rotation = 180;
+                break;
+            case Orientation.RIGHT_BOTTOM:  // Rotate 270
+                params.rotation = 270;
+                params.invertDimensions = true;
+                break;
+            case Orientation.RIGHT_TOP:     // Rotate 90
+                params.rotation = 90;
+                params.invertDimensions = true;
+                break;
+            case Orientation.LEFT_TOP:      // Transpose
+                params.rotation = 90;
+                params.scaleX = -1;
+                params.invertDimensions = true;
+                break;
+            case Orientation.LEFT_BOTTOM:   // Transverse
+                params.rotation = 270;
+                params.scaleX = -1;
+                params.invertDimensions = true;
+                break;
+        }
+        return params;
+    }
+
+    public static class OrientationParams {
+        public int rotation = 0;
+        public int scaleX = 1;
+        public int scaleY = 1;
+        public boolean invertDimensions = false;
+    }
+
+    /**
+     * Gets the double representation of the GPS latitude or longitude
+     * coordinate.
+     *
+     * @param coordinate an array of 3 Rationals representing the degrees,
+     *            minutes, and seconds of the GPS location as defined in the
+     *            exif specification.
+     * @param reference a GPS reference reperesented by a String containing "N",
+     *            "S", "E", or "W".
+     * @return the GPS coordinate represented as degrees + minutes/60 +
+     *         seconds/3600
+     */
+    public static double convertLatOrLongToDouble(Rational[] coordinate, String reference) {
+        try {
+            double degrees = coordinate[0].toDouble();
+            double minutes = coordinate[1].toDouble();
+            double seconds = coordinate[2].toDouble();
+            double result = degrees + minutes / 60.0 + seconds / 3600.0;
+            if ((reference.equals("S") || reference.equals("W"))) {
+                return -result;
+            }
+            return result;
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Gets the GPS latitude and longitude as a pair of doubles from this
+     * ExifInterface object's tags, or null if the necessary tags do not exist.
+     *
+     * @return an array of 2 doubles containing the latitude, and longitude
+     *         respectively.
+     * @see #convertLatOrLongToDouble
+     */
+    public double[] getLatLongAsDoubles() {
+        Rational[] latitude = getTagRationalValues(TAG_GPS_LATITUDE);
+        String latitudeRef = getTagStringValue(TAG_GPS_LATITUDE_REF);
+        Rational[] longitude = getTagRationalValues(TAG_GPS_LONGITUDE);
+        String longitudeRef = getTagStringValue(TAG_GPS_LONGITUDE_REF);
+        if (latitude == null || longitude == null || latitudeRef == null || longitudeRef == null
+                || latitude.length < 3 || longitude.length < 3) {
+            return null;
+        }
+        double[] latLon = new double[2];
+        latLon[0] = convertLatOrLongToDouble(latitude, latitudeRef);
+        latLon[1] = convertLatOrLongToDouble(longitude, longitudeRef);
+        return latLon;
+    }
+
+    private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
+    private static final String DATETIME_FORMAT_STR = "yyyy:MM:dd kk:mm:ss";
+    private final DateFormat mDateTimeStampFormat = new SimpleDateFormat(DATETIME_FORMAT_STR);
+    private final DateFormat mGPSDateStampFormat = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
+    private final Calendar mGPSTimeStampCalendar = Calendar
+            .getInstance(TimeZone.getTimeZone("UTC"));
+
+    /**
+     * Creates, formats, and sets the DateTimeStamp tag for one of:
+     * {@link #TAG_DATE_TIME}, {@link #TAG_DATE_TIME_DIGITIZED},
+     * {@link #TAG_DATE_TIME_ORIGINAL}.
+     *
+     * @param tagId one of the DateTimeStamp tags.
+     * @param timestamp a timestamp to format.
+     * @param timezone a TimeZone object.
+     * @return true if success, false if the tag could not be set.
+     */
+    public boolean addDateTimeStampTag(int tagId, long timestamp, TimeZone timezone) {
+        if (tagId == TAG_DATE_TIME || tagId == TAG_DATE_TIME_DIGITIZED
+                || tagId == TAG_DATE_TIME_ORIGINAL) {
+            mDateTimeStampFormat.setTimeZone(timezone);
+            ExifTag t = buildTag(tagId, mDateTimeStampFormat.format(timestamp));
+            if (t == null) {
+                return false;
+            }
+            setTag(t);
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Creates and sets all to the GPS tags for a give latitude and longitude.
+     *
+     * @param latitude a GPS latitude coordinate.
+     * @param longitude a GPS longitude coordinate.
+     * @return true if success, false if they could not be created or set.
+     */
+    public boolean addGpsTags(double latitude, double longitude) {
+        ExifTag latTag = buildTag(TAG_GPS_LATITUDE, toExifLatLong(latitude));
+        ExifTag longTag = buildTag(TAG_GPS_LONGITUDE, toExifLatLong(longitude));
+        ExifTag latRefTag = buildTag(TAG_GPS_LATITUDE_REF,
+                latitude >= 0 ? GpsLatitudeRef.NORTH
+                        : GpsLatitudeRef.SOUTH);
+        ExifTag longRefTag = buildTag(TAG_GPS_LONGITUDE_REF,
+                longitude >= 0 ? GpsLongitudeRef.EAST
+                        : GpsLongitudeRef.WEST);
+        if (latTag == null || longTag == null || latRefTag == null || longRefTag == null) {
+            return false;
+        }
+        setTag(latTag);
+        setTag(longTag);
+        setTag(latRefTag);
+        setTag(longRefTag);
+        return true;
+    }
+
+    /**
+     * Creates and sets the GPS timestamp tag.
+     *
+     * @param timestamp a GPS timestamp.
+     * @return true if success, false if could not be created or set.
+     */
+    public boolean addGpsDateTimeStampTag(long timestamp) {
+        ExifTag t = buildTag(TAG_GPS_DATE_STAMP, mGPSDateStampFormat.format(timestamp));
+        if (t == null) {
+            return false;
+        }
+        setTag(t);
+        mGPSTimeStampCalendar.setTimeInMillis(timestamp);
+        t = buildTag(TAG_GPS_TIME_STAMP, new Rational[] {
+                new Rational(mGPSTimeStampCalendar.get(Calendar.HOUR_OF_DAY), 1),
+                new Rational(mGPSTimeStampCalendar.get(Calendar.MINUTE), 1),
+                new Rational(mGPSTimeStampCalendar.get(Calendar.SECOND), 1)
+        });
+        if (t == null) {
+            return false;
+        }
+        setTag(t);
+        return true;
+    }
+
+    private static Rational[] toExifLatLong(double value) {
+        // convert to the format dd/1 mm/1 ssss/100
+        value = Math.abs(value);
+        int degrees = (int) value;
+        value = (value - degrees) * 60;
+        int minutes = (int) value;
+        value = (value - minutes) * 6000;
+        int seconds = (int) value;
+        return new Rational[] {
+                new Rational(degrees, 1), new Rational(minutes, 1), new Rational(seconds, 100)
+        };
+    }
+
+    private void doExifStreamIO(InputStream is, OutputStream os) throws IOException {
+        byte[] buf = new byte[1024];
+        int ret = is.read(buf, 0, 1024);
+        while (ret != -1) {
+            os.write(buf, 0, ret);
+            ret = is.read(buf, 0, 1024);
+        }
+    }
+
+    protected static void closeSilently(Closeable c) {
+        if (c != null) {
+            try {
+                c.close();
+            } catch (Throwable e) {
+                // ignored
+            }
+        }
+    }
+
+    private SparseIntArray mTagInfo = null;
+
+    protected SparseIntArray getTagInfo() {
+        if (mTagInfo == null) {
+            mTagInfo = new SparseIntArray();
+            initTagInfo();
+        }
+        return mTagInfo;
+    }
+
+    private void initTagInfo() {
+        /**
+         * We put tag information in a 4-bytes integer. The first byte a bitmask
+         * representing the allowed IFDs of the tag, the second byte is the data
+         * type, and the last two byte are a short value indicating the default
+         * component count of this tag.
+         */
+        // IFD0 tags
+        int[] ifdAllowedIfds = {
+                IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_1
+        };
+        int ifdFlags = getFlagsFromAllowedIfds(ifdAllowedIfds) << 24;
+        mTagInfo.put(ExifInterface.TAG_MAKE,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_IMAGE_WIDTH,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_IMAGE_LENGTH,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_BITS_PER_SAMPLE,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3);
+        mTagInfo.put(ExifInterface.TAG_COMPRESSION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_PHOTOMETRIC_INTERPRETATION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_ORIENTATION, ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16
+                | 1);
+        mTagInfo.put(ExifInterface.TAG_SAMPLES_PER_PIXEL,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_PLANAR_CONFIGURATION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_SUB_SAMPLING,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_POSITIONING,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_X_RESOLUTION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_Y_RESOLUTION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_RESOLUTION_UNIT,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_STRIP_OFFSETS,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_ROWS_PER_STRIP,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_STRIP_BYTE_COUNTS,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_TRANSFER_FUNCTION,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3 * 256);
+        mTagInfo.put(ExifInterface.TAG_WHITE_POINT,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_PRIMARY_CHROMATICITIES,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
+        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_COEFFICIENTS,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
+        mTagInfo.put(ExifInterface.TAG_REFERENCE_BLACK_WHITE,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
+        mTagInfo.put(ExifInterface.TAG_DATE_TIME,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | 20);
+        mTagInfo.put(ExifInterface.TAG_IMAGE_DESCRIPTION,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_MAKE,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_MODEL,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_SOFTWARE,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_ARTIST,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_COPYRIGHT,
+                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_EXIF_IFD,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_IFD,
+                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        // IFD1 tags
+        int[] ifd1AllowedIfds = {
+            IfdId.TYPE_IFD_1
+        };
+        int ifdFlags1 = getFlagsFromAllowedIfds(ifd1AllowedIfds) << 24;
+        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT,
+                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        // Exif tags
+        int[] exifAllowedIfds = {
+            IfdId.TYPE_IFD_EXIF
+        };
+        int exifFlags = getFlagsFromAllowedIfds(exifAllowedIfds) << 24;
+        mTagInfo.put(ExifInterface.TAG_EXIF_VERSION,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
+        mTagInfo.put(ExifInterface.TAG_FLASHPIX_VERSION,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
+        mTagInfo.put(ExifInterface.TAG_COLOR_SPACE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_COMPONENTS_CONFIGURATION,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
+        mTagInfo.put(ExifInterface.TAG_COMPRESSED_BITS_PER_PIXEL,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_PIXEL_X_DIMENSION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_PIXEL_Y_DIMENSION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_MAKER_NOTE,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_USER_COMMENT,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_RELATED_SOUND_FILE,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | 13);
+        mTagInfo.put(ExifInterface.TAG_DATE_TIME_ORIGINAL,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
+        mTagInfo.put(ExifInterface.TAG_DATE_TIME_DIGITIZED,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
+        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_ORIGINAL,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_DIGITIZED,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_IMAGE_UNIQUE_ID,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | 33);
+        mTagInfo.put(ExifInterface.TAG_EXPOSURE_TIME,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_F_NUMBER,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_EXPOSURE_PROGRAM,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SPECTRAL_SENSITIVITY,
+                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_ISO_SPEED_RATINGS,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_OECF,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE,
+                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_APERTURE_VALUE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_BRIGHTNESS_VALUE,
+                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_EXPOSURE_BIAS_VALUE,
+                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_MAX_APERTURE_VALUE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_METERING_MODE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_LIGHT_SOURCE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FLASH,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SUBJECT_AREA,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_FLASH_ENERGY,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SPATIAL_FREQUENCY_RESPONSE,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SUBJECT_LOCATION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_EXPOSURE_INDEX,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SENSING_METHOD,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FILE_SOURCE,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SCENE_TYPE,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_CFA_PATTERN,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_CUSTOM_RENDERED,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_EXPOSURE_MODE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_WHITE_BALANCE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_DIGITAL_ZOOM_RATIO,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH_IN_35_MM_FILE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SCENE_CAPTURE_TYPE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GAIN_CONTROL,
+                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_CONTRAST,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SATURATION,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_SHARPNESS,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION,
+                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE_RANGE,
+                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_INTEROPERABILITY_IFD, exifFlags
+                | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
+        // GPS tag
+        int[] gpsAllowedIfds = {
+            IfdId.TYPE_IFD_GPS
+        };
+        int gpsFlags = getFlagsFromAllowedIfds(gpsAllowedIfds) << 24;
+        mTagInfo.put(ExifInterface.TAG_GPS_VERSION_ID,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 4);
+        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE,
+                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
+        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE,
+                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
+        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE_REF,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_TIME_STAMP,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
+        mTagInfo.put(ExifInterface.TAG_GPS_SATTELLITES,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_GPS_STATUS,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_MEASURE_MODE,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_DOP,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_SPEED_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_SPEED,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_TRACK_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_TRACK,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_MAP_DATUM,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
+        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
+        mTagInfo.put(ExifInterface.TAG_GPS_PROCESSING_METHOD,
+                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_GPS_AREA_INFORMATION,
+                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
+        mTagInfo.put(ExifInterface.TAG_GPS_DATE_STAMP,
+                gpsFlags | ExifTag.TYPE_ASCII << 16 | 11);
+        mTagInfo.put(ExifInterface.TAG_GPS_DIFFERENTIAL,
+                gpsFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 11);
+        // Interoperability tag
+        int[] interopAllowedIfds = {
+            IfdId.TYPE_IFD_INTEROPERABILITY
+        };
+        int interopFlags = getFlagsFromAllowedIfds(interopAllowedIfds) << 24;
+        mTagInfo.put(TAG_INTEROPERABILITY_INDEX, interopFlags | ExifTag.TYPE_ASCII << 16
+                | ExifTag.SIZE_UNDEFINED);
+    }
+
+    protected static int getAllowedIfdFlagsFromInfo(int info) {
+        return info >>> 24;
+    }
+
+    protected static int[] getAllowedIfdsFromInfo(int info) {
+        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
+        int[] ifds = IfdData.getIfds();
+        ArrayList<Integer> l = new ArrayList<Integer>();
+        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
+            int flag = (ifdFlags >> i) & 1;
+            if (flag == 1) {
+                l.add(ifds[i]);
+            }
+        }
+        if (l.size() <= 0) {
+            return null;
+        }
+        int[] ret = new int[l.size()];
+        int j = 0;
+        for (int i : l) {
+            ret[j++] = i;
+        }
+        return ret;
+    }
+
+    protected static boolean isIfdAllowed(int info, int ifd) {
+        int[] ifds = IfdData.getIfds();
+        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
+        for (int i = 0; i < ifds.length; i++) {
+            if (ifd == ifds[i] && ((ifdFlags >> i) & 1) == 1) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected static int getFlagsFromAllowedIfds(int[] allowedIfds) {
+        if (allowedIfds == null || allowedIfds.length == 0) {
+            return 0;
+        }
+        int flags = 0;
+        int[] ifds = IfdData.getIfds();
+        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
+            for (int j : allowedIfds) {
+                if (ifds[i] == j) {
+                    flags |= 1 << i;
+                    break;
+                }
+            }
+        }
+        return flags;
+    }
+
+    protected static short getTypeFromInfo(int info) {
+        return (short) ((info >> 16) & 0x0ff);
+    }
+
+    protected static int getComponentCountFromInfo(int info) {
+        return info & 0x0ffff;
+    }
+
+}
diff --git a/src/com/android/messaging/util/exif/ExifInvalidFormatException.java b/src/com/android/messaging/util/exif/ExifInvalidFormatException.java
new file mode 100644
index 0000000..a38f8a3
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifInvalidFormatException.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+public class ExifInvalidFormatException extends Exception {
+    public ExifInvalidFormatException(String meg) {
+        super(meg);
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifModifier.java b/src/com/android/messaging/util/exif/ExifModifier.java
new file mode 100644
index 0000000..274022c
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifModifier.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.util.Log;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+class ExifModifier {
+    public static final String TAG = LogUtil.BUGLE_TAG;
+    public static final boolean DEBUG = false;
+    private final ByteBuffer mByteBuffer;
+    private final ExifData mTagToModified;
+    private final List<TagOffset> mTagOffsets = new ArrayList<TagOffset>();
+    private final ExifInterface mInterface;
+    private int mOffsetBase;
+
+    private static class TagOffset {
+        final int mOffset;
+        final ExifTag mTag;
+
+        TagOffset(ExifTag tag, int offset) {
+            mTag = tag;
+            mOffset = offset;
+        }
+    }
+
+    protected ExifModifier(ByteBuffer byteBuffer, ExifInterface iRef) throws IOException,
+            ExifInvalidFormatException {
+        mByteBuffer = byteBuffer;
+        mOffsetBase = byteBuffer.position();
+        mInterface = iRef;
+        InputStream is = null;
+        try {
+            is = new ByteBufferInputStream(byteBuffer);
+            // Do not require any IFD;
+            ExifParser parser = ExifParser.parse(is, mInterface);
+            mTagToModified = new ExifData(parser.getByteOrder());
+            mOffsetBase += parser.getTiffStartPosition();
+            mByteBuffer.position(0);
+        } finally {
+            ExifInterface.closeSilently(is);
+        }
+    }
+
+    protected ByteOrder getByteOrder() {
+        return mTagToModified.getByteOrder();
+    }
+
+    protected boolean commit() throws IOException, ExifInvalidFormatException {
+        InputStream is = null;
+        try {
+            is = new ByteBufferInputStream(mByteBuffer);
+            int flag = 0;
+            IfdData[] ifdDatas = new IfdData[] {
+                    mTagToModified.getIfdData(IfdId.TYPE_IFD_0),
+                    mTagToModified.getIfdData(IfdId.TYPE_IFD_1),
+                    mTagToModified.getIfdData(IfdId.TYPE_IFD_EXIF),
+                    mTagToModified.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY),
+                    mTagToModified.getIfdData(IfdId.TYPE_IFD_GPS)
+            };
+
+            if (ifdDatas[IfdId.TYPE_IFD_0] != null) {
+                flag |= ExifParser.OPTION_IFD_0;
+            }
+            if (ifdDatas[IfdId.TYPE_IFD_1] != null) {
+                flag |= ExifParser.OPTION_IFD_1;
+            }
+            if (ifdDatas[IfdId.TYPE_IFD_EXIF] != null) {
+                flag |= ExifParser.OPTION_IFD_EXIF;
+            }
+            if (ifdDatas[IfdId.TYPE_IFD_GPS] != null) {
+                flag |= ExifParser.OPTION_IFD_GPS;
+            }
+            if (ifdDatas[IfdId.TYPE_IFD_INTEROPERABILITY] != null) {
+                flag |= ExifParser.OPTION_IFD_INTEROPERABILITY;
+            }
+
+            ExifParser parser = ExifParser.parse(is, flag, mInterface);
+            int event = parser.next();
+            IfdData currIfd = null;
+            while (event != ExifParser.EVENT_END) {
+                switch (event) {
+                    case ExifParser.EVENT_START_OF_IFD:
+                        currIfd = ifdDatas[parser.getCurrentIfd()];
+                        if (currIfd == null) {
+                            parser.skipRemainingTagsInCurrentIfd();
+                        }
+                        break;
+                    case ExifParser.EVENT_NEW_TAG:
+                        ExifTag oldTag = parser.getTag();
+                        ExifTag newTag = currIfd.getTag(oldTag.getTagId());
+                        if (newTag != null) {
+                            if (newTag.getComponentCount() != oldTag.getComponentCount()
+                                    || newTag.getDataType() != oldTag.getDataType()) {
+                                return false;
+                            } else {
+                                mTagOffsets.add(new TagOffset(newTag, oldTag.getOffset()));
+                                currIfd.removeTag(oldTag.getTagId());
+                                if (currIfd.getTagCount() == 0) {
+                                    parser.skipRemainingTagsInCurrentIfd();
+                                }
+                            }
+                        }
+                        break;
+                }
+                event = parser.next();
+            }
+            for (IfdData ifd : ifdDatas) {
+                if (ifd != null && ifd.getTagCount() > 0) {
+                    return false;
+                }
+            }
+            modify();
+        } finally {
+            ExifInterface.closeSilently(is);
+        }
+        return true;
+    }
+
+    private void modify() {
+        mByteBuffer.order(getByteOrder());
+        for (TagOffset tagOffset : mTagOffsets) {
+            writeTagValue(tagOffset.mTag, tagOffset.mOffset);
+        }
+    }
+
+    private void writeTagValue(ExifTag tag, int offset) {
+        if (DEBUG) {
+            Log.v(TAG, "modifying tag to: \n" + tag.toString());
+            Log.v(TAG, "at offset: " + offset);
+        }
+        mByteBuffer.position(offset + mOffsetBase);
+        switch (tag.getDataType()) {
+            case ExifTag.TYPE_ASCII:
+                byte buf[] = tag.getStringByte();
+                if (buf.length == tag.getComponentCount()) {
+                    buf[buf.length - 1] = 0;
+                    mByteBuffer.put(buf);
+                } else {
+                    mByteBuffer.put(buf);
+                    mByteBuffer.put((byte) 0);
+                }
+                break;
+            case ExifTag.TYPE_LONG:
+            case ExifTag.TYPE_UNSIGNED_LONG:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    mByteBuffer.putInt((int) tag.getValueAt(i));
+                }
+                break;
+            case ExifTag.TYPE_RATIONAL:
+            case ExifTag.TYPE_UNSIGNED_RATIONAL:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    Rational v = tag.getRational(i);
+                    mByteBuffer.putInt((int) v.getNumerator());
+                    mByteBuffer.putInt((int) v.getDenominator());
+                }
+                break;
+            case ExifTag.TYPE_UNDEFINED:
+            case ExifTag.TYPE_UNSIGNED_BYTE:
+                buf = new byte[tag.getComponentCount()];
+                tag.getBytes(buf);
+                mByteBuffer.put(buf);
+                break;
+            case ExifTag.TYPE_UNSIGNED_SHORT:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    mByteBuffer.putShort((short) tag.getValueAt(i));
+                }
+                break;
+        }
+    }
+
+    public void modifyTag(ExifTag tag) {
+        mTagToModified.addTag(tag);
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifOutputStream.java b/src/com/android/messaging/util/exif/ExifOutputStream.java
new file mode 100644
index 0000000..2016da4
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifOutputStream.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.util.Log;
+import com.android.messaging.util.LogUtil;
+
+import java.io.BufferedOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+/**
+ * This class provides a way to replace the Exif header of a JPEG image.
+ * <p>
+ * Below is an example of writing EXIF data into a file
+ *
+ * <pre>
+ * public static void writeExif(byte[] jpeg, ExifData exif, String path) {
+ *     OutputStream os = null;
+ *     try {
+ *         os = new FileOutputStream(path);
+ *         ExifOutputStream eos = new ExifOutputStream(os);
+ *         // Set the exif header
+ *         eos.setExifData(exif);
+ *         // Write the original jpeg out, the header will be add into the file.
+ *         eos.write(jpeg);
+ *     } catch (FileNotFoundException e) {
+ *         e.printStackTrace();
+ *     } catch (IOException e) {
+ *         e.printStackTrace();
+ *     } finally {
+ *         if (os != null) {
+ *             try {
+ *                 os.close();
+ *             } catch (IOException e) {
+ *                 e.printStackTrace();
+ *             }
+ *         }
+ *     }
+ * }
+ * </pre>
+ */
+class ExifOutputStream extends FilterOutputStream {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    private static final boolean DEBUG = false;
+    private static final int STREAMBUFFER_SIZE = 0x00010000; // 64Kb
+
+    private static final int STATE_SOI = 0;
+    private static final int STATE_FRAME_HEADER = 1;
+    private static final int STATE_JPEG_DATA = 2;
+
+    private static final int EXIF_HEADER = 0x45786966;
+    private static final short TIFF_HEADER = 0x002A;
+    private static final short TIFF_BIG_ENDIAN = 0x4d4d;
+    private static final short TIFF_LITTLE_ENDIAN = 0x4949;
+    private static final short TAG_SIZE = 12;
+    private static final short TIFF_HEADER_SIZE = 8;
+    private static final int MAX_EXIF_SIZE = 65535;
+
+    private ExifData mExifData;
+    private int mState = STATE_SOI;
+    private int mByteToSkip;
+    private int mByteToCopy;
+    private final byte[] mSingleByteArray = new byte[1];
+    private final ByteBuffer mBuffer = ByteBuffer.allocate(4);
+    private final ExifInterface mInterface;
+
+    protected ExifOutputStream(OutputStream ou, ExifInterface iRef) {
+        super(new BufferedOutputStream(ou, STREAMBUFFER_SIZE));
+        mInterface = iRef;
+    }
+
+    /**
+     * Sets the ExifData to be written into the JPEG file. Should be called
+     * before writing image data.
+     */
+    protected void setExifData(ExifData exifData) {
+        mExifData = exifData;
+    }
+
+    /**
+     * Gets the Exif header to be written into the JPEF file.
+     */
+    protected ExifData getExifData() {
+        return mExifData;
+    }
+
+    private int requestByteToBuffer(int requestByteCount, byte[] buffer
+            , int offset, int length) {
+        int byteNeeded = requestByteCount - mBuffer.position();
+        int byteToRead = length > byteNeeded ? byteNeeded : length;
+        mBuffer.put(buffer, offset, byteToRead);
+        return byteToRead;
+    }
+
+    /**
+     * Writes the image out. The input data should be a valid JPEG format. After
+     * writing, it's Exif header will be replaced by the given header.
+     */
+    @Override
+    public void write(byte[] buffer, int offset, int length) throws IOException {
+        while ((mByteToSkip > 0 || mByteToCopy > 0 || mState != STATE_JPEG_DATA)
+                && length > 0) {
+            if (mByteToSkip > 0) {
+                int byteToProcess = length > mByteToSkip ? mByteToSkip : length;
+                length -= byteToProcess;
+                mByteToSkip -= byteToProcess;
+                offset += byteToProcess;
+            }
+            if (mByteToCopy > 0) {
+                int byteToProcess = length > mByteToCopy ? mByteToCopy : length;
+                out.write(buffer, offset, byteToProcess);
+                length -= byteToProcess;
+                mByteToCopy -= byteToProcess;
+                offset += byteToProcess;
+            }
+            if (length == 0) {
+                return;
+            }
+            switch (mState) {
+                case STATE_SOI:
+                    int byteRead = requestByteToBuffer(2, buffer, offset, length);
+                    offset += byteRead;
+                    length -= byteRead;
+                    if (mBuffer.position() < 2) {
+                        return;
+                    }
+                    mBuffer.rewind();
+                    if (mBuffer.getShort() != JpegHeader.SOI) {
+                        throw new IOException("Not a valid jpeg image, cannot write exif");
+                    }
+                    out.write(mBuffer.array(), 0, 2);
+                    mState = STATE_FRAME_HEADER;
+                    mBuffer.rewind();
+                    writeExifData();
+                    break;
+                case STATE_FRAME_HEADER:
+                    // We ignore the APP1 segment and copy all other segments
+                    // until SOF tag.
+                    byteRead = requestByteToBuffer(4, buffer, offset, length);
+                    offset += byteRead;
+                    length -= byteRead;
+                    // Check if this image data doesn't contain SOF.
+                    if (mBuffer.position() == 2) {
+                        short tag = mBuffer.getShort();
+                        if (tag == JpegHeader.EOI) {
+                            out.write(mBuffer.array(), 0, 2);
+                            mBuffer.rewind();
+                        }
+                    }
+                    if (mBuffer.position() < 4) {
+                        return;
+                    }
+                    mBuffer.rewind();
+                    short marker = mBuffer.getShort();
+                    if (marker == JpegHeader.APP1) {
+                        mByteToSkip = (mBuffer.getShort() & 0x0000ffff) - 2;
+                        mState = STATE_JPEG_DATA;
+                    } else if (!JpegHeader.isSofMarker(marker)) {
+                        out.write(mBuffer.array(), 0, 4);
+                        mByteToCopy = (mBuffer.getShort() & 0x0000ffff) - 2;
+                    } else {
+                        out.write(mBuffer.array(), 0, 4);
+                        mState = STATE_JPEG_DATA;
+                    }
+                    mBuffer.rewind();
+            }
+        }
+        if (length > 0) {
+            out.write(buffer, offset, length);
+        }
+    }
+
+    /**
+     * Writes the one bytes out. The input data should be a valid JPEG format.
+     * After writing, it's Exif header will be replaced by the given header.
+     */
+    @Override
+    public void write(int oneByte) throws IOException {
+        mSingleByteArray[0] = (byte) (0xff & oneByte);
+        write(mSingleByteArray);
+    }
+
+    /**
+     * Equivalent to calling write(buffer, 0, buffer.length).
+     */
+    @Override
+    public void write(byte[] buffer) throws IOException {
+        write(buffer, 0, buffer.length);
+    }
+
+    private void writeExifData() throws IOException {
+        if (mExifData == null) {
+            return;
+        }
+        if (DEBUG) {
+            Log.v(TAG, "Writing exif data...");
+        }
+        ArrayList<ExifTag> nullTags = stripNullValueTags(mExifData);
+        createRequiredIfdAndTag();
+        int exifSize = calculateAllOffset();
+        if (exifSize + 8 > MAX_EXIF_SIZE) {
+            throw new IOException("Exif header is too large (>64Kb)");
+        }
+        OrderedDataOutputStream dataOutputStream = new OrderedDataOutputStream(out);
+        dataOutputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
+        dataOutputStream.writeShort(JpegHeader.APP1);
+        dataOutputStream.writeShort((short) (exifSize + 8));
+        dataOutputStream.writeInt(EXIF_HEADER);
+        dataOutputStream.writeShort((short) 0x0000);
+        if (mExifData.getByteOrder() == ByteOrder.BIG_ENDIAN) {
+            dataOutputStream.writeShort(TIFF_BIG_ENDIAN);
+        } else {
+            dataOutputStream.writeShort(TIFF_LITTLE_ENDIAN);
+        }
+        dataOutputStream.setByteOrder(mExifData.getByteOrder());
+        dataOutputStream.writeShort(TIFF_HEADER);
+        dataOutputStream.writeInt(8);
+        writeAllTags(dataOutputStream);
+        writeThumbnail(dataOutputStream);
+        for (ExifTag t : nullTags) {
+            mExifData.addTag(t);
+        }
+    }
+
+    private ArrayList<ExifTag> stripNullValueTags(ExifData data) {
+        ArrayList<ExifTag> nullTags = new ArrayList<ExifTag>();
+        if (data.getAllTags() == null) {
+            return nullTags;
+        }
+        for (ExifTag t : data.getAllTags()) {
+            if (t.getValue() == null && !ExifInterface.isOffsetTag(t.getTagId())) {
+                data.removeTag(t.getTagId(), t.getIfd());
+                nullTags.add(t);
+            }
+        }
+        return nullTags;
+    }
+
+    private void writeThumbnail(OrderedDataOutputStream dataOutputStream) throws IOException {
+        if (mExifData.hasCompressedThumbnail()) {
+            dataOutputStream.write(mExifData.getCompressedThumbnail());
+        } else if (mExifData.hasUncompressedStrip()) {
+            for (int i = 0; i < mExifData.getStripCount(); i++) {
+                dataOutputStream.write(mExifData.getStrip(i));
+            }
+        }
+    }
+
+    private void writeAllTags(OrderedDataOutputStream dataOutputStream) throws IOException {
+        writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_0), dataOutputStream);
+        writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_EXIF), dataOutputStream);
+        IfdData interoperabilityIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+        if (interoperabilityIfd != null) {
+            writeIfd(interoperabilityIfd, dataOutputStream);
+        }
+        IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+        if (gpsIfd != null) {
+            writeIfd(gpsIfd, dataOutputStream);
+        }
+        IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+        if (ifd1 != null) {
+            writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_1), dataOutputStream);
+        }
+    }
+
+    private void writeIfd(IfdData ifd, OrderedDataOutputStream dataOutputStream)
+            throws IOException {
+        ExifTag[] tags = ifd.getAllTags();
+        dataOutputStream.writeShort((short) tags.length);
+        for (ExifTag tag : tags) {
+            dataOutputStream.writeShort(tag.getTagId());
+            dataOutputStream.writeShort(tag.getDataType());
+            dataOutputStream.writeInt(tag.getComponentCount());
+            if (DEBUG) {
+                Log.v(TAG, "\n" + tag.toString());
+            }
+            if (tag.getDataSize() > 4) {
+                dataOutputStream.writeInt(tag.getOffset());
+            } else {
+                ExifOutputStream.writeTagValue(tag, dataOutputStream);
+                for (int i = 0, n = 4 - tag.getDataSize(); i < n; i++) {
+                    dataOutputStream.write(0);
+                }
+            }
+        }
+        dataOutputStream.writeInt(ifd.getOffsetToNextIfd());
+        for (ExifTag tag : tags) {
+            if (tag.getDataSize() > 4) {
+                ExifOutputStream.writeTagValue(tag, dataOutputStream);
+            }
+        }
+    }
+
+    private int calculateOffsetOfIfd(IfdData ifd, int offset) {
+        offset += 2 + ifd.getTagCount() * TAG_SIZE + 4;
+        ExifTag[] tags = ifd.getAllTags();
+        for (ExifTag tag : tags) {
+            if (tag.getDataSize() > 4) {
+                tag.setOffset(offset);
+                offset += tag.getDataSize();
+            }
+        }
+        return offset;
+    }
+
+    private void createRequiredIfdAndTag() throws IOException {
+        // IFD0 is required for all file
+        IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0);
+        if (ifd0 == null) {
+            ifd0 = new IfdData(IfdId.TYPE_IFD_0);
+            mExifData.addIfdData(ifd0);
+        }
+        ExifTag exifOffsetTag = mInterface.buildUninitializedTag(ExifInterface.TAG_EXIF_IFD);
+        if (exifOffsetTag == null) {
+            throw new IOException("No definition for crucial exif tag: "
+                    + ExifInterface.TAG_EXIF_IFD);
+        }
+        ifd0.setTag(exifOffsetTag);
+
+        // Exif IFD is required for all files.
+        IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF);
+        if (exifIfd == null) {
+            exifIfd = new IfdData(IfdId.TYPE_IFD_EXIF);
+            mExifData.addIfdData(exifIfd);
+        }
+
+        // GPS IFD
+        IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+        if (gpsIfd != null) {
+            ExifTag gpsOffsetTag = mInterface.buildUninitializedTag(ExifInterface.TAG_GPS_IFD);
+            if (gpsOffsetTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_GPS_IFD);
+            }
+            ifd0.setTag(gpsOffsetTag);
+        }
+
+        // Interoperability IFD
+        IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+        if (interIfd != null) {
+            ExifTag interOffsetTag = mInterface
+                    .buildUninitializedTag(ExifInterface.TAG_INTEROPERABILITY_IFD);
+            if (interOffsetTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_INTEROPERABILITY_IFD);
+            }
+            exifIfd.setTag(interOffsetTag);
+        }
+
+        IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+
+        // thumbnail
+        if (mExifData.hasCompressedThumbnail()) {
+
+            if (ifd1 == null) {
+                ifd1 = new IfdData(IfdId.TYPE_IFD_1);
+                mExifData.addIfdData(ifd1);
+            }
+
+            ExifTag offsetTag = mInterface
+                    .buildUninitializedTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT);
+            if (offsetTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT);
+            }
+
+            ifd1.setTag(offsetTag);
+            ExifTag lengthTag = mInterface
+                    .buildUninitializedTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+            if (lengthTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+            }
+
+            lengthTag.setValue(mExifData.getCompressedThumbnail().length);
+            ifd1.setTag(lengthTag);
+
+            // Get rid of tags for uncompressed if they exist.
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS));
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_BYTE_COUNTS));
+        } else if (mExifData.hasUncompressedStrip()) {
+            if (ifd1 == null) {
+                ifd1 = new IfdData(IfdId.TYPE_IFD_1);
+                mExifData.addIfdData(ifd1);
+            }
+            int stripCount = mExifData.getStripCount();
+            ExifTag offsetTag = mInterface.buildUninitializedTag(ExifInterface.TAG_STRIP_OFFSETS);
+            if (offsetTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_STRIP_OFFSETS);
+            }
+            ExifTag lengthTag = mInterface
+                    .buildUninitializedTag(ExifInterface.TAG_STRIP_BYTE_COUNTS);
+            if (lengthTag == null) {
+                throw new IOException("No definition for crucial exif tag: "
+                        + ExifInterface.TAG_STRIP_BYTE_COUNTS);
+            }
+            long[] lengths = new long[stripCount];
+            for (int i = 0; i < mExifData.getStripCount(); i++) {
+                lengths[i] = mExifData.getStrip(i).length;
+            }
+            lengthTag.setValue(lengths);
+            ifd1.setTag(offsetTag);
+            ifd1.setTag(lengthTag);
+            // Get rid of tags for compressed if they exist.
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT));
+            ifd1.removeTag(ExifInterface
+                    .getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH));
+        } else if (ifd1 != null) {
+            // Get rid of offset and length tags if there is no thumbnail.
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS));
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_BYTE_COUNTS));
+            ifd1.removeTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT));
+            ifd1.removeTag(ExifInterface
+                    .getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH));
+        }
+    }
+
+    private int calculateAllOffset() {
+        int offset = TIFF_HEADER_SIZE;
+        IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0);
+        offset = calculateOffsetOfIfd(ifd0, offset);
+        ifd0.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_EXIF_IFD)).setValue(offset);
+
+        IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF);
+        offset = calculateOffsetOfIfd(exifIfd, offset);
+
+        IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+        if (interIfd != null) {
+            exifIfd.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_INTEROPERABILITY_IFD))
+                    .setValue(offset);
+            offset = calculateOffsetOfIfd(interIfd, offset);
+        }
+
+        IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+        if (gpsIfd != null) {
+            ifd0.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_GPS_IFD)).setValue(offset);
+            offset = calculateOffsetOfIfd(gpsIfd, offset);
+        }
+
+        IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+        if (ifd1 != null) {
+            ifd0.setOffsetToNextIfd(offset);
+            offset = calculateOffsetOfIfd(ifd1, offset);
+        }
+
+        // thumbnail
+        if (mExifData.hasCompressedThumbnail()) {
+            ifd1.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT))
+                    .setValue(offset);
+            offset += mExifData.getCompressedThumbnail().length;
+        } else if (mExifData.hasUncompressedStrip()) {
+            int stripCount = mExifData.getStripCount();
+            long[] offsets = new long[stripCount];
+            for (int i = 0; i < mExifData.getStripCount(); i++) {
+                offsets[i] = offset;
+                offset += mExifData.getStrip(i).length;
+            }
+            ifd1.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS)).setValue(
+                    offsets);
+        }
+        return offset;
+    }
+
+    static void writeTagValue(ExifTag tag, OrderedDataOutputStream dataOutputStream)
+            throws IOException {
+        switch (tag.getDataType()) {
+            case ExifTag.TYPE_ASCII:
+                byte buf[] = tag.getStringByte();
+                if (buf.length == tag.getComponentCount()) {
+                    buf[buf.length - 1] = 0;
+                    dataOutputStream.write(buf);
+                } else {
+                    dataOutputStream.write(buf);
+                    dataOutputStream.write(0);
+                }
+                break;
+            case ExifTag.TYPE_LONG:
+            case ExifTag.TYPE_UNSIGNED_LONG:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    dataOutputStream.writeInt((int) tag.getValueAt(i));
+                }
+                break;
+            case ExifTag.TYPE_RATIONAL:
+            case ExifTag.TYPE_UNSIGNED_RATIONAL:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    dataOutputStream.writeRational(tag.getRational(i));
+                }
+                break;
+            case ExifTag.TYPE_UNDEFINED:
+            case ExifTag.TYPE_UNSIGNED_BYTE:
+                buf = new byte[tag.getComponentCount()];
+                tag.getBytes(buf);
+                dataOutputStream.write(buf);
+                break;
+            case ExifTag.TYPE_UNSIGNED_SHORT:
+                for (int i = 0, n = tag.getComponentCount(); i < n; i++) {
+                    dataOutputStream.writeShort((short) tag.getValueAt(i));
+                }
+                break;
+        }
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifParser.java b/src/com/android/messaging/util/exif/ExifParser.java
new file mode 100644
index 0000000..46f253e
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifParser.java
@@ -0,0 +1,920 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.util.Log;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+/**
+ * This class provides a low-level EXIF parsing API. Given a JPEG format
+ * InputStream, the caller can request which IFD's to read via
+ * {@link #parse(java.io.InputStream, int)} with given options.
+ * <p>
+ * Below is an example of getting EXIF data from IFD 0 and EXIF IFD using the
+ * parser.
+ *
+ * <pre>
+ * void parse() {
+ *     ExifParser parser = ExifParser.parse(mImageInputStream,
+ *             ExifParser.OPTION_IFD_0 | ExifParser.OPTIONS_IFD_EXIF);
+ *     int event = parser.next();
+ *     while (event != ExifParser.EVENT_END) {
+ *         switch (event) {
+ *             case ExifParser.EVENT_START_OF_IFD:
+ *                 break;
+ *             case ExifParser.EVENT_NEW_TAG:
+ *                 ExifTag tag = parser.getTag();
+ *                 if (!tag.hasValue()) {
+ *                     parser.registerForTagValue(tag);
+ *                 } else {
+ *                     processTag(tag);
+ *                 }
+ *                 break;
+ *             case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG:
+ *                 tag = parser.getTag();
+ *                 if (tag.getDataType() != ExifTag.TYPE_UNDEFINED) {
+ *                     processTag(tag);
+ *                 }
+ *                 break;
+ *         }
+ *         event = parser.next();
+ *     }
+ * }
+ *
+ * void processTag(ExifTag tag) {
+ *     // process the tag as you like.
+ * }
+ * </pre>
+ */
+public class ExifParser {
+    private static final boolean LOGV = false;
+    private static final String TAG = LogUtil.BUGLE_TAG;
+    /**
+     * When the parser reaches a new IFD area. Call {@link #getCurrentIfd()} to
+     * know which IFD we are in.
+     */
+    public static final int EVENT_START_OF_IFD = 0;
+    /**
+     * When the parser reaches a new tag. Call {@link #getTag()}to get the
+     * corresponding tag.
+     */
+    public static final int EVENT_NEW_TAG = 1;
+    /**
+     * When the parser reaches the value area of tag that is registered by
+     * {@link #registerForTagValue(ExifTag)} previously. Call {@link #getTag()}
+     * to get the corresponding tag.
+     */
+    public static final int EVENT_VALUE_OF_REGISTERED_TAG = 2;
+
+    /**
+     * When the parser reaches the compressed image area.
+     */
+    public static final int EVENT_COMPRESSED_IMAGE = 3;
+    /**
+     * When the parser reaches the uncompressed image strip. Call
+     * {@link #getStripIndex()} to get the index of the strip.
+     *
+     * @see #getStripIndex()
+     * @see #getStripCount()
+     */
+    public static final int EVENT_UNCOMPRESSED_STRIP = 4;
+    /**
+     * When there is nothing more to parse.
+     */
+    public static final int EVENT_END = 5;
+
+    /**
+     * Option bit to request to parse IFD0.
+     */
+    public static final int OPTION_IFD_0 = 1 << 0;
+    /**
+     * Option bit to request to parse IFD1.
+     */
+    public static final int OPTION_IFD_1 = 1 << 1;
+    /**
+     * Option bit to request to parse Exif-IFD.
+     */
+    public static final int OPTION_IFD_EXIF = 1 << 2;
+    /**
+     * Option bit to request to parse GPS-IFD.
+     */
+    public static final int OPTION_IFD_GPS = 1 << 3;
+    /**
+     * Option bit to request to parse Interoperability-IFD.
+     */
+    public static final int OPTION_IFD_INTEROPERABILITY = 1 << 4;
+    /**
+     * Option bit to request to parse thumbnail.
+     */
+    public static final int OPTION_THUMBNAIL = 1 << 5;
+
+    protected static final int EXIF_HEADER = 0x45786966; // EXIF header "Exif"
+    protected static final short EXIF_HEADER_TAIL = (short) 0x0000; // EXIF header in APP1
+
+    // TIFF header
+    protected static final short LITTLE_ENDIAN_TAG = (short) 0x4949; // "II"
+    protected static final short BIG_ENDIAN_TAG = (short) 0x4d4d; // "MM"
+    protected static final short TIFF_HEADER_TAIL = 0x002A;
+
+    protected static final int TAG_SIZE = 12;
+    protected static final int OFFSET_SIZE = 2;
+
+    private static final Charset US_ASCII = Charset.forName("US-ASCII");
+
+    protected static final int DEFAULT_IFD0_OFFSET = 8;
+
+    private final CountedDataInputStream mTiffStream;
+    private final int mOptions;
+    private int mIfdStartOffset = 0;
+    private int mNumOfTagInIfd = 0;
+    private int mIfdType;
+    private ExifTag mTag;
+    private ImageEvent mImageEvent;
+    private int mStripCount;
+    private ExifTag mStripSizeTag;
+    private ExifTag mJpegSizeTag;
+    private boolean mNeedToParseOffsetsInCurrentIfd;
+    private boolean mContainExifData = false;
+    private int mApp1End;
+    private int mOffsetToApp1EndFromSOF = 0;
+    private byte[] mDataAboveIfd0;
+    private int mIfd0Position;
+    private int mTiffStartPosition;
+    private final ExifInterface mInterface;
+
+    private static final short TAG_EXIF_IFD = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_EXIF_IFD);
+    private static final short TAG_GPS_IFD = ExifInterface.getTrueTagKey(ExifInterface.TAG_GPS_IFD);
+    private static final short TAG_INTEROPERABILITY_IFD = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_INTEROPERABILITY_IFD);
+    private static final short TAG_JPEG_INTERCHANGE_FORMAT = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT);
+    private static final short TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+    private static final short TAG_STRIP_OFFSETS = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS);
+    private static final short TAG_STRIP_BYTE_COUNTS = ExifInterface
+            .getTrueTagKey(ExifInterface.TAG_STRIP_BYTE_COUNTS);
+
+    private final TreeMap<Integer, Object> mCorrespondingEvent = new TreeMap<Integer, Object>();
+
+    private boolean isIfdRequested(int ifdType) {
+        switch (ifdType) {
+            case IfdId.TYPE_IFD_0:
+                return (mOptions & OPTION_IFD_0) != 0;
+            case IfdId.TYPE_IFD_1:
+                return (mOptions & OPTION_IFD_1) != 0;
+            case IfdId.TYPE_IFD_EXIF:
+                return (mOptions & OPTION_IFD_EXIF) != 0;
+            case IfdId.TYPE_IFD_GPS:
+                return (mOptions & OPTION_IFD_GPS) != 0;
+            case IfdId.TYPE_IFD_INTEROPERABILITY:
+                return (mOptions & OPTION_IFD_INTEROPERABILITY) != 0;
+        }
+        return false;
+    }
+
+    private boolean isThumbnailRequested() {
+        return (mOptions & OPTION_THUMBNAIL) != 0;
+    }
+
+    private ExifParser(InputStream inputStream, int options, ExifInterface iRef)
+            throws IOException, ExifInvalidFormatException {
+        if (inputStream == null) {
+            throw new IOException("Null argument inputStream to ExifParser");
+        }
+        if (LOGV) {
+            Log.v(TAG, "Reading exif...");
+        }
+        mInterface = iRef;
+        mContainExifData = seekTiffData(inputStream);
+        mTiffStream = new CountedDataInputStream(inputStream);
+        mOptions = options;
+        if (!mContainExifData) {
+            return;
+        }
+
+        parseTiffHeader();
+        long offset = mTiffStream.readUnsignedInt();
+        if (offset > Integer.MAX_VALUE) {
+            throw new ExifInvalidFormatException("Invalid offset " + offset);
+        }
+        mIfd0Position = (int) offset;
+        mIfdType = IfdId.TYPE_IFD_0;
+        if (isIfdRequested(IfdId.TYPE_IFD_0) || needToParseOffsetsInCurrentIfd()) {
+            registerIfd(IfdId.TYPE_IFD_0, offset);
+            if (mIfd0Position > DEFAULT_IFD0_OFFSET) {
+                mDataAboveIfd0 = new byte[mIfd0Position - DEFAULT_IFD0_OFFSET];
+                read(mDataAboveIfd0);
+            }
+        }
+    }
+
+    /**
+     * Parses the the given InputStream with the given options
+     *
+     * @exception java.io.IOException
+     * @exception ExifInvalidFormatException
+     */
+    protected static ExifParser parse(InputStream inputStream, int options, ExifInterface iRef)
+            throws IOException, ExifInvalidFormatException {
+        return new ExifParser(inputStream, options, iRef);
+    }
+
+    /**
+     * Parses the the given InputStream with default options; that is, every IFD
+     * and thumbnaill will be parsed.
+     *
+     * @exception java.io.IOException
+     * @exception ExifInvalidFormatException
+     * @see #parse(java.io.InputStream, int)
+     */
+    protected static ExifParser parse(InputStream inputStream, ExifInterface iRef)
+            throws IOException, ExifInvalidFormatException {
+        return new ExifParser(inputStream, OPTION_IFD_0 | OPTION_IFD_1
+                | OPTION_IFD_EXIF | OPTION_IFD_GPS | OPTION_IFD_INTEROPERABILITY
+                | OPTION_THUMBNAIL, iRef);
+    }
+
+    /**
+     * Moves the parser forward and returns the next parsing event
+     *
+     * @exception java.io.IOException
+     * @exception ExifInvalidFormatException
+     * @see #EVENT_START_OF_IFD
+     * @see #EVENT_NEW_TAG
+     * @see #EVENT_VALUE_OF_REGISTERED_TAG
+     * @see #EVENT_COMPRESSED_IMAGE
+     * @see #EVENT_UNCOMPRESSED_STRIP
+     * @see #EVENT_END
+     */
+    protected int next() throws IOException, ExifInvalidFormatException {
+        if (!mContainExifData) {
+            return EVENT_END;
+        }
+        int offset = mTiffStream.getReadByteCount();
+        int endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * mNumOfTagInIfd;
+        if (offset < endOfTags) {
+            mTag = readTag();
+            if (mTag == null) {
+                return next();
+            }
+            if (mNeedToParseOffsetsInCurrentIfd) {
+                checkOffsetOrImageTag(mTag);
+            }
+            return EVENT_NEW_TAG;
+        } else if (offset == endOfTags) {
+            // There is a link to ifd1 at the end of ifd0
+            if (mIfdType == IfdId.TYPE_IFD_0) {
+                long ifdOffset = readUnsignedLong();
+                if (isIfdRequested(IfdId.TYPE_IFD_1) || isThumbnailRequested()) {
+                    if (ifdOffset != 0) {
+                        registerIfd(IfdId.TYPE_IFD_1, ifdOffset);
+                    }
+                }
+            } else {
+                int offsetSize = 4;
+                // Some camera models use invalid length of the offset
+                if (mCorrespondingEvent.size() > 0) {
+                    offsetSize = mCorrespondingEvent.firstEntry().getKey() -
+                            mTiffStream.getReadByteCount();
+                }
+                if (offsetSize < 4) {
+                    Log.w(TAG, "Invalid size of link to next IFD: " + offsetSize);
+                } else {
+                    long ifdOffset = readUnsignedLong();
+                    if (ifdOffset != 0) {
+                        Log.w(TAG, "Invalid link to next IFD: " + ifdOffset);
+                    }
+                }
+            }
+        }
+        while (mCorrespondingEvent.size() != 0) {
+            Entry<Integer, Object> entry = mCorrespondingEvent.pollFirstEntry();
+            Object event = entry.getValue();
+            try {
+                skipTo(entry.getKey());
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to skip to data at: " + entry.getKey() +
+                        " for " + event.getClass().getName() + ", the file may be broken.");
+                continue;
+            }
+            if (event instanceof IfdEvent) {
+                mIfdType = ((IfdEvent) event).ifd;
+                mNumOfTagInIfd = mTiffStream.readUnsignedShort();
+                mIfdStartOffset = entry.getKey();
+
+                if (mNumOfTagInIfd * TAG_SIZE + mIfdStartOffset + OFFSET_SIZE > mApp1End) {
+                    Log.w(TAG, "Invalid size of IFD " + mIfdType);
+                    return EVENT_END;
+                }
+
+                mNeedToParseOffsetsInCurrentIfd = needToParseOffsetsInCurrentIfd();
+                if (((IfdEvent) event).isRequested) {
+                    return EVENT_START_OF_IFD;
+                } else {
+                    skipRemainingTagsInCurrentIfd();
+                }
+            } else if (event instanceof ImageEvent) {
+                mImageEvent = (ImageEvent) event;
+                return mImageEvent.type;
+            } else {
+                ExifTagEvent tagEvent = (ExifTagEvent) event;
+                mTag = tagEvent.tag;
+                if (mTag.getDataType() != ExifTag.TYPE_UNDEFINED) {
+                    readFullTagValue(mTag);
+                    checkOffsetOrImageTag(mTag);
+                }
+                if (tagEvent.isRequested) {
+                    return EVENT_VALUE_OF_REGISTERED_TAG;
+                }
+            }
+        }
+        return EVENT_END;
+    }
+
+    /**
+     * Skips the tags area of current IFD, if the parser is not in the tag area,
+     * nothing will happen.
+     *
+     * @throws java.io.IOException
+     * @throws ExifInvalidFormatException
+     */
+    protected void skipRemainingTagsInCurrentIfd() throws IOException, ExifInvalidFormatException {
+        int endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * mNumOfTagInIfd;
+        int offset = mTiffStream.getReadByteCount();
+        if (offset > endOfTags) {
+            return;
+        }
+        if (mNeedToParseOffsetsInCurrentIfd) {
+            while (offset < endOfTags) {
+                mTag = readTag();
+                offset += TAG_SIZE;
+                if (mTag == null) {
+                    continue;
+                }
+                checkOffsetOrImageTag(mTag);
+            }
+        } else {
+            skipTo(endOfTags);
+        }
+        long ifdOffset = readUnsignedLong();
+        // For ifd0, there is a link to ifd1 in the end of all tags
+        if (mIfdType == IfdId.TYPE_IFD_0
+                && (isIfdRequested(IfdId.TYPE_IFD_1) || isThumbnailRequested())) {
+            if (ifdOffset > 0) {
+                registerIfd(IfdId.TYPE_IFD_1, ifdOffset);
+            }
+        }
+    }
+
+    private boolean needToParseOffsetsInCurrentIfd() {
+        switch (mIfdType) {
+            case IfdId.TYPE_IFD_0:
+                return isIfdRequested(IfdId.TYPE_IFD_EXIF) || isIfdRequested(IfdId.TYPE_IFD_GPS)
+                        || isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)
+                        || isIfdRequested(IfdId.TYPE_IFD_1);
+            case IfdId.TYPE_IFD_1:
+                return isThumbnailRequested();
+            case IfdId.TYPE_IFD_EXIF:
+                // The offset to interoperability IFD is located in Exif IFD
+                return isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY);
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * If {@link #next()} return {@link #EVENT_NEW_TAG} or
+     * {@link #EVENT_VALUE_OF_REGISTERED_TAG}, call this function to get the
+     * corresponding tag.
+     * <p>
+     * For {@link #EVENT_NEW_TAG}, the tag may not contain the value if the size
+     * of the value is greater than 4 bytes. One should call
+     * {@link ExifTag#hasValue()} to check if the tag contains value. If there
+     * is no value,call {@link #registerForTagValue(ExifTag)} to have the parser
+     * emit {@link #EVENT_VALUE_OF_REGISTERED_TAG} when it reaches the area
+     * pointed by the offset.
+     * <p>
+     * When {@link #EVENT_VALUE_OF_REGISTERED_TAG} is emitted, the value of the
+     * tag will have already been read except for tags of undefined type. For
+     * tags of undefined type, call one of the read methods to get the value.
+     *
+     * @see #registerForTagValue(ExifTag)
+     * @see #read(byte[])
+     * @see #read(byte[], int, int)
+     * @see #readLong()
+     * @see #readRational()
+     * @see #readString(int)
+     * @see #readString(int, java.nio.charset.Charset)
+     */
+    protected ExifTag getTag() {
+        return mTag;
+    }
+
+    /**
+     * Gets number of tags in the current IFD area.
+     */
+    protected int getTagCountInCurrentIfd() {
+        return mNumOfTagInIfd;
+    }
+
+    /**
+     * Gets the ID of current IFD.
+     *
+     * @see IfdId#TYPE_IFD_0
+     * @see IfdId#TYPE_IFD_1
+     * @see IfdId#TYPE_IFD_GPS
+     * @see IfdId#TYPE_IFD_INTEROPERABILITY
+     * @see IfdId#TYPE_IFD_EXIF
+     */
+    protected int getCurrentIfd() {
+        return mIfdType;
+    }
+
+    /**
+     * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, call this function to
+     * get the index of this strip.
+     *
+     * @see #getStripCount()
+     */
+    protected int getStripIndex() {
+        return mImageEvent.stripIndex;
+    }
+
+    /**
+     * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, call this function to
+     * get the number of strip data.
+     *
+     * @see #getStripIndex()
+     */
+    protected int getStripCount() {
+        return mStripCount;
+    }
+
+    /**
+     * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, call this function to
+     * get the strip size.
+     */
+    protected int getStripSize() {
+        if (mStripSizeTag == null) {
+            return 0;
+        }
+        return (int) mStripSizeTag.getValueAt(0);
+    }
+
+    /**
+     * When receiving {@link #EVENT_COMPRESSED_IMAGE}, call this function to get
+     * the image data size.
+     */
+    protected int getCompressedImageSize() {
+        if (mJpegSizeTag == null) {
+            return 0;
+        }
+        return (int) mJpegSizeTag.getValueAt(0);
+    }
+
+    private void skipTo(int offset) throws IOException {
+        mTiffStream.skipTo(offset);
+        while (!mCorrespondingEvent.isEmpty() && mCorrespondingEvent.firstKey() < offset) {
+            mCorrespondingEvent.pollFirstEntry();
+        }
+    }
+
+    /**
+     * When getting {@link #EVENT_NEW_TAG} in the tag area of IFD, the tag may
+     * not contain the value if the size of the value is greater than 4 bytes.
+     * When the value is not available here, call this method so that the parser
+     * will emit {@link #EVENT_VALUE_OF_REGISTERED_TAG} when it reaches the area
+     * where the value is located.
+     *
+     * @see #EVENT_VALUE_OF_REGISTERED_TAG
+     */
+    protected void registerForTagValue(ExifTag tag) {
+        if (tag.getOffset() >= mTiffStream.getReadByteCount()) {
+            mCorrespondingEvent.put(tag.getOffset(), new ExifTagEvent(tag, true));
+        }
+    }
+
+    private void registerIfd(int ifdType, long offset) {
+        // Cast unsigned int to int since the offset is always smaller
+        // than the size of APP1 (65536)
+        mCorrespondingEvent.put((int) offset, new IfdEvent(ifdType, isIfdRequested(ifdType)));
+    }
+
+    private void registerCompressedImage(long offset) {
+        mCorrespondingEvent.put((int) offset, new ImageEvent(EVENT_COMPRESSED_IMAGE));
+    }
+
+    private void registerUncompressedStrip(int stripIndex, long offset) {
+        mCorrespondingEvent.put((int) offset, new ImageEvent(EVENT_UNCOMPRESSED_STRIP
+                , stripIndex));
+    }
+
+    private ExifTag readTag() throws IOException, ExifInvalidFormatException {
+        short tagId = mTiffStream.readShort();
+        short dataFormat = mTiffStream.readShort();
+        long numOfComp = mTiffStream.readUnsignedInt();
+        if (numOfComp > Integer.MAX_VALUE) {
+            throw new ExifInvalidFormatException(
+                    "Number of component is larger then Integer.MAX_VALUE");
+        }
+        // Some invalid image file contains invalid data type. Ignore those tags
+        if (!ExifTag.isValidType(dataFormat)) {
+            Log.w(TAG, String.format("Tag %04x: Invalid data type %d", tagId, dataFormat));
+            mTiffStream.skip(4);
+            return null;
+        }
+        // TODO: handle numOfComp overflow
+        ExifTag tag = new ExifTag(tagId, dataFormat, (int) numOfComp, mIfdType,
+                ((int) numOfComp) != ExifTag.SIZE_UNDEFINED);
+        int dataSize = tag.getDataSize();
+        if (dataSize > 4) {
+            long offset = mTiffStream.readUnsignedInt();
+            if (offset > Integer.MAX_VALUE) {
+                throw new ExifInvalidFormatException(
+                        "offset is larger then Integer.MAX_VALUE");
+            }
+            // Some invalid images put some undefined data before IFD0.
+            // Read the data here.
+            if (mDataAboveIfd0 != null
+                    && offset < mIfd0Position
+                    && dataFormat == ExifTag.TYPE_UNDEFINED) {
+                byte[] buf = new byte[(int) numOfComp];
+                System.arraycopy(mDataAboveIfd0, (int) offset - DEFAULT_IFD0_OFFSET,
+                        buf, 0, (int) numOfComp);
+                tag.setValue(buf);
+            } else {
+                tag.setOffset((int) offset);
+            }
+        } else {
+            boolean defCount = tag.hasDefinedCount();
+            // Set defined count to 0 so we can add \0 to non-terminated strings
+            tag.setHasDefinedCount(false);
+            // Read value
+            readFullTagValue(tag);
+            tag.setHasDefinedCount(defCount);
+            mTiffStream.skip(4 - dataSize);
+            // Set the offset to the position of value.
+            tag.setOffset(mTiffStream.getReadByteCount() - 4);
+        }
+        return tag;
+    }
+
+    /**
+     * Check the tag, if the tag is one of the offset tag that points to the IFD
+     * or image the caller is interested in, register the IFD or image.
+     */
+    private void checkOffsetOrImageTag(ExifTag tag) {
+        // Some invalid formattd image contains tag with 0 size.
+        if (tag.getComponentCount() == 0) {
+            return;
+        }
+        short tid = tag.getTagId();
+        int ifd = tag.getIfd();
+        if (tid == TAG_EXIF_IFD && checkAllowed(ifd, ExifInterface.TAG_EXIF_IFD)) {
+            if (isIfdRequested(IfdId.TYPE_IFD_EXIF)
+                    || isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) {
+                registerIfd(IfdId.TYPE_IFD_EXIF, tag.getValueAt(0));
+            }
+        } else if (tid == TAG_GPS_IFD && checkAllowed(ifd, ExifInterface.TAG_GPS_IFD)) {
+            if (isIfdRequested(IfdId.TYPE_IFD_GPS)) {
+                registerIfd(IfdId.TYPE_IFD_GPS, tag.getValueAt(0));
+            }
+        } else if (tid == TAG_INTEROPERABILITY_IFD
+                && checkAllowed(ifd, ExifInterface.TAG_INTEROPERABILITY_IFD)) {
+            if (isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) {
+                registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getValueAt(0));
+            }
+        } else if (tid == TAG_JPEG_INTERCHANGE_FORMAT
+                && checkAllowed(ifd, ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT)) {
+            if (isThumbnailRequested()) {
+                registerCompressedImage(tag.getValueAt(0));
+            }
+        } else if (tid == TAG_JPEG_INTERCHANGE_FORMAT_LENGTH
+                && checkAllowed(ifd, ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH)) {
+            if (isThumbnailRequested()) {
+                mJpegSizeTag = tag;
+            }
+        } else if (tid == TAG_STRIP_OFFSETS && checkAllowed(ifd, ExifInterface.TAG_STRIP_OFFSETS)) {
+            if (isThumbnailRequested()) {
+                if (tag.hasValue()) {
+                    for (int i = 0; i < tag.getComponentCount(); i++) {
+                        if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) {
+                            registerUncompressedStrip(i, tag.getValueAt(i));
+                        } else {
+                            registerUncompressedStrip(i, tag.getValueAt(i));
+                        }
+                    }
+                } else {
+                    mCorrespondingEvent.put(tag.getOffset(), new ExifTagEvent(tag, false));
+                }
+            }
+        } else if (tid == TAG_STRIP_BYTE_COUNTS
+                && checkAllowed(ifd, ExifInterface.TAG_STRIP_BYTE_COUNTS)
+                && isThumbnailRequested() && tag.hasValue()) {
+            mStripSizeTag = tag;
+        }
+    }
+
+    private boolean checkAllowed(int ifd, int tagId) {
+        int info = mInterface.getTagInfo().get(tagId);
+        if (info == ExifInterface.DEFINITION_NULL) {
+            return false;
+        }
+        return ExifInterface.isIfdAllowed(info, ifd);
+    }
+
+    protected void readFullTagValue(ExifTag tag) throws IOException {
+        // Some invalid images contains tags with wrong size, check it here
+        short type = tag.getDataType();
+        if (type == ExifTag.TYPE_ASCII || type == ExifTag.TYPE_UNDEFINED ||
+                type == ExifTag.TYPE_UNSIGNED_BYTE) {
+            int size = tag.getComponentCount();
+            if (mCorrespondingEvent.size() > 0) {
+                if (mCorrespondingEvent.firstEntry().getKey() < mTiffStream.getReadByteCount()
+                        + size) {
+                    Object event = mCorrespondingEvent.firstEntry().getValue();
+                    if (event instanceof ImageEvent) {
+                        // Tag value overlaps thumbnail, ignore thumbnail.
+                        Log.w(TAG, "Thumbnail overlaps value for tag: \n" + tag.toString());
+                        Entry<Integer, Object> entry = mCorrespondingEvent.pollFirstEntry();
+                        Log.w(TAG, "Invalid thumbnail offset: " + entry.getKey());
+                    } else {
+                        // Tag value overlaps another tag, shorten count
+                        if (event instanceof IfdEvent) {
+                            Log.w(TAG, "Ifd " + ((IfdEvent) event).ifd
+                                    + " overlaps value for tag: \n" + tag.toString());
+                        } else if (event instanceof ExifTagEvent) {
+                            Log.w(TAG, "Tag value for tag: \n"
+                                    + ((ExifTagEvent) event).tag.toString()
+                                    + " overlaps value for tag: \n" + tag.toString());
+                        }
+                        size = mCorrespondingEvent.firstEntry().getKey()
+                                - mTiffStream.getReadByteCount();
+                        Log.w(TAG, "Invalid size of tag: \n" + tag.toString()
+                                + " setting count to: " + size);
+                        tag.forceSetComponentCount(size);
+                    }
+                }
+            }
+        }
+        switch (tag.getDataType()) {
+            case ExifTag.TYPE_UNSIGNED_BYTE:
+            case ExifTag.TYPE_UNDEFINED: {
+                byte buf[] = new byte[tag.getComponentCount()];
+                read(buf);
+                tag.setValue(buf);
+            }
+                break;
+            case ExifTag.TYPE_ASCII:
+                tag.setValue(readString(tag.getComponentCount()));
+                break;
+            case ExifTag.TYPE_UNSIGNED_LONG: {
+                long value[] = new long[tag.getComponentCount()];
+                for (int i = 0, n = value.length; i < n; i++) {
+                    value[i] = readUnsignedLong();
+                }
+                tag.setValue(value);
+            }
+                break;
+            case ExifTag.TYPE_UNSIGNED_RATIONAL: {
+                Rational value[] = new Rational[tag.getComponentCount()];
+                for (int i = 0, n = value.length; i < n; i++) {
+                    value[i] = readUnsignedRational();
+                }
+                tag.setValue(value);
+            }
+                break;
+            case ExifTag.TYPE_UNSIGNED_SHORT: {
+                int value[] = new int[tag.getComponentCount()];
+                for (int i = 0, n = value.length; i < n; i++) {
+                    value[i] = readUnsignedShort();
+                }
+                tag.setValue(value);
+            }
+                break;
+            case ExifTag.TYPE_LONG: {
+                int value[] = new int[tag.getComponentCount()];
+                for (int i = 0, n = value.length; i < n; i++) {
+                    value[i] = readLong();
+                }
+                tag.setValue(value);
+            }
+                break;
+            case ExifTag.TYPE_RATIONAL: {
+                Rational value[] = new Rational[tag.getComponentCount()];
+                for (int i = 0, n = value.length; i < n; i++) {
+                    value[i] = readRational();
+                }
+                tag.setValue(value);
+            }
+                break;
+        }
+        if (LOGV) {
+            Log.v(TAG, "\n" + tag.toString());
+        }
+    }
+
+    private void parseTiffHeader() throws IOException,
+            ExifInvalidFormatException {
+        short byteOrder = mTiffStream.readShort();
+        if (LITTLE_ENDIAN_TAG == byteOrder) {
+            mTiffStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+        } else if (BIG_ENDIAN_TAG == byteOrder) {
+            mTiffStream.setByteOrder(ByteOrder.BIG_ENDIAN);
+        } else {
+            throw new ExifInvalidFormatException("Invalid TIFF header");
+        }
+
+        if (mTiffStream.readShort() != TIFF_HEADER_TAIL) {
+            throw new ExifInvalidFormatException("Invalid TIFF header");
+        }
+    }
+
+    private boolean seekTiffData(InputStream inputStream) throws IOException,
+            ExifInvalidFormatException {
+        CountedDataInputStream dataStream = new CountedDataInputStream(inputStream);
+        if (dataStream.readShort() != JpegHeader.SOI) {
+            throw new ExifInvalidFormatException("Invalid JPEG format");
+        }
+
+        short marker = dataStream.readShort();
+        while (marker != JpegHeader.EOI
+                && !JpegHeader.isSofMarker(marker)) {
+            int length = dataStream.readUnsignedShort();
+            // Some invalid formatted image contains multiple APP1,
+            // try to find the one with Exif data.
+            if (marker == JpegHeader.APP1) {
+                int header = 0;
+                short headerTail = 0;
+                if (length >= 8) {
+                    header = dataStream.readInt();
+                    headerTail = dataStream.readShort();
+                    length -= 6;
+                    if (header == EXIF_HEADER && headerTail == EXIF_HEADER_TAIL) {
+                        mTiffStartPosition = dataStream.getReadByteCount();
+                        mApp1End = length;
+                        mOffsetToApp1EndFromSOF = mTiffStartPosition + mApp1End;
+                        return true;
+                    }
+                }
+            }
+            if (length < 2 || (length - 2) != dataStream.skip(length - 2)) {
+                Log.w(TAG, "Invalid JPEG format.");
+                return false;
+            }
+            marker = dataStream.readShort();
+        }
+        return false;
+    }
+
+    protected int getOffsetToExifEndFromSOF() {
+        return mOffsetToApp1EndFromSOF;
+    }
+
+    protected int getTiffStartPosition() {
+        return mTiffStartPosition;
+    }
+
+    /**
+     * Reads bytes from the InputStream.
+     */
+    protected int read(byte[] buffer, int offset, int length) throws IOException {
+        return mTiffStream.read(buffer, offset, length);
+    }
+
+    /**
+     * Equivalent to read(buffer, 0, buffer.length).
+     */
+    protected int read(byte[] buffer) throws IOException {
+        return mTiffStream.read(buffer);
+    }
+
+    /**
+     * Reads a String from the InputStream with US-ASCII charset. The parser
+     * will read n bytes and convert it to ascii string. This is used for
+     * reading values of type {@link ExifTag#TYPE_ASCII}.
+     */
+    protected String readString(int n) throws IOException {
+        return readString(n, US_ASCII);
+    }
+
+    /**
+     * Reads a String from the InputStream with the given charset. The parser
+     * will read n bytes and convert it to string. This is used for reading
+     * values of type {@link ExifTag#TYPE_ASCII}.
+     */
+    protected String readString(int n, Charset charset) throws IOException {
+        if (n > 0) {
+            return mTiffStream.readString(n, charset);
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Reads value of type {@link ExifTag#TYPE_UNSIGNED_SHORT} from the
+     * InputStream.
+     */
+    protected int readUnsignedShort() throws IOException {
+        return mTiffStream.readShort() & 0xffff;
+    }
+
+    /**
+     * Reads value of type {@link ExifTag#TYPE_UNSIGNED_LONG} from the
+     * InputStream.
+     */
+    protected long readUnsignedLong() throws IOException {
+        return readLong() & 0xffffffffL;
+    }
+
+    /**
+     * Reads value of type {@link ExifTag#TYPE_UNSIGNED_RATIONAL} from the
+     * InputStream.
+     */
+    protected Rational readUnsignedRational() throws IOException {
+        long nomi = readUnsignedLong();
+        long denomi = readUnsignedLong();
+        return new Rational(nomi, denomi);
+    }
+
+    /**
+     * Reads value of type {@link ExifTag#TYPE_LONG} from the InputStream.
+     */
+    protected int readLong() throws IOException {
+        return mTiffStream.readInt();
+    }
+
+    /**
+     * Reads value of type {@link ExifTag#TYPE_RATIONAL} from the InputStream.
+     */
+    protected Rational readRational() throws IOException {
+        int nomi = readLong();
+        int denomi = readLong();
+        return new Rational(nomi, denomi);
+    }
+
+    private static class ImageEvent {
+        int stripIndex;
+        int type;
+
+        ImageEvent(int type) {
+            this.stripIndex = 0;
+            this.type = type;
+        }
+
+        ImageEvent(int type, int stripIndex) {
+            this.type = type;
+            this.stripIndex = stripIndex;
+        }
+    }
+
+    private static class IfdEvent {
+        int ifd;
+        boolean isRequested;
+
+        IfdEvent(int ifd, boolean isInterestedIfd) {
+            this.ifd = ifd;
+            this.isRequested = isInterestedIfd;
+        }
+    }
+
+    private static class ExifTagEvent {
+        ExifTag tag;
+        boolean isRequested;
+
+        ExifTagEvent(ExifTag tag, boolean isRequireByUser) {
+            this.tag = tag;
+            this.isRequested = isRequireByUser;
+        }
+    }
+
+    /**
+     * Gets the byte order of the current InputStream.
+     */
+    protected ByteOrder getByteOrder() {
+        return mTiffStream.getByteOrder();
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifReader.java b/src/com/android/messaging/util/exif/ExifReader.java
new file mode 100644
index 0000000..eece48a
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifReader.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import android.util.Log;
+import com.android.messaging.util.LogUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class reads the EXIF header of a JPEG file and stores it in
+ * {@link ExifData}.
+ */
+class ExifReader {
+    private static final String TAG = LogUtil.BUGLE_TAG;
+
+    private final ExifInterface mInterface;
+
+    ExifReader(ExifInterface iRef) {
+        mInterface = iRef;
+    }
+
+    /**
+     * Parses the inputStream and and returns the EXIF data in an
+     * {@link ExifData}.
+     *
+     * @throws ExifInvalidFormatException
+     * @throws java.io.IOException
+     */
+    protected ExifData read(InputStream inputStream) throws ExifInvalidFormatException,
+            IOException {
+        ExifParser parser = ExifParser.parse(inputStream, mInterface);
+        ExifData exifData = new ExifData(parser.getByteOrder());
+        ExifTag tag = null;
+
+        int event = parser.next();
+        while (event != ExifParser.EVENT_END) {
+            switch (event) {
+                case ExifParser.EVENT_START_OF_IFD:
+                    exifData.addIfdData(new IfdData(parser.getCurrentIfd()));
+                    break;
+                case ExifParser.EVENT_NEW_TAG:
+                    tag = parser.getTag();
+                    if (!tag.hasValue()) {
+                        parser.registerForTagValue(tag);
+                    } else {
+                        exifData.getIfdData(tag.getIfd()).setTag(tag);
+                    }
+                    break;
+                case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG:
+                    tag = parser.getTag();
+                    if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) {
+                        parser.readFullTagValue(tag);
+                    }
+                    exifData.getIfdData(tag.getIfd()).setTag(tag);
+                    break;
+                case ExifParser.EVENT_COMPRESSED_IMAGE:
+                    byte buf[] = new byte[parser.getCompressedImageSize()];
+                    if (buf.length == parser.read(buf)) {
+                        exifData.setCompressedThumbnail(buf);
+                    } else {
+                        Log.w(TAG, "Failed to read the compressed thumbnail");
+                    }
+                    break;
+                case ExifParser.EVENT_UNCOMPRESSED_STRIP:
+                    buf = new byte[parser.getStripSize()];
+                    if (buf.length == parser.read(buf)) {
+                        exifData.setStripBytes(parser.getStripIndex(), buf);
+                    } else {
+                        Log.w(TAG, "Failed to read the strip bytes");
+                    }
+                    break;
+            }
+            event = parser.next();
+        }
+        return exifData;
+    }
+}
diff --git a/src/com/android/messaging/util/exif/ExifTag.java b/src/com/android/messaging/util/exif/ExifTag.java
new file mode 100644
index 0000000..da6f4ed
--- /dev/null
+++ b/src/com/android/messaging/util/exif/ExifTag.java
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * This class stores information of an EXIF tag. For more information about
+ * defined EXIF tags, please read the Jeita EXIF 2.2 standard. Tags should be
+ * instantiated using {@link ExifInterface#buildTag}.
+ *
+ * @see ExifInterface
+ */
+public class ExifTag {
+    /**
+     * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
+     */
+    public static final short TYPE_UNSIGNED_BYTE = 1;
+    /**
+     * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit
+     * ASCII code. The final byte is terminated with NULL.
+     */
+    public static final short TYPE_ASCII = 2;
+    /**
+     * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
+     */
+    public static final short TYPE_UNSIGNED_SHORT = 3;
+    /**
+     * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
+     */
+    public static final short TYPE_UNSIGNED_LONG = 4;
+    /**
+     * The RATIONAL type of EXIF standard. It consists of two LONGs. The first
+     * one is the numerator and the second one expresses the denominator.
+     */
+    public static final short TYPE_UNSIGNED_RATIONAL = 5;
+    /**
+     * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any
+     * value depending on the field definition.
+     */
+    public static final short TYPE_UNDEFINED = 7;
+    /**
+     * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
+     * (2's complement notation).
+     */
+    public static final short TYPE_LONG = 9;
+    /**
+     * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first
+     * one is the numerator and the second one is the denominator.
+     */
+    public static final short TYPE_RATIONAL = 10;
+
+    private static Charset US_ASCII = Charset.forName("US-ASCII");
+    private static final int TYPE_TO_SIZE_MAP[] = new int[11];
+    private static final int UNSIGNED_SHORT_MAX = 65535;
+    private static final long UNSIGNED_LONG_MAX = 4294967295L;
+    private static final long LONG_MAX = Integer.MAX_VALUE;
+    private static final long LONG_MIN = Integer.MIN_VALUE;
+
+    static {
+        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1;
+        TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1;
+        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2;
+        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4;
+        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8;
+        TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1;
+        TYPE_TO_SIZE_MAP[TYPE_LONG] = 4;
+        TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8;
+    }
+
+    static final int SIZE_UNDEFINED = 0;
+
+    // Exif TagId
+    private final short mTagId;
+    // Exif Tag Type
+    private final short mDataType;
+    // If tag has defined count
+    private boolean mHasDefinedDefaultComponentCount;
+    // Actual data count in tag (should be number of elements in value array)
+    private int mComponentCountActual;
+    // The ifd that this tag should be put in
+    private int mIfd;
+    // The value (array of elements of type Tag Type)
+    private Object mValue;
+    // Value offset in exif header.
+    private int mOffset;
+
+    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
+
+    /**
+     * Returns true if the given IFD is a valid IFD.
+     */
+    public static boolean isValidIfd(int ifdId) {
+        return ifdId == IfdId.TYPE_IFD_0 || ifdId == IfdId.TYPE_IFD_1
+                || ifdId == IfdId.TYPE_IFD_EXIF || ifdId == IfdId.TYPE_IFD_INTEROPERABILITY
+                || ifdId == IfdId.TYPE_IFD_GPS;
+    }
+
+    /**
+     * Returns true if a given type is a valid tag type.
+     */
+    public static boolean isValidType(short type) {
+        return type == TYPE_UNSIGNED_BYTE || type == TYPE_ASCII ||
+                type == TYPE_UNSIGNED_SHORT || type == TYPE_UNSIGNED_LONG ||
+                type == TYPE_UNSIGNED_RATIONAL || type == TYPE_UNDEFINED ||
+                type == TYPE_LONG || type == TYPE_RATIONAL;
+    }
+
+    // Use builtTag in ExifInterface instead of constructor.
+    ExifTag(short tagId, short type, int componentCount, int ifd,
+            boolean hasDefinedComponentCount) {
+        mTagId = tagId;
+        mDataType = type;
+        mComponentCountActual = componentCount;
+        mHasDefinedDefaultComponentCount = hasDefinedComponentCount;
+        mIfd = ifd;
+        mValue = null;
+    }
+
+    /**
+     * Gets the element size of the given data type in bytes.
+     *
+     * @see #TYPE_ASCII
+     * @see #TYPE_LONG
+     * @see #TYPE_RATIONAL
+     * @see #TYPE_UNDEFINED
+     * @see #TYPE_UNSIGNED_BYTE
+     * @see #TYPE_UNSIGNED_LONG
+     * @see #TYPE_UNSIGNED_RATIONAL
+     * @see #TYPE_UNSIGNED_SHORT
+     */
+    public static int getElementSize(short type) {
+        return TYPE_TO_SIZE_MAP[type];
+    }
+
+    /**
+     * Returns the ID of the IFD this tag belongs to.
+     *
+     * @see IfdId#TYPE_IFD_0
+     * @see IfdId#TYPE_IFD_1
+     * @see IfdId#TYPE_IFD_EXIF
+     * @see IfdId#TYPE_IFD_GPS
+     * @see IfdId#TYPE_IFD_INTEROPERABILITY
+     */
+    public int getIfd() {
+        return mIfd;
+    }
+
+    protected void setIfd(int ifdId) {
+        mIfd = ifdId;
+    }
+
+    /**
+     * Gets the TID of this tag.
+     */
+    public short getTagId() {
+        return mTagId;
+    }
+
+    /**
+     * Gets the data type of this tag
+     *
+     * @see #TYPE_ASCII
+     * @see #TYPE_LONG
+     * @see #TYPE_RATIONAL
+     * @see #TYPE_UNDEFINED
+     * @see #TYPE_UNSIGNED_BYTE
+     * @see #TYPE_UNSIGNED_LONG
+     * @see #TYPE_UNSIGNED_RATIONAL
+     * @see #TYPE_UNSIGNED_SHORT
+     */
+    public short getDataType() {
+        return mDataType;
+    }
+
+    /**
+     * Gets the total data size in bytes of the value of this tag.
+     */
+    public int getDataSize() {
+        return getComponentCount() * getElementSize(getDataType());
+    }
+
+    /**
+     * Gets the component count of this tag.
+     */
+
+    // TODO: fix integer overflows with this
+    public int getComponentCount() {
+        return mComponentCountActual;
+    }
+
+    /**
+     * Sets the component count of this tag. Call this function before
+     * setValue() if the length of value does not match the component count.
+     */
+    protected void forceSetComponentCount(int count) {
+        mComponentCountActual = count;
+    }
+
+    /**
+     * Returns true if this ExifTag contains value; otherwise, this tag will
+     * contain an offset value that is determined when the tag is written.
+     */
+    public boolean hasValue() {
+        return mValue != null;
+    }
+
+    /**
+     * Sets integer values into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_SHORT}. This method will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
+     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
+     * <li>The value overflows.</li>
+     * <li>The value.length does NOT match the component count in the definition
+     * for this tag.</li>
+     * </ul>
+     */
+    public boolean setValue(int[] value) {
+        if (checkBadComponentCount(value.length)) {
+            return false;
+        }
+        if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG &&
+                mDataType != TYPE_UNSIGNED_LONG) {
+            return false;
+        }
+        if (mDataType == TYPE_UNSIGNED_SHORT && checkOverflowForUnsignedShort(value)) {
+            return false;
+        } else if (mDataType == TYPE_UNSIGNED_LONG && checkOverflowForUnsignedLong(value)) {
+            return false;
+        }
+
+        long[] data = new long[value.length];
+        for (int i = 0; i < value.length; i++) {
+            data[i] = value[i];
+        }
+        mValue = data;
+        mComponentCountActual = value.length;
+        return true;
+    }
+
+    /**
+     * Sets integer value into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_SHORT}, or {@link #TYPE_LONG}. This method
+     * will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
+     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
+     * <li>The value overflows.</li>
+     * <li>The component count in the definition of this tag is not 1.</li>
+     * </ul>
+     */
+    public boolean setValue(int value) {
+        return setValue(new int[] {
+                value
+        });
+    }
+
+    /**
+     * Sets long values into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
+     * <li>The value overflows.</li>
+     * <li>The value.length does NOT match the component count in the definition
+     * for this tag.</li>
+     * </ul>
+     */
+    public boolean setValue(long[] value) {
+        if (checkBadComponentCount(value.length) || mDataType != TYPE_UNSIGNED_LONG) {
+            return false;
+        }
+        if (checkOverflowForUnsignedLong(value)) {
+            return false;
+        }
+        mValue = value;
+        mComponentCountActual = value.length;
+        return true;
+    }
+
+    /**
+     * Sets long values into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
+     * <li>The value overflows.</li>
+     * <li>The component count in the definition for this tag is not 1.</li>
+     * </ul>
+     */
+    public boolean setValue(long value) {
+        return setValue(new long[] {
+                value
+        });
+    }
+
+    /**
+     * Sets a string value into this tag. This method should be used for tags of
+     * type {@link #TYPE_ASCII}. The string is converted to an ASCII string.
+     * Characters that cannot be converted are replaced with '?'. The length of
+     * the string must be equal to either (component count -1) or (component
+     * count). The final byte will be set to the string null terminator '\0',
+     * overwriting the last character in the string if the value.length is equal
+     * to the component count. This method will fail if:
+     * <ul>
+     * <li>The data type is not {@link #TYPE_ASCII} or {@link #TYPE_UNDEFINED}.</li>
+     * <li>The length of the string is not equal to (component count -1) or
+     * (component count) in the definition for this tag.</li>
+     * </ul>
+     */
+    public boolean setValue(String value) {
+        if (mDataType != TYPE_ASCII && mDataType != TYPE_UNDEFINED) {
+            return false;
+        }
+
+        byte[] buf = value.getBytes(US_ASCII);
+        byte[] finalBuf = buf;
+        if (buf.length > 0) {
+            finalBuf = (buf[buf.length - 1] == 0 || mDataType == TYPE_UNDEFINED) ? buf : Arrays
+                .copyOf(buf, buf.length + 1);
+        } else if (mDataType == TYPE_ASCII && mComponentCountActual == 1) {
+            finalBuf = new byte[] { 0 };
+        }
+        int count = finalBuf.length;
+        if (checkBadComponentCount(count)) {
+            return false;
+        }
+        mComponentCountActual = count;
+        mValue = finalBuf;
+        return true;
+    }
+
+    /**
+     * Sets Rational values into this tag. This method should be used for tags
+     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
+     * method will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
+     * or {@link #TYPE_RATIONAL}.</li>
+     * <li>The value overflows.</li>
+     * <li>The value.length does NOT match the component count in the definition
+     * for this tag.</li>
+     * </ul>
+     *
+     * @see Rational
+     */
+    public boolean setValue(Rational[] value) {
+        if (checkBadComponentCount(value.length)) {
+            return false;
+        }
+        if (mDataType != TYPE_UNSIGNED_RATIONAL && mDataType != TYPE_RATIONAL) {
+            return false;
+        }
+        if (mDataType == TYPE_UNSIGNED_RATIONAL && checkOverflowForUnsignedRational(value)) {
+            return false;
+        } else if (mDataType == TYPE_RATIONAL && checkOverflowForRational(value)) {
+            return false;
+        }
+
+        mValue = value;
+        mComponentCountActual = value.length;
+        return true;
+    }
+
+    /**
+     * Sets a Rational value into this tag. This method should be used for tags
+     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
+     * method will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
+     * or {@link #TYPE_RATIONAL}.</li>
+     * <li>The value overflows.</li>
+     * <li>The component count in the definition for this tag is not 1.</li>
+     * </ul>
+     *
+     * @see Rational
+     */
+    public boolean setValue(Rational value) {
+        return setValue(new Rational[] {
+                value
+        });
+    }
+
+    /**
+     * Sets byte values into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
+     * will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
+     * {@link #TYPE_UNDEFINED} .</li>
+     * <li>The length does NOT match the component count in the definition for
+     * this tag.</li>
+     * </ul>
+     */
+    public boolean setValue(byte[] value, int offset, int length) {
+        if (checkBadComponentCount(length)) {
+            return false;
+        }
+        if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) {
+            return false;
+        }
+        mValue = new byte[length];
+        System.arraycopy(value, offset, mValue, 0, length);
+        mComponentCountActual = length;
+        return true;
+    }
+
+    /**
+     * Equivalent to setValue(value, 0, value.length).
+     */
+    public boolean setValue(byte[] value) {
+        return setValue(value, 0, value.length);
+    }
+
+    /**
+     * Sets byte value into this tag. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
+     * will fail if:
+     * <ul>
+     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
+     * {@link #TYPE_UNDEFINED} .</li>
+     * <li>The component count in the definition for this tag is not 1.</li>
+     * </ul>
+     */
+    public boolean setValue(byte value) {
+        return setValue(new byte[] {
+                value
+        });
+    }
+
+    /**
+     * Sets the value for this tag using an appropriate setValue method for the
+     * given object. This method will fail if:
+     * <ul>
+     * <li>The corresponding setValue method for the class of the object passed
+     * in would fail.</li>
+     * <li>There is no obvious way to cast the object passed in into an EXIF tag
+     * type.</li>
+     * </ul>
+     */
+    public boolean setValue(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj instanceof Short) {
+            return setValue(((Short) obj).shortValue() & 0x0ffff);
+        } else if (obj instanceof String) {
+            return setValue((String) obj);
+        } else if (obj instanceof int[]) {
+            return setValue((int[]) obj);
+        } else if (obj instanceof long[]) {
+            return setValue((long[]) obj);
+        } else if (obj instanceof Rational) {
+            return setValue((Rational) obj);
+        } else if (obj instanceof Rational[]) {
+            return setValue((Rational[]) obj);
+        } else if (obj instanceof byte[]) {
+            return setValue((byte[]) obj);
+        } else if (obj instanceof Integer) {
+            return setValue(((Integer) obj).intValue());
+        } else if (obj instanceof Long) {
+            return setValue(((Long) obj).longValue());
+        } else if (obj instanceof Byte) {
+            return setValue(((Byte) obj).byteValue());
+        } else if (obj instanceof Short[]) {
+            // Nulls in this array are treated as zeroes.
+            Short[] arr = (Short[]) obj;
+            int[] fin = new int[arr.length];
+            for (int i = 0; i < arr.length; i++) {
+                fin[i] = (arr[i] == null) ? 0 : arr[i].shortValue() & 0x0ffff;
+            }
+            return setValue(fin);
+        } else if (obj instanceof Integer[]) {
+            // Nulls in this array are treated as zeroes.
+            Integer[] arr = (Integer[]) obj;
+            int[] fin = new int[arr.length];
+            for (int i = 0; i < arr.length; i++) {
+                fin[i] = (arr[i] == null) ? 0 : arr[i].intValue();
+            }
+            return setValue(fin);
+        } else if (obj instanceof Long[]) {
+            // Nulls in this array are treated as zeroes.
+            Long[] arr = (Long[]) obj;
+            long[] fin = new long[arr.length];
+            for (int i = 0; i < arr.length; i++) {
+                fin[i] = (arr[i] == null) ? 0 : arr[i].longValue();
+            }
+            return setValue(fin);
+        } else if (obj instanceof Byte[]) {
+            // Nulls in this array are treated as zeroes.
+            Byte[] arr = (Byte[]) obj;
+            byte[] fin = new byte[arr.length];
+            for (int i = 0; i < arr.length; i++) {
+                fin[i] = (arr[i] == null) ? 0 : arr[i].byteValue();
+            }
+            return setValue(fin);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Sets a timestamp to this tag. The method converts the timestamp with the
+     * format of "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}. This
+     * method will fail if the data type is not {@link #TYPE_ASCII} or the
+     * component count of this tag is not 20 or undefined.
+     *
+     * @param time the number of milliseconds since Jan. 1, 1970 GMT
+     * @return true on success
+     */
+    public boolean setTimeValue(long time) {
+        // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe
+        synchronized (TIME_FORMAT) {
+            return setValue(TIME_FORMAT.format(new Date(time)));
+        }
+    }
+
+    /**
+     * Gets the value as a String. This method should be used for tags of type
+     * {@link #TYPE_ASCII}.
+     *
+     * @return the value as a String, or null if the tag's value does not exist
+     *         or cannot be converted to a String.
+     */
+    public String getValueAsString() {
+        if (mValue == null) {
+            return null;
+        } else if (mValue instanceof String) {
+            return (String) mValue;
+        } else if (mValue instanceof byte[]) {
+            return new String((byte[]) mValue, US_ASCII);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value as a String. This method should be used for tags of type
+     * {@link #TYPE_ASCII}.
+     *
+     * @param defaultValue the String to return if the tag's value does not
+     *            exist or cannot be converted to a String.
+     * @return the tag's value as a String, or the defaultValue.
+     */
+    public String getValueAsString(String defaultValue) {
+        String s = getValueAsString();
+        if (s == null) {
+            return defaultValue;
+        }
+        return s;
+    }
+
+    /**
+     * Gets the value as a byte array. This method should be used for tags of
+     * type {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
+     *
+     * @return the value as a byte array, or null if the tag's value does not
+     *         exist or cannot be converted to a byte array.
+     */
+    public byte[] getValueAsBytes() {
+        if (mValue instanceof byte[]) {
+            return (byte[]) mValue;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value as a byte. If there are more than 1 bytes in this value,
+     * gets the first byte. This method should be used for tags of type
+     * {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
+     *
+     * @param defaultValue the byte to return if tag's value does not exist or
+     *            cannot be converted to a byte.
+     * @return the tag's value as a byte, or the defaultValue.
+     */
+    public byte getValueAsByte(byte defaultValue) {
+        byte[] b = getValueAsBytes();
+        if (b == null || b.length < 1) {
+            return defaultValue;
+        }
+        return b[0];
+    }
+
+    /**
+     * Gets the value as an array of Rationals. This method should be used for
+     * tags of type {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
+     *
+     * @return the value as as an array of Rationals, or null if the tag's value
+     *         does not exist or cannot be converted to an array of Rationals.
+     */
+    public Rational[] getValueAsRationals() {
+        if (mValue instanceof Rational[]) {
+            return (Rational[]) mValue;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value as a Rational. If there are more than 1 Rationals in this
+     * value, gets the first one. This method should be used for tags of type
+     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
+     *
+     * @param defaultValue the Rational to return if tag's value does not exist
+     *            or cannot be converted to a Rational.
+     * @return the tag's value as a Rational, or the defaultValue.
+     */
+    public Rational getValueAsRational(Rational defaultValue) {
+        Rational[] r = getValueAsRationals();
+        if (r == null || r.length < 1) {
+            return defaultValue;
+        }
+        return r[0];
+    }
+
+    /**
+     * Gets the value as a Rational. If there are more than 1 Rationals in this
+     * value, gets the first one. This method should be used for tags of type
+     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
+     *
+     * @param defaultValue the numerator of the Rational to return if tag's
+     *            value does not exist or cannot be converted to a Rational (the
+     *            denominator will be 1).
+     * @return the tag's value as a Rational, or the defaultValue.
+     */
+    public Rational getValueAsRational(long defaultValue) {
+        Rational defaultVal = new Rational(defaultValue, 1);
+        return getValueAsRational(defaultVal);
+    }
+
+    /**
+     * Gets the value as an array of ints. This method should be used for tags
+     * of type {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
+     *
+     * @return the value as as an array of ints, or null if the tag's value does
+     *         not exist or cannot be converted to an array of ints.
+     */
+    public int[] getValueAsInts() {
+        if (mValue == null) {
+            return null;
+        } else if (mValue instanceof long[]) {
+            long[] val = (long[]) mValue;
+            int[] arr = new int[val.length];
+            for (int i = 0; i < val.length; i++) {
+                arr[i] = (int) val[i]; // Truncates
+            }
+            return arr;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value as an int. If there are more than 1 ints in this value,
+     * gets the first one. This method should be used for tags of type
+     * {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
+     *
+     * @param defaultValue the int to return if tag's value does not exist or
+     *            cannot be converted to an int.
+     * @return the tag's value as a int, or the defaultValue.
+     */
+    public int getValueAsInt(int defaultValue) {
+        int[] i = getValueAsInts();
+        if (i == null || i.length < 1) {
+            return defaultValue;
+        }
+        return i[0];
+    }
+
+    /**
+     * Gets the value as an array of longs. This method should be used for tags
+     * of type {@link #TYPE_UNSIGNED_LONG}.
+     *
+     * @return the value as as an array of longs, or null if the tag's value
+     *         does not exist or cannot be converted to an array of longs.
+     */
+    public long[] getValueAsLongs() {
+        if (mValue instanceof long[]) {
+            return (long[]) mValue;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value or null if none exists. If there are more than 1 longs in
+     * this value, gets the first one. This method should be used for tags of
+     * type {@link #TYPE_UNSIGNED_LONG}.
+     *
+     * @param defaultValue the long to return if tag's value does not exist or
+     *            cannot be converted to a long.
+     * @return the tag's value as a long, or the defaultValue.
+     */
+    public long getValueAsLong(long defaultValue) {
+        long[] l = getValueAsLongs();
+        if (l == null || l.length < 1) {
+            return defaultValue;
+        }
+        return l[0];
+    }
+
+    /**
+     * Gets the tag's value or null if none exists.
+     */
+    public Object getValue() {
+        return mValue;
+    }
+
+    /**
+     * Gets a long representation of the value.
+     *
+     * @param defaultValue value to return if there is no value or value is a
+     *            rational with a denominator of 0.
+     * @return the tag's value as a long, or defaultValue if no representation
+     *         exists.
+     */
+    public long forceGetValueAsLong(long defaultValue) {
+        long[] l = getValueAsLongs();
+        if (l != null && l.length >= 1) {
+            return l[0];
+        }
+        byte[] b = getValueAsBytes();
+        if (b != null && b.length >= 1) {
+            return b[0];
+        }
+        Rational[] r = getValueAsRationals();
+        if (r != null && r.length >= 1 && r[0].getDenominator() != 0) {
+            return (long) r[0].toDouble();
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets a string representation of the value.
+     */
+    public String forceGetValueAsString() {
+        if (mValue == null) {
+            return "";
+        } else if (mValue instanceof byte[]) {
+            if (mDataType == TYPE_ASCII) {
+                return new String((byte[]) mValue, US_ASCII);
+            } else {
+                return Arrays.toString((byte[]) mValue);
+            }
+        } else if (mValue instanceof long[]) {
+            if (((long[]) mValue).length == 1) {
+                return String.valueOf(((long[]) mValue)[0]);
+            } else {
+                return Arrays.toString((long[]) mValue);
+            }
+        } else if (mValue instanceof Object[]) {
+            if (((Object[]) mValue).length == 1) {
+                Object val = ((Object[]) mValue)[0];
+                if (val == null) {
+                    return "";
+                } else {
+                    return val.toString();
+                }
+            } else {
+                return Arrays.toString((Object[]) mValue);
+            }
+        } else {
+            return mValue.toString();
+        }
+    }
+
+    /**
+     * Gets the value for type {@link #TYPE_ASCII}, {@link #TYPE_LONG},
+     * {@link #TYPE_UNDEFINED}, {@link #TYPE_UNSIGNED_BYTE},
+     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_UNSIGNED_SHORT}. For
+     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}, call
+     * {@link #getRational(int)} instead.
+     *
+     * @exception IllegalArgumentException if the data type is
+     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
+     */
+    protected long getValueAt(int index) {
+        if (mValue instanceof long[]) {
+            return ((long[]) mValue)[index];
+        } else if (mValue instanceof byte[]) {
+            return ((byte[]) mValue)[index];
+        }
+        throw new IllegalArgumentException("Cannot get integer value from "
+                + convertTypeToString(mDataType));
+    }
+
+    /**
+     * Gets the {@link #TYPE_ASCII} data.
+     *
+     * @exception IllegalArgumentException If the type is NOT
+     *                {@link #TYPE_ASCII}.
+     */
+    protected String getString() {
+        if (mDataType != TYPE_ASCII) {
+            throw new IllegalArgumentException("Cannot get ASCII value from "
+                    + convertTypeToString(mDataType));
+        }
+        return new String((byte[]) mValue, US_ASCII);
+    }
+
+    /*
+     * Get the converted ascii byte. Used by ExifOutputStream.
+     */
+    protected byte[] getStringByte() {
+        return (byte[]) mValue;
+    }
+
+    /**
+     * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data.
+     *
+     * @exception IllegalArgumentException If the type is NOT
+     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
+     */
+    protected Rational getRational(int index) {
+        if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) {
+            throw new IllegalArgumentException("Cannot get RATIONAL value from "
+                    + convertTypeToString(mDataType));
+        }
+        return ((Rational[]) mValue)[index];
+    }
+
+    /**
+     * Equivalent to getBytes(buffer, 0, buffer.length).
+     */
+    protected void getBytes(byte[] buf) {
+        getBytes(buf, 0, buf.length);
+    }
+
+    /**
+     * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
+     *
+     * @param buf the byte array in which to store the bytes read.
+     * @param offset the initial position in buffer to store the bytes.
+     * @param length the maximum number of bytes to store in buffer. If length >
+     *            component count, only the valid bytes will be stored.
+     * @exception IllegalArgumentException If the type is NOT
+     *                {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
+     */
+    protected void getBytes(byte[] buf, int offset, int length) {
+        if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) {
+            throw new IllegalArgumentException("Cannot get BYTE value from "
+                    + convertTypeToString(mDataType));
+        }
+        System.arraycopy(mValue, 0, buf, offset,
+                (length > mComponentCountActual) ? mComponentCountActual : length);
+    }
+
+    /**
+     * Gets the offset of this tag. This is only valid if this data size > 4 and
+     * contains an offset to the location of the actual value.
+     */
+    protected int getOffset() {
+        return mOffset;
+    }
+
+    /**
+     * Sets the offset of this tag.
+     */
+    protected void setOffset(int offset) {
+        mOffset = offset;
+    }
+
+    protected void setHasDefinedCount(boolean d) {
+        mHasDefinedDefaultComponentCount = d;
+    }
+
+    protected boolean hasDefinedCount() {
+        return mHasDefinedDefaultComponentCount;
+    }
+
+    private boolean checkBadComponentCount(int count) {
+        if (mHasDefinedDefaultComponentCount && (mComponentCountActual != count)) {
+            return true;
+        }
+        return false;
+    }
+
+    private static String convertTypeToString(short type) {
+        switch (type) {
+            case TYPE_UNSIGNED_BYTE:
+                return "UNSIGNED_BYTE";
+            case TYPE_ASCII:
+                return "ASCII";
+            case TYPE_UNSIGNED_SHORT:
+                return "UNSIGNED_SHORT";
+            case TYPE_UNSIGNED_LONG:
+                return "UNSIGNED_LONG";
+            case TYPE_UNSIGNED_RATIONAL:
+                return "UNSIGNED_RATIONAL";
+            case TYPE_UNDEFINED:
+                return "UNDEFINED";
+            case TYPE_LONG:
+                return "LONG";
+            case TYPE_RATIONAL:
+                return "RATIONAL";
+            default:
+                return "";
+        }
+    }
+
+    private boolean checkOverflowForUnsignedShort(int[] value) {
+        for (int v : value) {
+            if (v > UNSIGNED_SHORT_MAX || v < 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkOverflowForUnsignedLong(long[] value) {
+        for (long v : value) {
+            if (v < 0 || v > UNSIGNED_LONG_MAX) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkOverflowForUnsignedLong(int[] value) {
+        for (int v : value) {
+            if (v < 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkOverflowForUnsignedRational(Rational[] value) {
+        for (Rational v : value) {
+            if (v.getNumerator() < 0 || v.getDenominator() < 0
+                    || v.getNumerator() > UNSIGNED_LONG_MAX
+                    || v.getDenominator() > UNSIGNED_LONG_MAX) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkOverflowForRational(Rational[] value) {
+        for (Rational v : value) {
+            if (v.getNumerator() < LONG_MIN || v.getDenominator() < LONG_MIN
+                    || v.getNumerator() > LONG_MAX
+                    || v.getDenominator() > LONG_MAX) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof ExifTag) {
+            ExifTag tag = (ExifTag) obj;
+            if (tag.mTagId != this.mTagId
+                    || tag.mComponentCountActual != this.mComponentCountActual
+                    || tag.mDataType != this.mDataType) {
+                return false;
+            }
+            if (mValue != null) {
+                if (tag.mValue == null) {
+                    return false;
+                } else if (mValue instanceof long[]) {
+                    if (!(tag.mValue instanceof long[])) {
+                        return false;
+                    }
+                    return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
+                } else if (mValue instanceof Rational[]) {
+                    if (!(tag.mValue instanceof Rational[])) {
+                        return false;
+                    }
+                    return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
+                } else if (mValue instanceof byte[]) {
+                    if (!(tag.mValue instanceof byte[])) {
+                        return false;
+                    }
+                    return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
+                } else {
+                    return mValue.equals(tag.mValue);
+                }
+            } else {
+                return tag.mValue == null;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("tag id: %04X\n", mTagId) + "ifd id: " + mIfd + "\ntype: "
+                + convertTypeToString(mDataType) + "\ncount: " + mComponentCountActual
+                + "\noffset: " + mOffset + "\nvalue: " + forceGetValueAsString() + "\n";
+    }
+
+}
diff --git a/src/com/android/messaging/util/exif/IfdData.java b/src/com/android/messaging/util/exif/IfdData.java
new file mode 100644
index 0000000..6b8c293
--- /dev/null
+++ b/src/com/android/messaging/util/exif/IfdData.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class stores all the tags in an IFD.
+ *
+ * @see ExifData
+ * @see ExifTag
+ */
+class IfdData {
+
+    private final int mIfdId;
+    private final Map<Short, ExifTag> mExifTags = new HashMap<Short, ExifTag>();
+    private int mOffsetToNextIfd = 0;
+    private static final int[] sIfds = {
+            IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_1, IfdId.TYPE_IFD_EXIF,
+            IfdId.TYPE_IFD_INTEROPERABILITY, IfdId.TYPE_IFD_GPS
+    };
+    /**
+     * Creates an IfdData with given IFD ID.
+     *
+     * @see IfdId#TYPE_IFD_0
+     * @see IfdId#TYPE_IFD_1
+     * @see IfdId#TYPE_IFD_EXIF
+     * @see IfdId#TYPE_IFD_GPS
+     * @see IfdId#TYPE_IFD_INTEROPERABILITY
+     */
+    IfdData(int ifdId) {
+        mIfdId = ifdId;
+    }
+
+    protected static int[] getIfds() {
+        return sIfds;
+    }
+
+    /**
+     * Get a array the contains all {@link ExifTag} in this IFD.
+     */
+    protected ExifTag[] getAllTags() {
+        return mExifTags.values().toArray(new ExifTag[mExifTags.size()]);
+    }
+
+    /**
+     * Gets the ID of this IFD.
+     *
+     * @see IfdId#TYPE_IFD_0
+     * @see IfdId#TYPE_IFD_1
+     * @see IfdId#TYPE_IFD_EXIF
+     * @see IfdId#TYPE_IFD_GPS
+     * @see IfdId#TYPE_IFD_INTEROPERABILITY
+     */
+    protected int getId() {
+        return mIfdId;
+    }
+
+    /**
+     * Gets the {@link ExifTag} with given tag id. Return null if there is no
+     * such tag.
+     */
+    protected ExifTag getTag(short tagId) {
+        return mExifTags.get(tagId);
+    }
+
+    /**
+     * Adds or replaces a {@link ExifTag}.
+     */
+    protected ExifTag setTag(ExifTag tag) {
+        tag.setIfd(mIfdId);
+        return mExifTags.put(tag.getTagId(), tag);
+    }
+
+    protected boolean checkCollision(short tagId) {
+        return mExifTags.get(tagId) != null;
+    }
+
+    /**
+     * Removes the tag of the given ID
+     */
+    protected void removeTag(short tagId) {
+        mExifTags.remove(tagId);
+    }
+
+    /**
+     * Gets the tags count in the IFD.
+     */
+    protected int getTagCount() {
+        return mExifTags.size();
+    }
+
+    /**
+     * Sets the offset of next IFD.
+     */
+    protected void setOffsetToNextIfd(int offset) {
+        mOffsetToNextIfd = offset;
+    }
+
+    /**
+     * Gets the offset of next IFD.
+     */
+    protected int getOffsetToNextIfd() {
+        return mOffsetToNextIfd;
+    }
+
+    /**
+     * Returns true if all tags in this two IFDs are equal. Note that tags of
+     * IFDs offset or thumbnail offset will be ignored.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof IfdData) {
+            IfdData data = (IfdData) obj;
+            if (data.getId() == mIfdId && data.getTagCount() == getTagCount()) {
+                ExifTag[] tags = data.getAllTags();
+                for (ExifTag tag : tags) {
+                    if (ExifInterface.isOffsetTag(tag.getTagId())) {
+                        continue;
+                    }
+                    ExifTag tag2 = mExifTags.get(tag.getTagId());
+                    if (!tag.equals(tag2)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/messaging/util/exif/IfdId.java b/src/com/android/messaging/util/exif/IfdId.java
new file mode 100644
index 0000000..06a820d
--- /dev/null
+++ b/src/com/android/messaging/util/exif/IfdId.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+/**
+ * The constants of the IFD ID defined in EXIF spec.
+ */
+public interface IfdId {
+    public static final int TYPE_IFD_0 = 0;
+    public static final int TYPE_IFD_1 = 1;
+    public static final int TYPE_IFD_EXIF = 2;
+    public static final int TYPE_IFD_INTEROPERABILITY = 3;
+    public static final int TYPE_IFD_GPS = 4;
+    /* This is used in ExifData to allocate enough IfdData */
+    static final int TYPE_IFD_COUNT = 5;
+
+}
diff --git a/src/com/android/messaging/util/exif/JpegHeader.java b/src/com/android/messaging/util/exif/JpegHeader.java
new file mode 100644
index 0000000..1dd12a5
--- /dev/null
+++ b/src/com/android/messaging/util/exif/JpegHeader.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+class JpegHeader {
+    public static final short SOI =  (short) 0xFFD8;
+    public static final short APP1 = (short) 0xFFE1;
+    public static final short APP0 = (short) 0xFFE0;
+    public static final short EOI = (short) 0xFFD9;
+
+    /**
+     *  SOF (start of frame). All value between SOF0 and SOF15 is SOF marker except for DHT, JPG,
+     *  and DAC marker.
+     */
+    public static final short SOF0 = (short) 0xFFC0;
+    public static final short SOF15 = (short) 0xFFCF;
+    public static final short DHT = (short) 0xFFC4;
+    public static final short JPG = (short) 0xFFC8;
+    public static final short DAC = (short) 0xFFCC;
+
+    public static final boolean isSofMarker(short marker) {
+        return marker >= SOF0 && marker <= SOF15 && marker != DHT && marker != JPG
+                && marker != DAC;
+    }
+}
diff --git a/src/com/android/messaging/util/exif/OrderedDataOutputStream.java b/src/com/android/messaging/util/exif/OrderedDataOutputStream.java
new file mode 100644
index 0000000..cf64805
--- /dev/null
+++ b/src/com/android/messaging/util/exif/OrderedDataOutputStream.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+class OrderedDataOutputStream extends FilterOutputStream {
+    private final ByteBuffer mByteBuffer = ByteBuffer.allocate(4);
+
+    public OrderedDataOutputStream(OutputStream out) {
+        super(out);
+    }
+
+    public OrderedDataOutputStream setByteOrder(ByteOrder order) {
+        mByteBuffer.order(order);
+        return this;
+    }
+
+    public OrderedDataOutputStream writeShort(short value) throws IOException {
+        mByteBuffer.rewind();
+        mByteBuffer.putShort(value);
+        out.write(mByteBuffer.array(), 0, 2);
+        return this;
+    }
+
+    public OrderedDataOutputStream writeInt(int value) throws IOException {
+        mByteBuffer.rewind();
+        mByteBuffer.putInt(value);
+        out.write(mByteBuffer.array());
+        return this;
+    }
+
+    public OrderedDataOutputStream writeRational(Rational rational) throws IOException {
+        writeInt((int) rational.getNumerator());
+        writeInt((int) rational.getDenominator());
+        return this;
+    }
+}
diff --git a/src/com/android/messaging/util/exif/Rational.java b/src/com/android/messaging/util/exif/Rational.java
new file mode 100644
index 0000000..b42ceb7
--- /dev/null
+++ b/src/com/android/messaging/util/exif/Rational.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util.exif;
+
+/**
+ * The rational data type of EXIF tag. Contains a pair of longs representing the
+ * numerator and denominator of a Rational number.
+ */
+public class Rational {
+
+    private final long mNumerator;
+    private final long mDenominator;
+
+    /**
+     * Create a Rational with a given numerator and denominator.
+     *
+     * @param nominator
+     * @param denominator
+     */
+    public Rational(long nominator, long denominator) {
+        mNumerator = nominator;
+        mDenominator = denominator;
+    }
+
+    /**
+     * Create a copy of a Rational.
+     */
+    public Rational(Rational r) {
+        mNumerator = r.mNumerator;
+        mDenominator = r.mDenominator;
+    }
+
+    /**
+     * Gets the numerator of the rational.
+     */
+    public long getNumerator() {
+        return mNumerator;
+    }
+
+    /**
+     * Gets the denominator of the rational
+     */
+    public long getDenominator() {
+        return mDenominator;
+    }
+
+    /**
+     * Gets the rational value as type double. Will cause a divide-by-zero error
+     * if the denominator is 0.
+     */
+    public double toDouble() {
+        return mNumerator / (double) mDenominator;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Rational) {
+            Rational data = (Rational) obj;
+            return mNumerator == data.mNumerator && mDenominator == data.mDenominator;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return mNumerator + "/" + mDenominator;
+    }
+}
diff --git a/src/com/android/messaging/widget/BaseWidgetFactory.java b/src/com/android/messaging/widget/BaseWidgetFactory.java
new file mode 100644
index 0000000..30b80ae
--- /dev/null
+++ b/src/com/android/messaging/widget/BaseWidgetFactory.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.Binder;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.media.AvatarGroupRequestDescriptor;
+import com.android.messaging.datamodel.media.AvatarRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageRequestDescriptor;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.LogUtil;
+
+/**
+ * Remote Views Factory for Bugle Widget.
+ */
+abstract class BaseWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
+    protected static final String TAG = LogUtil.BUGLE_WIDGET_TAG;
+
+    protected static final int MAX_ITEMS_TO_SHOW = 25;
+
+    /**
+     * Lock to avoid race condition between widgets.
+     */
+    protected static final Object sWidgetLock = new Object();
+
+    protected final Context mContext;
+    protected final int mAppWidgetId;
+    protected boolean mShouldShowViewMore;
+    protected Cursor mCursor;
+    protected final AppWidgetManager mAppWidgetManager;
+    protected int mIconSize;
+    protected ImageResource mAvatarResource;
+
+    public BaseWidgetFactory(Context context, Intent intent) {
+        mContext = context;
+        mAppWidgetId = intent.getIntExtra(
+                AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
+        mAppWidgetManager = AppWidgetManager.getInstance(context);
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BaseWidgetFactory intent: " + intent + "widget id: " + mAppWidgetId);
+        }
+        mIconSize = (int) context.getResources()
+                .getDimension(R.dimen.contact_icon_view_normal_size);
+
+    }
+
+    @Override
+    public void onCreate() {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onCreate");
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onDestroy");
+        }
+        synchronized (sWidgetLock) {
+            if (mCursor != null && !mCursor.isClosed()) {
+                mCursor.close();
+                mCursor = null;
+            }
+        }
+    }
+
+    @Override
+    public void onDataSetChanged() {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onDataSetChanged");
+        }
+        synchronized (sWidgetLock) {
+            if (mCursor != null) {
+                mCursor.close();
+                mCursor = null;
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mCursor = doQuery();
+                onLoadComplete();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    }
+
+    protected abstract Cursor doQuery();
+
+    /**
+     * Returns the number of items that should be shown in the widget list.  This method also
+     * updates the boolean that indicates whether the "show more" item should be shown.
+     * @return the number of items to be displayed in the list.
+     */
+    @Override
+    public int getCount() {
+        synchronized (sWidgetLock) {
+            if (mCursor == null) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "getCount: 0");
+                }
+                return 0;
+            }
+            final int count = getItemCount();
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "getCount: " + count);
+            }
+            mShouldShowViewMore = count < mCursor.getCount();
+            return count + (mShouldShowViewMore ? 1 : 0);
+        }
+    }
+
+    /**
+     * Returns the number of messages that should be shown in the widget.  This method
+     * doesn't update the boolean that indicates whether the "show more" item should be included
+     * in the list.
+     * @return
+     */
+    protected int getItemCount() {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "getItemCount: " + mCursor.getCount());
+        }
+        return Math.min(mCursor.getCount(), MAX_ITEMS_TO_SHOW);
+    }
+
+    /*
+     * Make the given text bold if the item is unread
+     */
+    protected CharSequence boldifyIfUnread(CharSequence text, final boolean unread) {
+        if (!unread) {
+            return text;
+        }
+        final SpannableStringBuilder builder = new SpannableStringBuilder(text);
+        builder.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(),
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return builder;
+    }
+
+    protected Bitmap getAvatarBitmap(final Uri avatarUri) {
+        final String avatarType = avatarUri == null ?
+                null : AvatarUriUtil.getAvatarType(avatarUri);
+        ImageRequestDescriptor descriptor;
+        if (AvatarUriUtil.TYPE_GROUP_URI.equals(avatarType)) {
+            descriptor = new AvatarGroupRequestDescriptor(avatarUri, mIconSize, mIconSize);
+        } else {
+            descriptor = new AvatarRequestDescriptor(avatarUri, mIconSize, mIconSize);
+        }
+
+        final MediaRequest<ImageResource> imageRequest =
+                descriptor.buildSyncMediaRequest(mContext);
+        final ImageResource imageResource =
+                MediaResourceManager.get().requestMediaResourceSync(imageRequest);
+        if (imageResource != null) {
+            setAvatarResource(imageResource);
+            return mAvatarResource.getBitmap();
+        } else {
+            releaseAvatarResource();
+            return null;
+        }
+    }
+
+    /**
+     * @return the "View more messages" view. When the user taps this item, they're
+     * taken to the conversation in Bugle.
+     */
+    abstract protected RemoteViews getViewMoreItemsView();
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    private void onLoadComplete() {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onLoadComplete");
+        }
+        final RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(),
+                getMainLayoutId());
+        mAppWidgetManager.partiallyUpdateAppWidget(mAppWidgetId, remoteViews);
+    }
+
+    protected abstract int getMainLayoutId();
+
+    private void setAvatarResource(final ImageResource resource) {
+        if (mAvatarResource != resource) {
+            // Clear out any information for what is currently used
+            releaseAvatarResource();
+            mAvatarResource = resource;
+        }
+    }
+
+    private void releaseAvatarResource() {
+        if (mAvatarResource != null) {
+            mAvatarResource.release();
+        }
+        mAvatarResource = null;
+    }
+}
diff --git a/src/com/android/messaging/widget/BaseWidgetProvider.java b/src/com/android/messaging/widget/BaseWidgetProvider.java
new file mode 100644
index 0000000..6632c5f
--- /dev/null
+++ b/src/com/android/messaging/widget/BaseWidgetProvider.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+
+import com.android.messaging.util.LogUtil;
+
+public abstract class BaseWidgetProvider extends AppWidgetProvider {
+    protected static final String TAG = LogUtil.BUGLE_WIDGET_TAG;
+
+    public static final int WIDGET_CONVERSATION_REQUEST_CODE = 987;
+
+    static final String WIDGET_SIZE_KEY = "widgetSizeKey";
+
+    public static final int SIZE_LARGE  = 0;    // undefined == 0, which is the default, large
+    public static final int SIZE_SMALL  = 1;
+    public static final int SIZE_MEDIUM = 2;
+    public static final int SIZE_PRE_JB = 3;
+
+    /**
+     * Update all widgets in the list
+     */
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        super.onUpdate(context, appWidgetManager, appWidgetIds);
+
+        for (int i = 0; i < appWidgetIds.length; ++i) {
+            updateWidget(context, appWidgetIds[i]);
+        }
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onReceive intent: " + intent + " for " + this.getClass());
+        }
+        final String action = intent.getAction();
+
+        // The base class AppWidgetProvider's onReceive handles the normal widget intents. Here
+        // we're looking for an intent sent by our app when it knows a message has
+        // been sent or received (or a conversation has been read) and is telling the widget it
+        // needs to update.
+        if (getAction().equals(action)) {
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+            final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
+                    this.getClass()));
+
+            if (appWidgetIds.length > 0) {
+                // We need to update all Bugle app widgets on the home screen.
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "onReceive notifyAppWidgetViewDataChanged listId: " +
+                            getListId() + " first widgetId: " + appWidgetIds[0]);
+                }
+                appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, getListId());
+            }
+        } else {
+            super.onReceive(context, intent);
+        }
+    }
+
+    @Override
+    public void onEnabled(Context context) {
+        super.onEnabled(context);
+        context.getApplicationContext().registerReceiver(this, new IntentFilter(getAction()));
+    }
+
+    protected abstract String getAction();
+
+    protected abstract int getListId();
+
+    /**
+     * Update the widget appWidgetId
+     */
+    protected abstract void updateWidget(Context context, int appWidgetId);
+
+    private int getWidgetSize(AppWidgetManager appWidgetManager, int appWidgetId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize");
+        }
+
+        // Get the dimensions
+        final Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+
+        // Get min width and height.
+        final int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
+        final int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
+
+        // First find out rows and columns based on width provided.
+        final int rows = getCellsForSize(minHeight);
+        final int columns = getCellsForSize(minWidth);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize row: " + rows
+                    + " columns: " + columns);
+        }
+
+        int size = SIZE_MEDIUM;
+        if (rows == 1) {
+            size = SIZE_SMALL;  // Our widget doesn't let itself get this small. Perhaps in the
+                                // future will add a super-mini widget.
+        } else if (columns > 3) {
+            size = SIZE_LARGE;
+        }
+
+        // put the size in the bundle so our service know what size it's dealing with.
+        final int savedSize = options.getInt(WIDGET_SIZE_KEY);
+        if (savedSize != size) {
+            options.putInt(WIDGET_SIZE_KEY, size);
+            appWidgetManager.updateAppWidgetOptions(appWidgetId, options);
+
+            // The size changed. We have to force the widget to rebuild the list.
+            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, getListId());
+
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize old size: " + savedSize
+                                + " new size saved: " + size);
+            }
+        }
+
+        return size;
+    }
+
+    /**
+     * Returns number of cells needed for given size of the widget.
+     *
+     * @param size Widget size in dp.
+     * @return Size in number of cells.
+     */
+    private static int getCellsForSize(int size) {
+        // The hardwired sizes in this function come from the hardwired formula found in
+        // Android's UI guidelines for widget design:
+        // http://developer.android.com/guide/practices/ui_guidelines/widget_design.html
+        return (size + 30) / 70;
+    }
+
+    @Override
+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
+            int appWidgetId, Bundle newOptions) {
+
+        final int widgetSize = getWidgetSize(appWidgetManager, appWidgetId);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BaseWidgetProvider.onAppWidgetOptionsChanged new size: " +
+                    widgetSize);
+        }
+
+        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+    }
+
+    protected void deletePreferences(final int widgetId) {
+    }
+
+    /**
+     * Remove preferences when deleting widget
+     */
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds) {
+        super.onDeleted(context, appWidgetIds);
+
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BaseWidgetProvider.onDeleted");
+        }
+
+        for (final int widgetId : appWidgetIds) {
+            deletePreferences(widgetId);
+        }
+    }
+
+}
diff --git a/src/com/android/messaging/widget/BugleWidgetProvider.java b/src/com/android/messaging/widget/BugleWidgetProvider.java
new file mode 100644
index 0000000..50c97b6
--- /dev/null
+++ b/src/com/android/messaging/widget/BugleWidgetProvider.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.widget.RemoteViews;
+
+import com.android.messaging.R;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UiUtils;
+
+public class BugleWidgetProvider extends BaseWidgetProvider {
+    public static final String ACTION_NOTIFY_CONVERSATIONS_CHANGED =
+            "com.android.Bugle.intent.action.ACTION_NOTIFY_CONVERSATIONS_CHANGED";
+
+    public static final int WIDGET_NEW_CONVERSATION_REQUEST_CODE = 986;
+
+    /**
+     * Update the widget appWidgetId
+     */
+    @Override
+    protected void updateWidget(final Context context, final int appWidgetId) {
+        if (OsUtil.hasRequiredPermissions()) {
+            SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                @Override
+                public void run() {
+                    rebuildWidget(context, appWidgetId);
+                }
+            });
+        } else {
+            AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId,
+                    UiUtils.getWidgetMissingPermissionView(context));
+        }
+    }
+
+    @Override
+    protected String getAction() {
+        return ACTION_NOTIFY_CONVERSATIONS_CHANGED;
+    }
+
+    @Override
+    protected int getListId() {
+        return R.id.conversation_list;
+    }
+
+    public static void rebuildWidget(final Context context, final int appWidgetId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "BugleWidgetProvider.rebuildWidget appWidgetId: " + appWidgetId);
+        }
+        final RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
+                R.layout.widget_conversation_list);
+        PendingIntent clickIntent;
+
+        // Launch an intent to avoid ANRs
+        final Intent intent = new Intent(context, WidgetConversationListService.class);
+        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+        remoteViews.setRemoteAdapter(appWidgetId, R.id.conversation_list, intent);
+
+        remoteViews.setTextViewText(R.id.widget_label, context.getString(R.string.app_name));
+
+        // Open Bugle's app conversation list when click on header
+        clickIntent = UIIntents.get().getWidgetPendingIntentForConversationListActivity(context);
+        remoteViews.setOnClickPendingIntent(R.id.widget_header, clickIntent);
+
+        // On click intent for Compose
+        clickIntent = UIIntents.get().getWidgetPendingIntentForConversationActivity(context,
+                null /*conversationId*/, WIDGET_NEW_CONVERSATION_REQUEST_CODE);
+        remoteViews.setOnClickPendingIntent(R.id.widget_compose, clickIntent);
+
+        // On click intent for Conversation
+        // Note: the template intent has to be a "naked" intent without any extras. It turns out
+        // that if the template intent does have extras, those particular extras won't get
+        // replaced by the fill-in intent on each list item.
+        clickIntent = UIIntents.get().getWidgetPendingIntentForConversationActivity(context,
+                null /*conversationId*/, WIDGET_CONVERSATION_REQUEST_CODE);
+        remoteViews.setPendingIntentTemplate(R.id.conversation_list, clickIntent);
+
+        AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, remoteViews);
+    }
+
+    /*
+     * notifyDatasetChanged call when the conversation list changes so the Bugle widget will
+     * update and reflect the changes
+     */
+    public static void notifyConversationListChanged(final Context context) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "notifyConversationListChanged");
+        }
+        final Intent intent = new Intent(ACTION_NOTIFY_CONVERSATIONS_CHANGED);
+        context.sendBroadcast(intent);
+    }
+}
diff --git a/src/com/android/messaging/widget/WidgetConversationListService.java b/src/com/android/messaging/widget/WidgetConversationListService.java
new file mode 100644
index 0000000..b67bd79
--- /dev/null
+++ b/src/com/android/messaging/widget/WidgetConversationListService.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.conversationlist.ConversationListItemView;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+public class WidgetConversationListService extends RemoteViewsService {
+    private static final String TAG = LogUtil.BUGLE_WIDGET_TAG;
+
+    @Override
+    public RemoteViewsFactory onGetViewFactory(Intent intent) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onGetViewFactory intent: " + intent);
+        }
+        return new WidgetConversationListFactory(getApplicationContext(), intent);
+    }
+
+    /**
+     * Remote Views Factory for Bugle Widget.
+     */
+    private static class WidgetConversationListFactory extends BaseWidgetFactory {
+
+        public WidgetConversationListFactory(Context context, Intent intent) {
+            super(context, intent);
+        }
+
+        @Override
+        protected Cursor doQuery() {
+            return  mContext.getContentResolver().query(MessagingContentProvider.CONVERSATIONS_URI,
+                    ConversationListItemData.PROJECTION,
+                    ConversationListData.WHERE_NOT_ARCHIVED,
+                    null,       // selection args
+                    ConversationListData.SORT_ORDER);
+        }
+
+        /**
+         * @return the {@link RemoteViews} for a specific position in the list.
+         */
+        @Override
+        public RemoteViews getViewAt(int position) {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "getViewAt position: " + position);
+            }
+            synchronized (sWidgetLock) {
+                // "View more conversations" view.
+                if (mCursor == null
+                        || (mShouldShowViewMore && position >= getItemCount())) {
+                    return getViewMoreItemsView();
+                }
+
+                if (!mCursor.moveToPosition(position)) {
+                    // If we ever fail to move to a position, return the "View More conversations"
+                    // view.
+                    LogUtil.w(TAG, "Failed to move to position: " + position);
+                    return getViewMoreItemsView();
+                }
+
+                final ConversationListItemData conv = new ConversationListItemData();
+                conv.bind(mCursor);
+
+                // Inflate and fill out the remote view
+                final RemoteViews remoteViews = new RemoteViews(
+                        mContext.getPackageName(), R.layout.widget_conversation_list_item);
+
+                final boolean hasUnreadMessages = !conv.getIsRead();
+                final Resources resources = mContext.getResources();
+                final boolean isDefaultSmsApp = PhoneUtils.getDefault().isDefaultSmsApp();
+
+                final String timeStamp = conv.getIsSendRequested() ?
+                        resources.getString(R.string.message_status_sending) :
+                            Dates.getWidgetTimeString(conv.getTimestamp(), true /*abbreviated*/)
+                                .toString();
+                // Date/Timestamp or Sending or Error state -- all shown in the date item
+                remoteViews.setTextViewText(R.id.date,
+                        boldifyIfUnread(timeStamp, hasUnreadMessages));
+
+                // From
+                remoteViews.setTextViewText(R.id.from,
+                        boldifyIfUnread(conv.getName(), hasUnreadMessages));
+
+                // Notifications turned off mini-bell icon
+                remoteViews.setViewVisibility(R.id.conversation_notification_bell,
+                        conv.getNotificationEnabled() ? View.GONE : View.VISIBLE);
+
+                // On click intent.
+                final Intent intent = UIIntents.get().getIntentForConversationActivity(mContext,
+                        conv.getConversationId(), null /* draft */);
+
+                remoteViews.setOnClickFillInIntent(R.id.widget_conversation_list_item, intent);
+
+                // Avatar
+                boolean includeAvatar;
+                if (OsUtil.isAtLeastJB()) {
+                    final Bundle options = mAppWidgetManager.getAppWidgetOptions(mAppWidgetId);
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "getViewAt BugleWidgetProvider.WIDGET_SIZE_KEY: " +
+                                options.getInt(BugleWidgetProvider.WIDGET_SIZE_KEY));
+                    }
+
+                    includeAvatar = options.getInt(BugleWidgetProvider.WIDGET_SIZE_KEY) ==
+                            BugleWidgetProvider.SIZE_LARGE;
+                } else {
+                    includeAvatar = true;;
+                }
+
+                // Show the avatar when grande size, otherwise hide it.
+                remoteViews.setViewVisibility(R.id.avatarView, includeAvatar ?
+                        View.VISIBLE : View.GONE);
+
+                Uri iconUri = null;
+                if (conv.getIcon() != null) {
+                    iconUri = Uri.parse(conv.getIcon());
+                }
+                remoteViews.setImageViewBitmap(R.id.avatarView, includeAvatar ?
+                        getAvatarBitmap(iconUri) : null);
+
+                // Error
+                // Only show the fail icon if it is not a group conversation.
+                // And also require that we be the default sms app.
+                final boolean showError =
+                        conv.getIsFailedStatus() && !conv.getIsGroup() && isDefaultSmsApp;
+                final boolean showDraft = conv.getShowDraft() && isDefaultSmsApp;
+                remoteViews.setViewVisibility(R.id.conversation_failed_status_icon,
+                        showError && includeAvatar ?
+                        View.VISIBLE : View.GONE);
+
+                if (showError || showDraft) {
+                    remoteViews.setViewVisibility(R.id.snippet, View.GONE);
+                    remoteViews.setViewVisibility(R.id.errorBlock, View.VISIBLE);
+                    remoteViews.setTextViewText(R.id.errorSnippet, getSnippetText(conv));
+
+                    if (showDraft) {
+                        // Show italicized "Draft" on third line
+                        final String text = resources.getString(
+                                R.string.conversation_list_item_view_draft_message);
+                        SpannableStringBuilder builder = new SpannableStringBuilder(text);
+                        builder.setSpan(new StyleSpan(Typeface.ITALIC), 0, text.length(),
+                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                        builder.setSpan(new ForegroundColorSpan(
+                                    resources.getColor(R.color.widget_text_color)),
+                                0, text.length(),
+                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                        remoteViews.setTextViewText(R.id.errorText, builder);
+                    } else {
+                        // Show error message on third line
+                       int failureMessageId = R.string.message_status_download_failed;
+                        if (conv.getIsMessageTypeOutgoing()) {
+                            failureMessageId = MmsUtils.mapRawStatusToErrorResourceId(
+                                    conv.getMessageStatus(),
+                                    conv.getMessageRawTelephonyStatus());
+                        }
+                        remoteViews.setTextViewText(R.id.errorText,
+                                resources.getString(failureMessageId));
+                    }
+                } else {
+                    remoteViews.setViewVisibility(R.id.errorBlock, View.GONE);
+                    remoteViews.setViewVisibility(R.id.snippet, View.VISIBLE);
+                    remoteViews.setTextViewText(R.id.snippet,
+                            boldifyIfUnread(getSnippetText(conv), hasUnreadMessages));
+                }
+
+                // Set the accessibility TalkBack text
+                remoteViews.setContentDescription(R.id.widget_conversation_list_item,
+                        ConversationListItemView.buildContentDescription(mContext.getResources(),
+                                conv, new TextPaint()));
+
+                return remoteViews;
+            }
+        }
+
+        private String getSnippetText(final ConversationListItemData conv) {
+            String snippetText = conv.getShowDraft() ?
+                    conv.getDraftSnippetText() : conv.getSnippetText();
+            final String previewContentType = conv.getShowDraft() ?
+                    conv.getDraftPreviewContentType() : conv.getPreviewContentType();
+            if (TextUtils.isEmpty(snippetText)) {
+                Resources resources = mContext.getResources();
+                // Use the attachment type as a snippet so the preview doesn't look odd
+                if (ContentType.isAudioType(previewContentType)) {
+                    snippetText = resources.getString(
+                            R.string.conversation_list_snippet_audio_clip);
+                } else if (ContentType.isImageType(previewContentType)) {
+                    snippetText = resources.getString(R.string.conversation_list_snippet_picture);
+                } else if (ContentType.isVideoType(previewContentType)) {
+                    snippetText = resources.getString(R.string.conversation_list_snippet_video);
+                } else if (ContentType.isVCardType(previewContentType)) {
+                    snippetText = resources.getString(R.string.conversation_list_snippet_vcard);
+                }
+            }
+            return snippetText;
+        }
+
+        /**
+         * @return the "View more conversations" view. When the user taps this item, they're
+         * taken to the Bugle's conversation list.
+         */
+        @Override
+        protected RemoteViews getViewMoreItemsView() {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "getViewMoreItemsView");
+            }
+            final RemoteViews view = new RemoteViews(mContext.getPackageName(),
+                    R.layout.widget_loading);
+            view.setTextViewText(
+                    R.id.loading_text, mContext.getText(R.string.view_more_conversations));
+
+            // Tapping this "More conversations" item should take us to the ConversationList.
+            // However, the list view is primed with an intent to go to the Conversation activity.
+            // Each normal conversation list item sets the fill-in intent with the
+            // ConversationId for that particular conversation. In other words, the only place
+            // we can go is the ConversationActivity. We add an extra here to tell the
+            // ConversationActivity to really take us to the ConversationListActivity.
+            final Intent intent = new Intent();
+            intent.putExtra(UIIntents.UI_INTENT_EXTRA_GOTO_CONVERSATION_LIST, true);
+            view.setOnClickFillInIntent(R.id.widget_loading, intent);
+            return view;
+        }
+
+        @Override
+        public RemoteViews getLoadingView() {
+            RemoteViews view = new RemoteViews(mContext.getPackageName(), R.layout.widget_loading);
+            view.setTextViewText(
+                    R.id.loading_text, mContext.getText(R.string.loading_conversations));
+            return view;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 2;
+        }
+
+        @Override
+        protected int getMainLayoutId() {
+            return R.layout.widget_conversation_list;
+        }
+    }
+
+}
diff --git a/src/com/android/messaging/widget/WidgetConversationProvider.java b/src/com/android/messaging/widget/WidgetConversationProvider.java
new file mode 100644
index 0000000..6ae5614
--- /dev/null
+++ b/src/com/android/messaging/widget/WidgetConversationProvider.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.WidgetPickConversationActivity;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UiUtils;
+
+public class WidgetConversationProvider extends BaseWidgetProvider {
+    public static final String ACTION_NOTIFY_MESSAGES_CHANGED =
+            "com.android.Bugle.intent.action.ACTION_NOTIFY_MESSAGES_CHANGED";
+
+    public static final int WIDGET_CONVERSATION_TEMPLATE_REQUEST_CODE = 1985;
+    public static final int WIDGET_CONVERSATION_REPLY_CODE = 1987;
+
+    // Intent extras
+    public static final String UI_INTENT_EXTRA_RECIPIENT = "recipient";
+    public static final String UI_INTENT_EXTRA_ICON = "icon";
+
+    /**
+     * Update the widget appWidgetId
+     */
+    @Override
+    protected void updateWidget(final Context context, final int appWidgetId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "updateWidget appWidgetId: " + appWidgetId);
+        }
+        if (OsUtil.hasRequiredPermissions()) {
+            rebuildWidget(context, appWidgetId);
+        } else {
+            AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId,
+                    UiUtils.getWidgetMissingPermissionView(context));
+        }
+    }
+
+    @Override
+    protected String getAction() {
+        return ACTION_NOTIFY_MESSAGES_CHANGED;
+    }
+
+    @Override
+    protected int getListId() {
+        return R.id.message_list;
+    }
+
+    public static void rebuildWidget(final Context context, final int appWidgetId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "WidgetConversationProvider.rebuildWidget appWidgetId: " + appWidgetId);
+        }
+        final RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
+                R.layout.widget_conversation);
+        PendingIntent clickIntent;
+        final UIIntents uiIntents = UIIntents.get();
+        if (!isWidgetConfigured(appWidgetId)) {
+            // Widget has not been configured yet. Hide the normal UI elements and show the
+            // configuration view instead.
+            remoteViews.setViewVisibility(R.id.widget_label, View.GONE);
+            remoteViews.setViewVisibility(R.id.message_list, View.GONE);
+            remoteViews.setViewVisibility(R.id.launcher_icon, View.VISIBLE);
+            remoteViews.setViewVisibility(R.id.widget_configuration, View.VISIBLE);
+
+            remoteViews.setOnClickPendingIntent(R.id.widget_configuration,
+                    uiIntents.getWidgetPendingIntentForConfigurationActivity(context, appWidgetId));
+
+            // On click intent for Goto Conversation List
+            clickIntent = uiIntents.getWidgetPendingIntentForConversationListActivity(context);
+            remoteViews.setOnClickPendingIntent(R.id.widget_header, clickIntent);
+
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "WidgetConversationProvider.rebuildWidget appWidgetId: " +
+                        appWidgetId + " going into configure state");
+            }
+        } else {
+            remoteViews.setViewVisibility(R.id.widget_label, View.VISIBLE);
+            remoteViews.setViewVisibility(R.id.message_list, View.VISIBLE);
+            remoteViews.setViewVisibility(R.id.launcher_icon, View.GONE);
+            remoteViews.setViewVisibility(R.id.widget_configuration, View.GONE);
+
+            final String conversationId =
+                    WidgetPickConversationActivity.getConversationIdPref(appWidgetId);
+            final boolean isMainThread =  Looper.myLooper() == Looper.getMainLooper();
+            // If we're running on the UI thread, we can't do the DB access needed to get the
+            // conversation data. We'll do excute this again off of the UI thread.
+            final ConversationListItemData convData = isMainThread ?
+                    null : getConversationData(context, conversationId);
+
+            // Launch an intent to avoid ANRs
+            final Intent intent = new Intent(context, WidgetConversationService.class);
+            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+            intent.putExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+            remoteViews.setRemoteAdapter(appWidgetId, R.id.message_list, intent);
+
+            remoteViews.setTextViewText(R.id.widget_label, convData != null ?
+                    convData.getName() : context.getString(R.string.app_name));
+
+            // On click intent for Goto Conversation List
+            clickIntent = uiIntents.getWidgetPendingIntentForConversationListActivity(context);
+            remoteViews.setOnClickPendingIntent(R.id.widget_goto_conversation_list, clickIntent);
+
+            // Open the conversation when click on header
+            clickIntent = uiIntents.getWidgetPendingIntentForConversationActivity(context,
+                    conversationId, WIDGET_CONVERSATION_REQUEST_CODE);
+            remoteViews.setOnClickPendingIntent(R.id.widget_header, clickIntent);
+
+            // On click intent for Conversation
+            // Note: the template intent has to be a "naked" intent without any extras. It turns out
+            // that if the template intent does have extras, those particular extras won't get
+            // replaced by the fill-in intent on each list item.
+            clickIntent = uiIntents.getWidgetPendingIntentForConversationActivity(context,
+                    conversationId, WIDGET_CONVERSATION_TEMPLATE_REQUEST_CODE);
+            remoteViews.setPendingIntentTemplate(R.id.message_list, clickIntent);
+
+            if (isMainThread) {
+                // We're running on the UI thread and we couldn't update all the parts of the
+                // widget dependent on ConversationListItemData. However, we have to update
+                // the widget regardless, even with those missing pieces. Here we update the
+                // widget again in the background.
+                SafeAsyncTask.executeOnThreadPool(new Runnable() {
+                    @Override
+                    public void run() {
+                        rebuildWidget(context, appWidgetId);
+                    }
+                });
+            }
+        }
+
+        AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, remoteViews);
+
+    }
+
+    /*
+     * notifyMessagesChanged called when the conversation changes so the widget will
+     * update and reflect the changes
+     */
+    public static void notifyMessagesChanged(final Context context, final String conversationId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "notifyMessagesChanged");
+        }
+        final Intent intent = new Intent(ACTION_NOTIFY_MESSAGES_CHANGED);
+        intent.putExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID, conversationId);
+        context.sendBroadcast(intent);
+    }
+
+    /*
+     * notifyConversationDeleted is called when a conversation is deleted. Look through all the
+     * widgets and if they're displaying that conversation, force the widget into its
+     * configuration state.
+     */
+    public static void notifyConversationDeleted(final Context context,
+            final String conversationId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "notifyConversationDeleted convId: " + conversationId);
+        }
+
+        final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+        for (final int appWidgetId : appWidgetManager.getAppWidgetIds(new ComponentName(context,
+                WidgetConversationProvider.class))) {
+            // Retrieve the persisted information for this widget from preferences.
+            final String widgetConvId =
+                    WidgetPickConversationActivity.getConversationIdPref(appWidgetId);
+
+            if (widgetConvId == null || widgetConvId.equals(conversationId)) {
+                if (widgetConvId != null) {
+                    WidgetPickConversationActivity.deleteConversationIdPref(appWidgetId);
+                }
+                rebuildWidget(context, appWidgetId);
+            }
+        }
+    }
+
+    /*
+     * notifyConversationRenamed is called when a conversation is renamed. Look through all the
+     * widgets and if they're displaying that conversation, force the widget to rebuild itself
+     */
+    public static void notifyConversationRenamed(final Context context,
+            final String conversationId) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "notifyConversationRenamed convId: " + conversationId);
+        }
+
+        final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+        for (final int appWidgetId : appWidgetManager.getAppWidgetIds(new ComponentName(context,
+                WidgetConversationProvider.class))) {
+            // Retrieve the persisted information for this widget from preferences.
+            final String widgetConvId =
+                    WidgetPickConversationActivity.getConversationIdPref(appWidgetId);
+
+            if (widgetConvId != null && widgetConvId.equals(conversationId)) {
+                rebuildWidget(context, appWidgetId);
+            }
+        }
+    }
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "WidgetConversationProvider onReceive intent: " + intent);
+        }
+        final String action = intent.getAction();
+
+        // The base class AppWidgetProvider's onReceive handles the normal widget intents. Here
+        // we're looking for an intent sent by our app when it knows a message has
+        // been sent or received (or a conversation has been read) and is telling the widget it
+        // needs to update.
+        if (getAction().equals(action)) {
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+            final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
+                    this.getClass()));
+
+            if (appWidgetIds.length == 0) {
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "WidgetConversationProvider onReceive no widget ids");
+                }
+                return;
+            }
+            // Normally the conversation id points to a specific conversation and we only update
+            // widgets looking at that conversation. When the conversation id is null, that means
+            // there's been a massive change (such as the initial import) and we need to update
+            // every conversation widget.
+            final String conversationId = intent.getExtras()
+                    .getString(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+
+            // Only update the widgets that match the conversation id that changed.
+            for (final int widgetId : appWidgetIds) {
+                // Retrieve the persisted information for this widget from preferences.
+                final String widgetConvId =
+                        WidgetPickConversationActivity.getConversationIdPref(widgetId);
+                if (conversationId == null || TextUtils.equals(conversationId, widgetConvId)) {
+                    // Update the list portion (i.e. the message list) of the widget
+                    appWidgetManager.notifyAppWidgetViewDataChanged(widgetId, getListId());
+                }
+            }
+        } else {
+            super.onReceive(context, intent);
+        }
+    }
+
+    private static ConversationListItemData getConversationData(final Context context,
+            final String conversationId) {
+        if (TextUtils.isEmpty(conversationId)) {
+            return null;
+        }
+        final Uri uri = MessagingContentProvider.buildConversationMetadataUri(conversationId);
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(uri,
+                    ConversationListItemData.PROJECTION,
+                    null,       // selection
+                    null,       // selection args
+                    null);      // sort order
+            if (cursor != null && cursor.getCount() > 0) {
+                final ConversationListItemData conv = new ConversationListItemData();
+                cursor.moveToFirst();
+                conv.bind(cursor);
+                return conv;
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void deletePreferences(final int widgetId) {
+        WidgetPickConversationActivity.deleteConversationIdPref(widgetId);
+    }
+
+    /**
+     * When this widget is created, it's created for a particular conversation and that
+     * ConversationId is stored in shared prefs. If the associated conversation is deleted,
+     * the widget doesn't get deleted. Instead, it goes into a "tap to configure" state. This
+     * function determines whether the widget has been configured and has an associated
+     * ConversationId.
+     */
+    public static boolean isWidgetConfigured(final int appWidgetId) {
+        final String conversationId =
+                WidgetPickConversationActivity.getConversationIdPref(appWidgetId);
+        return !TextUtils.isEmpty(conversationId);
+    }
+
+}
diff --git a/src/com/android/messaging/widget/WidgetConversationService.java b/src/com/android/messaging/widget/WidgetConversationService.java
new file mode 100644
index 0000000..5b8587b
--- /dev/null
+++ b/src/com/android/messaging/widget/WidgetConversationService.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.text.style.ForegroundColorSpan;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.data.ConversationMessageData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.media.ImageResource;
+import com.android.messaging.datamodel.media.MediaRequest;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.datamodel.media.MessagePartImageRequestDescriptor;
+import com.android.messaging.datamodel.media.MessagePartVideoThumbnailRequestDescriptor;
+import com.android.messaging.datamodel.media.UriImageRequestDescriptor;
+import com.android.messaging.datamodel.media.VideoThumbnailRequest;
+import com.android.messaging.sms.MmsUtils;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.AvatarUriUtil;
+import com.android.messaging.util.Dates;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import java.util.List;
+
+public class WidgetConversationService extends RemoteViewsService {
+    private static final String TAG = LogUtil.BUGLE_WIDGET_TAG;
+
+    private static final int IMAGE_ATTACHMENT_SIZE = 400;
+
+    @Override
+    public RemoteViewsFactory onGetViewFactory(Intent intent) {
+        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+            LogUtil.v(TAG, "onGetViewFactory intent: " + intent);
+        }
+        return new WidgetConversationFactory(getApplicationContext(), intent);
+    }
+
+    /**
+     * Remote Views Factory for the conversation widget.
+     */
+    private static class WidgetConversationFactory extends BaseWidgetFactory {
+        private ImageResource mImageResource;
+        private String mConversationId;
+
+        public WidgetConversationFactory(Context context, Intent intent) {
+            super(context, intent);
+
+            mConversationId = intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "BugleFactory intent: " + intent + "widget id: " + mAppWidgetId);
+            }
+            mIconSize = (int) context.getResources()
+                    .getDimension(R.dimen.contact_icon_view_normal_size);
+        }
+
+        @Override
+        public void onCreate() {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "onCreate");
+            }
+            super.onCreate();
+
+            // If the conversation for this widget has been removed, we want to update the widget to
+            // "Tap to configure" mode.
+            if (!WidgetConversationProvider.isWidgetConfigured(mAppWidgetId)) {
+                WidgetConversationProvider.rebuildWidget(mContext, mAppWidgetId);
+            }
+        }
+
+        @Override
+        protected Cursor doQuery() {
+            if (TextUtils.isEmpty(mConversationId)) {
+                LogUtil.w(TAG, "doQuery no conversation id");
+                return null;
+            }
+            final Uri uri = MessagingContentProvider.buildConversationMessagesUri(mConversationId);
+            if (uri != null) {
+                LogUtil.w(TAG, "doQuery uri: " + uri.toString());
+            }
+            return mContext.getContentResolver().query(uri,
+                    ConversationMessageData.getProjection(),
+                    null,       // where
+                    null,       // selection args
+                    null        // sort order
+                    );
+        }
+
+        /**
+         * @return the {@link RemoteViews} for a specific position in the list.
+         */
+        @Override
+        public RemoteViews getViewAt(final int originalPosition) {
+            synchronized (sWidgetLock) {
+                // "View more messages" view.
+                if (mCursor == null
+                        || (mShouldShowViewMore && originalPosition == 0)) {
+                    return getViewMoreItemsView();
+                }
+                // The message cursor is in reverse order for performance reasons.
+                final int position = getCount() - originalPosition - 1;
+                if (!mCursor.moveToPosition(position)) {
+                    // If we ever fail to move to a position, return the "View More messages"
+                    // view.
+                    LogUtil.w(TAG, "Failed to move to position: " + position);
+                    return getViewMoreItemsView();
+                }
+
+                final ConversationMessageData message = new ConversationMessageData();
+                message.bind(mCursor);
+
+                // Inflate and fill out the remote view
+                final RemoteViews remoteViews = new RemoteViews(
+                        mContext.getPackageName(), message.getIsIncoming() ?
+                                R.layout.widget_message_item_incoming :
+                                    R.layout.widget_message_item_outgoing);
+
+                final boolean hasUnreadMessages = false; //!message.getIsRead();
+
+                // Date
+                remoteViews.setTextViewText(R.id.date, boldifyIfUnread(
+                        Dates.getWidgetTimeString(message.getReceivedTimeStamp(),
+                                false /*abbreviated*/),
+                        hasUnreadMessages));
+
+                // On click intent.
+                final Intent intent = UIIntents.get().getIntentForConversationActivity(mContext,
+                        mConversationId, null /* draft */);
+
+                // Attachments
+                int attachmentStringId = 0;
+                remoteViews.setViewVisibility(R.id.attachmentFrame, View.GONE);
+
+                int scrollToPosition = originalPosition;
+                final int cursorCount = mCursor.getCount();
+                if (cursorCount > MAX_ITEMS_TO_SHOW) {
+                    scrollToPosition += cursorCount - MAX_ITEMS_TO_SHOW;
+                }
+                if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                    LogUtil.v(TAG, "getViewAt position: " + originalPosition +
+                            " computed position: " + position +
+                            " scrollToPosition: " + scrollToPosition +
+                            " cursorCount: " + cursorCount +
+                            " MAX_ITEMS_TO_SHOW: " + MAX_ITEMS_TO_SHOW);
+                }
+
+                intent.putExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_POSITION, scrollToPosition);
+                if (message.hasAttachments()) {
+                    final List<MessagePartData> attachments = message.getAttachments();
+                    for (MessagePartData part : attachments) {
+                        final boolean videoWithThumbnail = part.isVideo()
+                                && (VideoThumbnailRequest.shouldShowIncomingVideoThumbnails()
+                                || !message.getIsIncoming());
+                        if (part.isImage() || videoWithThumbnail) {
+                            final Uri uri = part.getContentUri();
+                            remoteViews.setViewVisibility(R.id.attachmentFrame, View.VISIBLE);
+                            remoteViews.setViewVisibility(R.id.playButton, part.isVideo() ?
+                                    View.VISIBLE : View.GONE);
+                            remoteViews.setImageViewBitmap(R.id.attachment,
+                                    getAttachmentBitmap(part));
+                            intent.putExtra(UIIntents.UI_INTENT_EXTRA_ATTACHMENT_URI ,
+                                    uri.toString());
+                            intent.putExtra(UIIntents.UI_INTENT_EXTRA_ATTACHMENT_TYPE ,
+                                    part.getContentType());
+                            break;
+                        } else if (part.isVideo()) {
+                            attachmentStringId = R.string.conversation_list_snippet_video;
+                            break;
+                        }
+                        if (part.isAudio()) {
+                            attachmentStringId = R.string.conversation_list_snippet_audio_clip;
+                            break;
+                        }
+                        if (part.isVCard()) {
+                            attachmentStringId = R.string.conversation_list_snippet_vcard;
+                            break;
+                        }
+                    }
+                }
+
+                remoteViews.setOnClickFillInIntent(message.getIsIncoming() ?
+                        R.id.widget_message_item_incoming :
+                            R.id.widget_message_item_outgoing,
+                        intent);
+
+                // Avatar
+                boolean includeAvatar;
+                if (OsUtil.isAtLeastJB()) {
+                    final Bundle options = mAppWidgetManager.getAppWidgetOptions(mAppWidgetId);
+                    if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                        LogUtil.v(TAG, "getViewAt BugleWidgetProvider.WIDGET_SIZE_KEY: " +
+                                options.getInt(BugleWidgetProvider.WIDGET_SIZE_KEY));
+                    }
+
+                    includeAvatar = options.getInt(BugleWidgetProvider.WIDGET_SIZE_KEY)
+                            == BugleWidgetProvider.SIZE_LARGE;
+                } else {
+                    includeAvatar = true;
+                }
+
+                // Show the avatar (and shadow) when grande size, otherwise hide it.
+                remoteViews.setViewVisibility(R.id.avatarView, includeAvatar ?
+                        View.VISIBLE : View.GONE);
+                remoteViews.setViewVisibility(R.id.avatarShadow, includeAvatar ?
+                        View.VISIBLE : View.GONE);
+
+                final Uri avatarUri = AvatarUriUtil.createAvatarUri(
+                        message.getSenderProfilePhotoUri(),
+                        message.getSenderFullName(),
+                        message.getSenderNormalizedDestination(),
+                        message.getSenderContactLookupKey());
+
+                remoteViews.setImageViewBitmap(R.id.avatarView, includeAvatar ?
+                        getAvatarBitmap(avatarUri) : null);
+
+                String text = message.getText();
+                if (attachmentStringId != 0) {
+                    final String attachment = mContext.getString(attachmentStringId);
+                    if (!TextUtils.isEmpty(text)) {
+                        text += '\n' + attachment;
+                    } else {
+                        text = attachment;
+                    }
+                }
+
+                remoteViews.setViewVisibility(R.id.message, View.VISIBLE);
+                updateViewContent(text, message, remoteViews);
+
+                return remoteViews;
+            }
+        }
+
+        // updateViewContent figures out what to show in the message and date fields based on
+        // the message status. This code came from ConversationMessageView.updateViewContent, but
+        // had to be simplified to work with our simple widget list item.
+        // updateViewContent also builds the accessibility content description for the list item.
+        private void updateViewContent(final String messageText,
+                final ConversationMessageData message,
+                final RemoteViews remoteViews) {
+            int titleResId = -1;
+            int statusResId = -1;
+            boolean showInRed = false;
+            String statusText = null;
+            switch(message.getStatus()) {
+                case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING:
+                case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING:
+                case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD:
+                case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD:
+                    titleResId = R.string.message_title_downloading;
+                    statusResId = R.string.message_status_downloading;
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD:
+                    if (!OsUtil.isSecondaryUser()) {
+                        titleResId = R.string.message_title_manual_download;
+                        statusResId = R.string.message_status_download;
+                    }
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE:
+                    if (!OsUtil.isSecondaryUser()) {
+                        titleResId = R.string.message_title_download_failed;
+                        statusResId = R.string.message_status_download_error;
+                        showInRed = true;
+                    }
+                    break;
+
+                case MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED:
+                    if (!OsUtil.isSecondaryUser()) {
+                        titleResId = R.string.message_title_download_failed;
+                        statusResId = R.string.message_status_download;
+                        showInRed = true;
+                    }
+                    break;
+
+                case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND:
+                case MessageData.BUGLE_STATUS_OUTGOING_SENDING:
+                    statusResId = R.string.message_status_sending;
+                    break;
+
+                case MessageData.BUGLE_STATUS_OUTGOING_RESENDING:
+                case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY:
+                    statusResId = R.string.message_status_send_retrying;
+                    break;
+
+                case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER:
+                    statusResId = R.string.message_status_send_failed_emergency_number;
+                    showInRed = true;
+                    break;
+
+                case MessageData.BUGLE_STATUS_OUTGOING_FAILED:
+                    // don't show the error state unless we're the default sms app
+                    if (PhoneUtils.getDefault().isDefaultSmsApp()) {
+                        statusResId = MmsUtils.mapRawStatusToErrorResourceId(
+                                message.getStatus(), message.getRawTelephonyStatus());
+                        showInRed = true;
+                        break;
+                    }
+                    // FALL THROUGH HERE
+
+                case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE:
+                case MessageData.BUGLE_STATUS_OUTGOING_DELIVERED:
+                case MessageData.BUGLE_STATUS_INCOMING_COMPLETE:
+                default:
+                    if (!message.getCanClusterWithNextMessage()) {
+                        statusText = Dates.getWidgetTimeString(message.getReceivedTimeStamp(),
+                                false /*abbreviated*/).toString();
+                    }
+                    break;
+            }
+
+            // Build the content description while we're populating the various fields.
+            final StringBuilder description = new StringBuilder();
+            final String separator = mContext.getString(R.string.enumeration_comma);
+            // Sender information
+            final boolean hasPlainTextMessage = !(TextUtils.isEmpty(message.getText()));
+            if (message.getIsIncoming()) {
+                int senderResId = hasPlainTextMessage
+                    ? R.string.incoming_text_sender_content_description
+                    : R.string.incoming_sender_content_description;
+                description.append(mContext.getString(senderResId, message.getSenderDisplayName()));
+            } else {
+                int senderResId = hasPlainTextMessage
+                    ? R.string.outgoing_text_sender_content_description
+                    : R.string.outgoing_sender_content_description;
+                description.append(mContext.getString(senderResId));
+            }
+
+            final boolean titleVisible = (titleResId >= 0);
+            if (titleVisible) {
+                final String titleText = mContext.getString(titleResId);
+                remoteViews.setTextViewText(R.id.message, titleText);
+
+                final String mmsInfoText = mContext.getString(
+                        R.string.mms_info,
+                        Formatter.formatFileSize(mContext, message.getSmsMessageSize()),
+                        DateUtils.formatDateTime(
+                                mContext,
+                                message.getMmsExpiry(),
+                                DateUtils.FORMAT_SHOW_DATE |
+                                DateUtils.FORMAT_SHOW_TIME |
+                                DateUtils.FORMAT_NUMERIC_DATE |
+                                DateUtils.FORMAT_NO_YEAR));
+                remoteViews.setTextViewText(R.id.date, mmsInfoText);
+                description.append(separator);
+                description.append(mmsInfoText);
+            } else if (!TextUtils.isEmpty(messageText)) {
+                remoteViews.setTextViewText(R.id.message, messageText);
+                description.append(separator);
+                description.append(messageText);
+            } else {
+                remoteViews.setViewVisibility(R.id.message, View.GONE);
+            }
+
+            final String subjectText = MmsUtils.cleanseMmsSubject(mContext.getResources(),
+                    message.getMmsSubject());
+            if (!TextUtils.isEmpty(subjectText)) {
+                description.append(separator);
+                description.append(subjectText);
+            }
+
+            if (statusResId >= 0) {
+                statusText = mContext.getString(statusResId);
+                final Spannable colorStr = new SpannableString(statusText);
+                if (showInRed) {
+                    colorStr.setSpan(new ForegroundColorSpan(
+                            mContext.getResources().getColor(R.color.timestamp_text_failed)),
+                            0, statusText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                }
+                remoteViews.setTextViewText(R.id.date, colorStr);
+                description.append(separator);
+                description.append(colorStr);
+            } else {
+                description.append(separator);
+                description.append(Dates.getWidgetTimeString(message.getReceivedTimeStamp(),
+                        false /*abbreviated*/));
+            }
+
+            if (message.hasAttachments()) {
+                final List<MessagePartData> attachments = message.getAttachments();
+                int stringId;
+                for (MessagePartData part : attachments) {
+                    if (part.isImage()) {
+                        stringId = R.string.conversation_list_snippet_picture;
+                    } else if (part.isVideo()) {
+                        stringId = R.string.conversation_list_snippet_video;
+                    } else if (part.isAudio()) {
+                        stringId = R.string.conversation_list_snippet_audio_clip;
+                    } else if (part.isVCard()) {
+                        stringId = R.string.conversation_list_snippet_vcard;
+                    } else {
+                        stringId = 0;
+                    }
+                    if (stringId > 0) {
+                        description.append(separator);
+                        description.append(mContext.getString(stringId));
+                    }
+                }
+            }
+            remoteViews.setContentDescription(message.getIsIncoming() ?
+                    R.id.widget_message_item_incoming :
+                        R.id.widget_message_item_outgoing, description);
+        }
+
+        private Bitmap getAttachmentBitmap(final MessagePartData part) {
+            UriImageRequestDescriptor descriptor;
+            if (part.isImage()) {
+                descriptor = new MessagePartImageRequestDescriptor(part,
+                        IMAGE_ATTACHMENT_SIZE, // desiredWidth
+                        IMAGE_ATTACHMENT_SIZE,  // desiredHeight
+                        true // isStatic
+                        );
+            } else if (part.isVideo()) {
+                descriptor = new MessagePartVideoThumbnailRequestDescriptor(part);
+            } else {
+                return null;
+            }
+
+            final MediaRequest<ImageResource> imageRequest =
+                    descriptor.buildSyncMediaRequest(mContext);
+            final ImageResource imageResource =
+                    MediaResourceManager.get().requestMediaResourceSync(imageRequest);
+            if (imageResource != null && imageResource.getBitmap() != null) {
+                setImageResource(imageResource);
+                return Bitmap.createBitmap(imageResource.getBitmap());
+            } else {
+                releaseImageResource();
+                return null;
+            }
+        }
+
+        /**
+         * @return the "View more messages" view. When the user taps this item, they're
+         * taken to the conversation in Bugle.
+         */
+        @Override
+        protected RemoteViews getViewMoreItemsView() {
+            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
+                LogUtil.v(TAG, "getViewMoreConversationsView");
+            }
+            final RemoteViews view = new RemoteViews(mContext.getPackageName(),
+                    R.layout.widget_loading);
+            view.setTextViewText(
+                    R.id.loading_text, mContext.getText(R.string.view_more_messages));
+
+            // Tapping this "More messages" item should take us to the conversation.
+            final Intent intent = UIIntents.get().getIntentForConversationActivity(mContext,
+                    mConversationId, null /* draft */);
+            view.setOnClickFillInIntent(R.id.widget_loading, intent);
+            return view;
+        }
+
+        @Override
+        public RemoteViews getLoadingView() {
+            final RemoteViews view = new RemoteViews(mContext.getPackageName(),
+                    R.layout.widget_loading);
+            view.setTextViewText(
+                    R.id.loading_text, mContext.getText(R.string.loading_messages));
+            return view;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 3;   // Number of different list items that can be returned -
+                        // 1- incoming list item
+                        // 2- outgoing list item
+                        // 3- more items list item
+        }
+
+        @Override
+        protected int getMainLayoutId() {
+            return R.layout.widget_conversation;
+        }
+
+        private void setImageResource(final ImageResource resource) {
+            if (mImageResource != resource) {
+                // Clear out any information for what is currently used
+                releaseImageResource();
+                mImageResource = resource;
+            }
+        }
+
+        private void releaseImageResource() {
+            if (mImageResource != null) {
+                mImageResource.release();
+            }
+            mImageResource = null;
+        }
+    }
+
+}
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..4db1efd
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,45 @@
+//  Copyright (C) 2015 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 {
+    default_team: "trendy_team_messages",
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "Android-Apache-2.0",
+    ],
+}
+
+android_test {
+    name: "messagingtests",
+    srcs: ["src/**/*.java"],
+    instrumentation_for: "messaging",
+    optimize: {
+        enabled: false,
+    },
+    sdk_version: "current",
+    test_suites: ["general-tests"],
+    certificate: "platform",
+    static_libs: [
+        "mockito-target",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.mock.stubs",
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    data: [
+        ":messaging",
+    ],
+}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 0000000..07f0d17
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.messaging.test" >
+
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="24"/>
+
+    <application android:label="Messaging Tests" >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:label="Messaging Tests"
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.messaging"
+        android:windowSoftInputMode="stateHidden|adjustResize" />
+</manifest>
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
new file mode 100644
index 0000000..cd66c48
--- /dev/null
+++ b/tests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Runs Messaging Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="messagingtests.apk" />
+        <option name="test-file-name" value="messaging.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.messaging.test" />
+        <option name="runner" value="android.test.InstrumentationTestRunner" />
+    </test>
+</configuration>
+
diff --git a/tests/src/com/android/messaging/BugleTestCase.java b/tests/src/com/android/messaging/BugleTestCase.java
new file mode 100644
index 0000000..64c6c86
--- /dev/null
+++ b/tests/src/com/android/messaging/BugleTestCase.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/*
+ * Base class for service tests that takes care of housekeeping that is common amongst basic test
+ * cases.
+ */
+public abstract class BugleTestCase extends AndroidTestCase {
+
+    static {
+        // Set flag during loading of test cases to prevent application initialization starting
+        setTestsRunning();
+    }
+
+    public static void setTestsRunning() {
+        BugleApplication.setTestsRunning();
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        TestUtil.testSetup(super.getContext(), this);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        TestUtil.testTeardown(this);
+    }
+
+    @Override
+    public Context getContext() {
+        // This doesn't really get the "application context" - just the fake context
+        // that the factory has been initialized with for each test case.
+        return Factory.get().getApplicationContext();
+    }
+
+    public Context getTestContext() {
+        return super.getContext();
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/FakeContentProvider.java b/tests/src/com/android/messaging/FakeContentProvider.java
new file mode 100644
index 0000000..eb90cbb
--- /dev/null
+++ b/tests/src/com/android/messaging/FakeContentProvider.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.ContentProvider;
+import android.content.ContentProviderClient;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import androidx.collection.SimpleArrayMap;
+import android.text.TextUtils;
+
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.util.LogUtil;
+
+import java.util.ArrayList;
+
+public class FakeContentProvider extends ContentProvider {
+
+    private static class ContentOverride {
+        private final String uri;
+        private final String where;
+        private final String args;
+        private final String[] columns;
+        private final Object[][] data;
+
+        ContentOverride(final String uri, final String where, final String args,
+                final String[] columns, final Object[][] data) {
+            this.uri = uri;
+            this.where = where;
+            this.args = args;
+            this.columns = columns;
+            this.data = data;
+        }
+
+        boolean match(final String uri, final String where, final String[] args) {
+            if (!this.uri.equals(uri) || !TextUtils.equals(this.where, where)) {
+                return false;
+            }
+
+            if (this.args == null || args == null) {
+                return this.args == null && args == null;
+            }
+
+            return this.args.equals(TextUtils.join(";", args));
+        }
+    }
+
+    private final Context mGlobalContext;
+    private final ArrayList<ContentOverride> mOverrides = new ArrayList<ContentOverride>();
+    private final SimpleArrayMap<String, String> mTypes = new SimpleArrayMap<String, String>();
+    private final ContentProviderClient mProvider;
+    private final Uri mUri;
+
+    public FakeContentProvider(final Context context, final Uri uri, final boolean canDelegate) {
+        mGlobalContext = context;
+        mUri = uri;
+        if (canDelegate) {
+            mProvider = mGlobalContext.getContentResolver().acquireContentProviderClient(mUri);
+        } else {
+            mProvider = null;
+        }
+
+        ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.authority = uri.getAuthority();
+
+        this.attachInfo(mGlobalContext, providerInfo);
+    }
+
+    public void addOverrideData(final Uri uri, final String where, final String args,
+            final String[] columns, final Object[][] data) {
+        mOverrides.add(new ContentOverride(uri.toString(), where, args, columns, data));
+    }
+
+    public void addOverrideType(final Uri uri, final String type) {
+        mTypes.put(uri.toString(), type);
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public void shutdown() {
+        if (mProvider != null) {
+            mProvider.release();
+        }
+    }
+
+    @Override
+    public Cursor query(final Uri uri, final String[] projection, final String selection,
+            final String[] selectionArgs, final String sortOrder) {
+        LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: query " + uri.toString()
+                + " for " + (projection == null ? null : TextUtils.join(",", projection))
+                + " where " + selection
+                + " with " + (selectionArgs == null ? null : TextUtils.join(";", selectionArgs)));
+
+        for(final ContentOverride content : mOverrides) {
+            if (content.match(uri.toString(), selection, selectionArgs)) {
+                return new FakeCursor(projection, content.columns, content.data);
+            }
+        }
+        if (mProvider != null) {
+            try {
+                LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: delgating");
+
+                final Cursor cursor = mProvider.query(uri, projection, selection, selectionArgs,
+                        sortOrder);
+
+                LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: response size "
+                        + cursor.getCount() + " contains " + TextUtils.join(",",
+                                cursor.getColumnNames()) + " type(0) " + cursor.getType(0));
+
+                return cursor;
+            } catch (final RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getType(final Uri uri) {
+        String type = mTypes.get(uri.toString());
+        if (type == null) {
+            try {
+                type = mProvider.getType(uri);
+            } catch (final RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+        return type;
+    }
+
+    @Override
+    public Uri insert(final Uri uri, final ContentValues values) {
+        // TODO: Add code to track insert operations and return correct status
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
+        // TODO: Add code to track delete operations and return correct status
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int update(final Uri uri, final ContentValues values, final String selection,
+            final String[] selectionArgs) {
+        // TODO: Add code to track update operations and return correct status
+        throw new UnsupportedOperationException();
+    }
+
+    public Bundle call(final String callingPkg, final String method, final String arg,
+            final Bundle extras) {
+        return null;
+    }
+}
diff --git a/tests/src/com/android/messaging/FakeContext.java b/tests/src/com/android/messaging/FakeContext.java
new file mode 100644
index 0000000..671e0f3
--- /dev/null
+++ b/tests/src/com/android/messaging/FakeContext.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.test.RenamingDelegatingContext;
+import android.test.mock.MockContentResolver;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class FakeContext extends RenamingDelegatingContext {
+    private static final String TAG = "FakeContext";
+
+    public interface FakeContextHost {
+        public String getServiceClassName();
+        public void startServiceForStub(Intent intent);
+        public void onStartCommandForStub(Intent intent, int flags, int startid);
+    }
+
+    ArrayList<Intent> mStartedIntents;
+    boolean mServiceStarted = false;
+    private final FakeContextHost mService;
+    private final MockContentResolver mContentResolver;
+
+
+    public FakeContext(final Context context, final FakeContextHost service) {
+        super(context, "test_");
+        mService = service;
+        mStartedIntents = new ArrayList<Intent>();
+        mContentResolver = new MockContentResolver();
+    }
+
+    public FakeContext(final Context context) {
+        this(context, null);
+    }
+
+    public ArrayList<Intent> extractIntents() {
+        final ArrayList<Intent> intents = mStartedIntents;
+        mStartedIntents = new ArrayList<Intent>();
+        return intents;
+    }
+
+    @Override
+    public ComponentName startService(final Intent intent) {
+        // Record that a startService occurred with the intent that was passed.
+        Log.d(TAG, "MockContext receiving startService. intent=" + intent.toString());
+        mStartedIntents.add(intent);
+        if (mService == null) {
+            return super.startService(intent);
+        } else if (intent.getComponent() != null &&
+                intent.getComponent().getClassName().equals(mService.getServiceClassName())) {
+            if (!mServiceStarted) {
+                Log.d(TAG, "MockContext first start service.");
+                mService.startServiceForStub(intent);
+            } else {
+                Log.d(TAG, "MockContext not first start service. Calling onStartCommand.");
+                mService.onStartCommandForStub(intent, 0, 0);
+            }
+            mServiceStarted = true;
+            return new ComponentName(this, intent.getComponent().getClassName());
+        }
+        return null;
+    }
+
+    @Override
+    public ContentResolver getContentResolver() {
+        // If you want to use a content provider in your test, then you need to add it
+        // explicitly.
+        return mContentResolver;
+    }
+
+    public void addContentProvider(final String name, final ContentProvider provider) {
+        mContentResolver.addProvider(name, provider);
+    }
+
+    public void addDefaultProvider(final Context context, final Uri uri) {
+        final FakeContentProvider provider = new FakeContentProvider(context, uri, true);
+        mContentResolver.addProvider(uri.getAuthority(), provider);
+    }
+
+}
diff --git a/tests/src/com/android/messaging/FakeFactory.java b/tests/src/com/android/messaging/FakeFactory.java
new file mode 100644
index 0000000..4c7c9de
--- /dev/null
+++ b/tests/src/com/android/messaging/FakeFactory.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.content.ContentProvider;
+import android.content.Context;
+import android.net.Uri;
+import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.ParticipantRefresh.ContactContentObserver;
+import com.android.messaging.datamodel.media.MediaCacheManager;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.BugleCarrierConfigValuesLoader;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.FakeBugleGservices;
+import com.android.messaging.util.FakeBuglePrefs;
+import com.android.messaging.util.MediaUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FakeFactory extends Factory {
+    private Context mContext;
+    private FakeContext mFakeContext;
+    private BugleGservices mBugleGservices;
+    private BuglePrefs mBuglePrefs;
+    private DataModel mDataModel;
+    private UIIntents mUIIntents;
+    private MemoryCacheManager mMemoryCacheManager;
+    private MediaResourceManager mMediaResourceManager;
+    private MediaCacheManager mMediaCacheManager;
+    @Mock protected PhoneUtils mPhoneUtils;
+    private MediaUtil mMediaUtil;
+    private BugleCarrierConfigValuesLoader mCarrierConfigValuesLoader;
+
+    private FakeFactory() {
+    }
+
+    public static FakeFactory registerWithFakeContext(final Context context,
+            final FakeContext fake) {
+        // In tests we currently NEVER run the application/factory initialization
+        Assert.isTrue(!sRegistered);
+        Assert.isTrue(!sInitialized);
+
+        final FakeFactory factory = new FakeFactory();
+        Factory.setInstance(factory);
+
+        // At this point Factory is published. Services can now get initialized and depend on
+        // Factory.get().
+        factory.mContext = context;
+        factory.mFakeContext = fake;
+        factory.mMediaResourceManager = Mockito.mock(MediaResourceManager.class);
+        factory.mBugleGservices = new FakeBugleGservices();
+        factory.mBuglePrefs = new FakeBuglePrefs();
+        factory.mPhoneUtils = Mockito.mock(PhoneUtils.class);
+
+        ApnDatabase.initializeAppContext(context);
+
+        Mockito.when(factory.mPhoneUtils.getCanonicalBySystemLocale(Matchers.anyString()))
+                .thenAnswer(new Answer<String>() {
+                        @Override
+                        public String answer(final InvocationOnMock invocation) throws Throwable {
+                            final Object[] args = invocation.getArguments();
+                            return (String) args[0];
+                        }
+                    }
+                );
+        Mockito.when(factory.mPhoneUtils.getCanonicalBySimLocale(Matchers.anyString())).thenAnswer(
+                new Answer<String>() {
+                    @Override
+                    public String answer(final InvocationOnMock invocation) throws Throwable {
+                        final Object[] args = invocation.getArguments();
+                        return (String) args[0];
+                    }
+                }
+        );
+        Mockito.when(factory.mPhoneUtils.formatForDisplay(Matchers.anyString())).thenAnswer(
+                new Answer<String>() {
+                    @Override
+                    public String answer(final InvocationOnMock invocation) throws Throwable {
+                        return (String) invocation.getArguments()[0];
+                    }
+                }
+        );
+        if (OsUtil.isAtLeastL_MR1()) {
+            Mockito.when(factory.mPhoneUtils.toLMr1()).thenReturn(
+                    new PhoneUtils.LMr1() {
+                        @Override
+                        public SubscriptionInfo getActiveSubscriptionInfo() {
+                            return null;
+                        }
+
+                        @Override
+                        public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
+                            // Return empty list
+                            return new ArrayList<>();
+                        }
+
+                        @Override
+                        public void registerOnSubscriptionsChangedListener(
+                                final SubscriptionManager.OnSubscriptionsChangedListener listener) {
+                        }
+                    }
+            );
+        }
+        // By default only allow reading of system settings (that we provide) - can delegate
+        // to real provider if required.
+        final FakeContentProvider settings = new FakeContentProvider(context,
+                Settings.System.CONTENT_URI, false);
+        settings.addOverrideData(Settings.System.CONTENT_URI, "name=?", "time_12_24",
+                new String[] { "value" }, new Object[][] { { "12" } });
+        settings.addOverrideData(Settings.System.CONTENT_URI, "name=?", "sound_effects_enabled",
+                new String[] { "value" }, new Object[][] { { 1 } });
+
+        factory.withProvider(Settings.System.CONTENT_URI, settings);
+
+        return factory;
+    }
+
+    public static FakeFactory register(final Context applicationContext) {
+        final FakeContext context = new FakeContext(applicationContext);
+        return registerWithFakeContext(applicationContext, context);
+    }
+
+    public static FakeFactory registerWithoutFakeContext(final Context applicationContext) {
+        return registerWithFakeContext(applicationContext, null);
+    }
+
+    @Override
+    public void onRequiredPermissionsAcquired() {
+    }
+
+    @Override
+    public Context getApplicationContext() {
+        return ((mFakeContext != null) ? mFakeContext : mContext );
+    }
+
+    @Override
+    public DataModel getDataModel() {
+        return mDataModel;
+    }
+
+    @Override
+    public BugleGservices getBugleGservices() {
+        return mBugleGservices;
+    }
+
+    @Override
+    public BuglePrefs getApplicationPrefs() {
+        return mBuglePrefs;
+    }
+
+    @Override
+    public BuglePrefs getWidgetPrefs() {
+        return mBuglePrefs;
+    }
+
+    @Override
+    public BuglePrefs getSubscriptionPrefs(final int subId) {
+        return mBuglePrefs;
+    }
+
+    @Override
+    public UIIntents getUIIntents() {
+        return mUIIntents;
+    }
+
+    @Override
+    public MemoryCacheManager getMemoryCacheManager() {
+        return mMemoryCacheManager;
+    }
+
+    @Override
+    public MediaResourceManager getMediaResourceManager() {
+        return mMediaResourceManager;
+    }
+
+    @Override
+    public MediaCacheManager getMediaCacheManager() {
+        return mMediaCacheManager;
+    }
+
+    @Override
+    public PhoneUtils getPhoneUtils(final int subId) {
+        return mPhoneUtils;
+    }
+
+    @Override
+    public MediaUtil getMediaUtil() {
+        return mMediaUtil;
+    }
+
+    @Override
+    public BugleCarrierConfigValuesLoader getCarrierConfigValuesLoader() {
+        return mCarrierConfigValuesLoader;
+    }
+
+    @Override
+    public ContactContentObserver getContactContentObserver() {
+        return null;
+    }
+
+    @Override
+    public void reclaimMemory() {
+    }
+
+    @Override
+    public void onActivityResume() {
+    }
+
+    public FakeFactory withDataModel(final DataModel dataModel) {
+        this.mDataModel = dataModel;
+        return this;
+    }
+
+    public FakeFactory withUIIntents(final UIIntents uiIntents) {
+        this.mUIIntents = uiIntents;
+        return this;
+    }
+
+    public FakeFactory withMemoryCacheManager(final MemoryCacheManager memoryCacheManager) {
+        this.mMemoryCacheManager = memoryCacheManager;
+        return this;
+    }
+
+    public FakeFactory withBugleGservices(final BugleGservices bugleGservices) {
+        this.mBugleGservices = bugleGservices;
+        return this;
+    }
+
+    public FakeFactory withMediaCacheManager(final MediaCacheManager mediaCacheManager) {
+        this.mMediaCacheManager = mediaCacheManager;
+        return this;
+    }
+
+    public FakeFactory withProvider(final Uri uri, final ContentProvider provider) {
+        if (mFakeContext != null) {
+            mFakeContext.addContentProvider(uri.getAuthority(), provider);
+        }
+        return this;
+    }
+
+    public FakeFactory withDefaultProvider(final Uri uri) {
+        if (mFakeContext != null) {
+            mFakeContext.addDefaultProvider(this.mContext, uri);
+        }
+        return this;
+    }
+
+    public FakeFactory withMediaUtil(final MediaUtil mediaUtil) {
+        this.mMediaUtil = mediaUtil;
+        return this;
+    }
+
+    public FakeFactory withCarrierConfigValuesLoader(
+            final BugleCarrierConfigValuesLoader carrierConfigValuesLoader) {
+        this.mCarrierConfigValuesLoader = carrierConfigValuesLoader;
+        return this;
+    }
+}
diff --git a/tests/src/com/android/messaging/TestUtil.java b/tests/src/com/android/messaging/TestUtil.java
new file mode 100644
index 0000000..77a8450
--- /dev/null
+++ b/tests/src/com/android/messaging/TestUtil.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging;
+
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.PowerManager;
+import android.test.InstrumentationTestCase;
+
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.widget.BugleWidgetProvider;
+import com.android.messaging.widget.WidgetConversationProvider;
+
+import junit.framework.TestCase;
+
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Helpers that can be called from all test base classes to 'reset' state and prevent as much as
+ * possible having side effects leak from one test to another.
+ */
+public class TestUtil {
+    public static void testSetup(final Context context, final TestCase testCase) {
+        haltIfTestsAreNotAbleToRun(context);
+
+        // Workaround to get mockito to work.
+        // See https://code.google.com/p/dexmaker/issues/detail?id=2. TODO: Apparently
+        // solvable by using a different runner.
+        System.setProperty("dexmaker.dexcache",
+                context.getCacheDir().getPath());
+
+        // Initialize @Mock objects.
+        MockitoAnnotations.initMocks(testCase);
+
+        // Tests have to explicitly override this
+        Factory.setInstance(null);
+    }
+
+    public static void testTeardown(final TestCase testCase) {
+        if (testCase instanceof InstrumentationTestCase) {
+            // Make sure the test case is finished running or we'll get NPEs when accessing
+            // Fragment.get()
+            ((InstrumentationTestCase) testCase).getInstrumentation().waitForIdleSync();
+        }
+        Factory.setInstance(null);
+    }
+
+    private static void haltIfTestsAreNotAbleToRun(final Context context) {
+        final PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        if (!pm.isScreenOn()) {
+            // Ideally we could turn it on for you using the WindowManager, but we currently run
+            // the tests independently of the activity life cycle.
+            LogUtil.wtf(LogUtil.BUGLE_TAG, "You need to turn on your screen to run tests!");
+        }
+
+        final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+        int [] conversationWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
+                WidgetConversationProvider.class));
+        int [] conversationListWidgetIds = appWidgetManager.getAppWidgetIds(new
+                ComponentName(context, BugleWidgetProvider.class));
+
+        if ((conversationWidgetIds.length > 0) || (conversationListWidgetIds.length > 0)) {
+            // Currently widgets asynchronously access our content providers and singletons which
+            // interacts badly with our test setup and tear down.
+            LogUtil.wtf(LogUtil.BUGLE_TAG, "You currently can't reliably run unit tests" +
+                    " with a Messaging widget on your desktop!");
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/BindingTest.java b/tests/src/com/android/messaging/datamodel/BindingTest.java
new file mode 100644
index 0000000..6052ed1
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/BindingTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.datamodel.binding.BindableData;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.binding.ImmutableBindingRef;
+
+/**
+ * Test binding
+ */
+@SmallTest
+public class BindingTest extends BugleTestCase {
+    private static final Object TEST_DATA_ID = "myDataId";
+    private static final Object YOUR_DATA_ID = "yourDataId";
+
+    public void testBindingStartsUnbound() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        assertNull(binding.getBindingId());
+    }
+
+    public void testDataStartsUnbound() {
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        assertFalse(data.isBound());
+    }
+
+    public void testBindingUpdatesDataAndBindee() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        binding.bind(data);
+        assertTrue(binding.isBound());
+        assertEquals(binding.getData(), data);
+        assertTrue(data.isBound(binding.getBindingId()));
+        assertFalse(data.isBound("SomeRandomString"));
+        assertNotNull(binding.getBindingId());
+        assertFalse(data.mListenersUnregistered);
+    }
+
+    public void testRebindingFails() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        final TestBindableData yours = new TestBindableData(YOUR_DATA_ID);
+        binding.bind(yours);
+        assertEquals(binding.getData(), yours);
+        assertTrue(yours.isBound(binding.getBindingId()));
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        try {
+            binding.bind(data);
+            fail();
+        } catch (final IllegalStateException e) {
+        }
+        assertTrue(binding.isBound());
+        assertEquals(binding.getData(), yours);
+        assertTrue(yours.isBound(binding.getBindingId()));
+    }
+
+    public void testUnbindingClearsDataAndBindee() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        binding.bind(data);
+        assertTrue(data.isBound(binding.getBindingId()));
+        assertTrue(binding.isBound());
+        binding.unbind();
+        try {
+            final TestBindableData other = binding.getData();
+            fail();
+        } catch (final IllegalStateException e) {
+        }
+        assertFalse(data.isBound());
+        assertNull(binding.getBindingId());
+        assertTrue(data.mListenersUnregistered);
+    }
+
+    public void testUnbindingAndRebinding() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        final TestBindableData yours = new TestBindableData(YOUR_DATA_ID);
+        binding.bind(yours);
+        assertEquals(binding.getData(), yours);
+        assertTrue(yours.isBound(binding.getBindingId()));
+        binding.unbind();
+        assertFalse(yours.isBound());
+        assertNull(binding.getBindingId());
+
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        binding.bind(data);
+        assertEquals(binding.getData(), data);
+        assertTrue(data.isBound(binding.getBindingId()));
+        assertFalse(data.isBound("SomeRandomString"));
+        assertTrue(binding.isBound());
+        assertNotNull(binding.getBindingId());
+    }
+
+    public void testBindingReference() {
+        final Binding<TestBindableData> binding = BindingBase.createBinding(this);
+        final TestBindableData data = new TestBindableData(TEST_DATA_ID);
+        binding.bind(data);
+        assertEquals(binding.getData(), data);
+        assertTrue(data.isBound(binding.getBindingId()));
+
+        final ImmutableBindingRef<TestBindableData> bindingRef =
+                BindingBase.createBindingReference(binding);
+        assertEquals(bindingRef.getData(), data);
+        assertTrue(data.isBound(bindingRef.getBindingId()));
+
+        binding.unbind();
+        assertFalse(binding.isBound());
+        assertNull(binding.getBindingId());
+        assertFalse(bindingRef.isBound());
+        assertNull(bindingRef.getBindingId());
+    }
+
+    static class TestBindableData extends BindableData {
+        private final Object mDataId;
+        public boolean mListenersUnregistered;
+
+        public TestBindableData(final Object dataId) {
+            mDataId = dataId;
+            mListenersUnregistered = false;
+        }
+
+        @Override
+        public void unregisterListeners() {
+            mListenersUnregistered = true;
+        }
+
+        @Override
+        public boolean isBound() {
+            return super.isBound();
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/BitmapPoolTest.java b/tests/src/com/android/messaging/datamodel/BitmapPoolTest.java
new file mode 100644
index 0000000..c7bb3d9
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/BitmapPoolTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+
+import org.mockito.Mock;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@SmallTest
+public class BitmapPoolTest extends BugleTestCase {
+    private static final int POOL_SIZE = 5;
+    private static final int IMAGE_DIM = 1;
+    private static final String NAME = "BitmapPoolTest";
+
+    @Mock private MemoryCacheManager mockMemoryCacheManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext())
+                .withMemoryCacheManager(mockMemoryCacheManager);
+    }
+
+    private Set<Bitmap> fillPoolAndGetPoolContents(final BitmapPool pool, final int width,
+            final int height) {
+        final Set<Bitmap> returnedBitmaps = new HashSet<Bitmap>();
+        for (int i = 0; i < POOL_SIZE; i++) {
+            final Bitmap temp = pool.createOrReuseBitmap(width, height);
+            assertFalse(returnedBitmaps.contains(temp));
+            returnedBitmaps.add(temp);
+        }
+        for (final Bitmap b : returnedBitmaps) {
+            pool.reclaimBitmap(b);
+        }
+        assertTrue(pool.isFull(width, height));
+        return returnedBitmaps;
+    }
+
+    public void testCreateAndPutBackInPoolTest() {
+        final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
+        final Bitmap bitmap = pool.createOrReuseBitmap(IMAGE_DIM, IMAGE_DIM);
+        assertFalse(bitmap.isRecycled());
+        assertFalse(pool.isFull(IMAGE_DIM, IMAGE_DIM));
+        pool.reclaimBitmap(bitmap);
+
+        // Don't recycle because the pool isn't full yet.
+        assertFalse(bitmap.isRecycled());
+    }
+
+    public void testCreateBeyondFullAndCheckReuseTest() {
+        final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
+        final Set<Bitmap> returnedBitmaps =
+                fillPoolAndGetPoolContents(pool, IMAGE_DIM, IMAGE_DIM);
+        final Bitmap overflowBitmap = pool.createOrReuseBitmap(IMAGE_DIM, IMAGE_DIM);
+        assertFalse(overflowBitmap.isRecycled());
+        assertTrue(returnedBitmaps.contains(overflowBitmap));
+    }
+
+    /**
+     * Make sure that we have the correct options to create mutable for bitmap pool reuse.
+     */
+    public void testAssertBitmapOptionsAreMutable() {
+        final BitmapFactory.Options options =
+                BitmapPool.getBitmapOptionsForPool(false, IMAGE_DIM, IMAGE_DIM);
+        assertTrue(options.inMutable);
+    }
+
+    public void testDecodeFromResourceBitmap() {
+        final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
+        final BitmapFactory.Options options =
+                BitmapPool.getBitmapOptionsForPool(true, IMAGE_DIM, IMAGE_DIM);
+        final Resources resources = getContext().getResources();
+        final Bitmap resourceBitmap = pool.decodeSampledBitmapFromResource(
+                R.drawable.msg_bubble_incoming, resources, options, IMAGE_DIM, IMAGE_DIM);
+        assertNotNull(resourceBitmap);
+        assertTrue(resourceBitmap.getByteCount() > 0);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/BugleServiceTestCase.java b/tests/src/com/android/messaging/datamodel/BugleServiceTestCase.java
new file mode 100644
index 0000000..42eb647
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/BugleServiceTestCase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.app.Service;
+import android.test.ServiceTestCase;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.TestUtil;
+
+
+/*
+ * Base class for service tests that takes care of housekeeping that is commong amongst our service
+ * test case.
+ */
+public abstract class BugleServiceTestCase<T extends Service> extends ServiceTestCase<T> {
+
+    static {
+        // Set flag during loading of test cases to prevent application initialization starting
+        BugleTestCase.setTestsRunning();
+    }
+
+    public BugleServiceTestCase(final Class<T> serviceClass) {
+        super(serviceClass);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+      TestUtil.testSetup(getContext(), this);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        TestUtil.testTeardown(this);
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/datamodel/ConversationListTest.java b/tests/src/com/android/messaging/datamodel/ConversationListTest.java
new file mode 100644
index 0000000..b9ef5d0
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/ConversationListTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+
+@SmallTest
+public class ConversationListTest extends BugleTestCase {
+    public void testTesting() {
+        assertTrue(true);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/DataModelTest.java b/tests/src/com/android/messaging/datamodel/DataModelTest.java
new file mode 100644
index 0000000..701f053
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/DataModelTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+
+import org.mockito.Mock;
+
+public class DataModelTest extends BugleTestCase {
+
+    DataModel dataModel;
+    @Mock protected ConversationDataListener mockConversationDataListener;
+    @Mock protected ConversationListDataListener mockConversationListDataListener;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory factory = FakeFactory.register(mContext);
+        dataModel = new DataModelImpl(getTestContext());
+        factory.withDataModel(dataModel);
+    }
+
+    @SmallTest
+    public void testCreateConversationList() {
+        final ConversationListData list = dataModel.createConversationListData(getContext(),
+                        mockConversationListDataListener, true);
+        assertTrue(list instanceof ConversationListData);
+        final ConversationData conv = dataModel.createConversationData(getContext(),
+                mockConversationDataListener, "testConversation");
+        assertTrue(conv instanceof ConversationData);
+    }
+
+    private static final String FOCUSED_CONV_ID = "focused_conv_id";
+
+    @SmallTest
+    public void testFocusedConversationIsObservable() {
+        dataModel.setFocusedConversation(FOCUSED_CONV_ID);
+        assertTrue(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
+        dataModel.setFocusedConversation(null);
+        assertFalse(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
+    }
+
+    @SmallTest
+    public void testConversationIsObservableInList() {
+        dataModel.setConversationListScrolledToNewestConversation(true);
+        assertTrue(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
+        dataModel.setConversationListScrolledToNewestConversation(false);
+        assertFalse(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/FakeCursor.java b/tests/src/com/android/messaging/datamodel/FakeCursor.java
new file mode 100644
index 0000000..59d1b89
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/FakeCursor.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.os.Bundle;
+import android.test.mock.MockCursor;
+
+import java.util.ArrayList;
+
+/**
+ * A simple in memory fake cursor that can be used for UI tests.
+ */
+public class FakeCursor extends MockCursor {
+    private final ArrayList<Integer> mProjection;
+    private final String[] mColumnNamesOfData;
+    private final Object[][] mData;
+    private int mIndex;
+
+    public FakeCursor(final String[] projection, final String[] columnNames,
+            final Object[][] data) {
+        mColumnNamesOfData = columnNames;
+        mData = data;
+        mIndex = -1;
+        mProjection = new ArrayList<Integer>(projection.length);
+        for (final String column : projection) {
+            mProjection.add(getColumnIndex(column));
+        }
+    }
+
+    public Object getAt(final String columnName, final int row) {
+        final int dataIdx = getColumnIndex(columnName);
+        return (dataIdx < 0 || row < 0 || row >= mData.length) ? 0 : mData[row][dataIdx];
+    }
+
+    @Override
+    public int getCount() {
+        return mData.length;
+    }
+
+    @Override
+    public boolean isFirst() {
+        return mIndex == 0;
+    }
+
+    @Override
+    public boolean isLast() {
+        return mIndex == mData.length - 1;
+    }
+
+    @Override
+    public boolean moveToFirst() {
+        if (mData.length == 0) {
+            return false;
+        }
+        mIndex = 0;
+        return true;
+    }
+
+    @Override
+    public boolean moveToPosition(final int position) {
+        if (position < 0 || position >= mData.length) {
+            return false;
+        }
+        mIndex = position;
+        return true;
+    }
+
+    @Override
+    public int getPosition() {
+        return mIndex;
+    }
+
+    @Override
+    public boolean moveToPrevious() {
+        if (mIndex <= 0) {
+            return false;
+        }
+        mIndex--;
+        return true;
+    }
+
+    @Override
+    public boolean moveToNext() {
+        if (mIndex == mData.length - 1) {
+            return false;
+        }
+
+        mIndex++;
+        return true;
+    }
+
+    @Override
+    public int getColumnCount() {
+        return mColumnNamesOfData.length;
+    }
+
+    @Override
+    public int getColumnIndex(final String columnName) {
+        for (int i = 0 ; i < mColumnNamesOfData.length ; i++) {
+            if (mColumnNamesOfData[i].equals(columnName)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    public int getColumnIndexOrThrow(final String columnName) {
+        final int result = getColumnIndex(columnName);
+        if (result == -1) {
+            throw new IllegalArgumentException();
+        }
+
+        return result;
+    }
+
+    @Override
+    public String getString(final int columnIndex) {
+        final int dataIdx = mProjection.get(columnIndex);
+        final Object obj = (dataIdx < 0 ? null : mData[mIndex][dataIdx]);
+        return (obj == null ? null : obj.toString());
+    }
+
+    @Override
+    public int getInt(final int columnIndex) {
+        final int dataIdx = mProjection.get(columnIndex);
+        return (dataIdx < 0 ? 0 : (Integer) mData[mIndex][dataIdx]);
+    }
+
+    @Override
+    public long getLong(final int columnIndex) {
+        final int dataIdx = mProjection.get(columnIndex);
+        return (dataIdx < 0 ? 0 : (Long) mData[mIndex][dataIdx]);
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public boolean isClosed() {
+        return false;
+    }
+
+    @Override
+    public Bundle getExtras() { return null; }
+}
diff --git a/tests/src/com/android/messaging/datamodel/FakeDataModel.java b/tests/src/com/android/messaging/datamodel/FakeDataModel.java
new file mode 100644
index 0000000..1daaa20
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/FakeDataModel.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.test.RenamingDelegatingContext;
+
+import com.android.messaging.datamodel.action.ActionService;
+import com.android.messaging.datamodel.action.BackgroundWorker;
+import com.android.messaging.datamodel.data.BlockedParticipantsData;
+import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.ContactPickerData;
+import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.LaunchConversationData;
+import com.android.messaging.datamodel.data.LaunchConversationData.LaunchConversationDataListener;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantListItemData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData;
+import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
+import com.android.messaging.datamodel.data.PeopleOptionsItemData;
+import com.android.messaging.datamodel.data.SettingsData;
+import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.datamodel.data.VCardContactItemData;
+
+public class FakeDataModel extends DataModel {
+    private BackgroundWorker mWorker;
+    private ActionService mActionService;
+    private final DatabaseHelper mDatabaseHelper;
+    private ConversationListData mConversationListData;
+    private ContactPickerData mContactPickerData;
+    private MediaPickerData mMediaPickerData;
+    private PeopleAndOptionsData mPeopleAndOptionsData;
+    private SyncManager mSyncManager;
+    private SettingsData mSettingsData;
+    private DraftMessageData mDraftMessageData;
+
+    public FakeDataModel(final Context context) {
+        super();
+        if (context instanceof RenamingDelegatingContext) {
+            mDatabaseHelper = DatabaseHelper.getNewInstanceForTest(context);
+        } else {
+            mDatabaseHelper = null;
+        }
+    }
+
+    @Override
+    public BackgroundWorker getBackgroundWorkerForActionService() {
+        return mWorker;
+    }
+
+    public FakeDataModel withBackgroundWorkerForActionService(final BackgroundWorker worker) {
+        mWorker = worker;
+        return this;
+    }
+
+    public FakeDataModel withActionService(final ActionService ActionService) {
+        mActionService = ActionService;
+        return this;
+    }
+
+    public FakeDataModel withConversationListData(final ConversationListData conversationListData) {
+        mConversationListData = conversationListData;
+        return this;
+    }
+
+    public FakeDataModel withContactPickerData(final ContactPickerData contactPickerData) {
+        mContactPickerData = contactPickerData;
+        return this;
+    }
+
+    public FakeDataModel withMediaPickerData(final MediaPickerData mediaPickerData) {
+        mMediaPickerData = mediaPickerData;
+        return this;
+    }
+
+    public FakeDataModel withSyncManager(final SyncManager syncManager) {
+        mSyncManager = syncManager;
+        return this;
+    }
+
+    public FakeDataModel withPeopleAndOptionsData(final PeopleAndOptionsData peopleAndOptionsData) {
+        mPeopleAndOptionsData = peopleAndOptionsData;
+        return this;
+    }
+
+    public FakeDataModel withSettingsData(final SettingsData settingsData) {
+        mSettingsData = settingsData;
+        return this;
+    }
+
+    public FakeDataModel withDraftMessageData(final DraftMessageData draftMessageData) {
+        mDraftMessageData = draftMessageData;
+        return this;
+    }
+
+    @Override
+    public ConversationListData createConversationListData(final Context context,
+            final ConversationListDataListener listener, final boolean archivedMode) {
+        return mConversationListData;
+    }
+
+    @Override
+    public ConversationData createConversationData(final Context context,
+            final ConversationDataListener listener, final String conversationId) {
+        throw new IllegalStateException("Add withXXX or mock this method");
+    }
+
+    @Override
+    public ContactListItemData createContactListItemData() {
+        // This is a lightweight data holder object for each individual list item for which
+        // we don't perform any data request, so we can directly return a new instance.
+        return new ContactListItemData();
+    }
+
+    @Override
+    public ContactPickerData createContactPickerData(final Context context,
+            final ContactPickerDataListener listener) {
+        return mContactPickerData;
+    }
+
+    @Override
+    public MediaPickerData createMediaPickerData(final Context context) {
+        return mMediaPickerData;
+    }
+
+    @Override
+    public GalleryGridItemData createGalleryGridItemData() {
+        // This is a lightweight data holder object for each individual grid item for which
+        // we don't perform any data request, so we can directly return a new instance.
+        return new GalleryGridItemData();
+    }
+
+    @Override
+    public LaunchConversationData createLaunchConversationData(
+            final LaunchConversationDataListener listener) {
+       return new LaunchConversationData(listener);
+    }
+
+    @Override
+    public PeopleOptionsItemData createPeopleOptionsItemData(final Context context) {
+        return new PeopleOptionsItemData(context);
+    }
+
+    @Override
+    public PeopleAndOptionsData createPeopleAndOptionsData(final String conversationId,
+            final Context context, final PeopleAndOptionsDataListener listener) {
+        return mPeopleAndOptionsData;
+    }
+
+    @Override
+    public VCardContactItemData createVCardContactItemData(final Context context,
+            final MessagePartData data) {
+        return new VCardContactItemData(context, data);
+    }
+
+    @Override
+    public VCardContactItemData createVCardContactItemData(final Context context,
+            final Uri vCardUri) {
+        return new VCardContactItemData(context, vCardUri);
+    }
+
+    @Override
+    public ParticipantListItemData createParticipantListItemData(
+            final ParticipantData participant) {
+        return new ParticipantListItemData(participant);
+    }
+
+    @Override
+    public SubscriptionListData createSubscriptonListData(Context context) {
+        return new SubscriptionListData(context);
+    }
+
+    @Override
+    public SettingsData createSettingsData(Context context, SettingsDataListener listener) {
+        return mSettingsData;
+    }
+
+    @Override
+    public DraftMessageData createDraftMessageData(String conversationId) {
+        return mDraftMessageData;
+    }
+
+    @Override
+    public ActionService getActionService() {
+        return mActionService;
+    }
+
+    @Override
+    public SyncManager getSyncManager() {
+        return mSyncManager;
+    }
+
+    @Override
+    public DatabaseWrapper getDatabase() {
+        // Note this will crash unless the application context is redirected...
+        // This is by design so that tests do not inadvertently use the real database
+        return mDatabaseHelper.getDatabase();
+    }
+
+    @Override
+    void onCreateTables(final SQLiteDatabase db) {
+        TestDataFactory.createTestData(db);
+    }
+
+    @Override
+    public void onActivityResume() {
+    }
+
+    @Override
+    public void onApplicationCreated() {
+    }
+
+    @Override
+    public BlockedParticipantsData createBlockedParticipantsData(Context context,
+            BlockedParticipantsDataListener listener) {
+        return new BlockedParticipantsData(context, listener);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/FrequentContactsCursorBuilderTest.java b/tests/src/com/android/messaging/datamodel/FrequentContactsCursorBuilderTest.java
new file mode 100644
index 0000000..afa95bb
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/FrequentContactsCursorBuilderTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel;
+
+import android.database.Cursor;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.util.ContactUtil;
+
+@SmallTest
+public class FrequentContactsCursorBuilderTest extends BugleTestCase {
+
+    private void verifyBuiltCursor(final Cursor expected, final Cursor actual) {
+        final int rowCount = expected.getCount();
+        final int columnCount = expected.getColumnCount();
+        assertEquals(rowCount, actual.getCount());
+        assertEquals(columnCount, actual.getColumnCount());
+        for (int i = 0; i < rowCount; i++) {
+            expected.moveToPosition(i);
+            actual.moveToPosition(i);
+            assertEquals(expected.getLong(ContactUtil.INDEX_DATA_ID),
+                    actual.getLong(ContactUtil.INDEX_DATA_ID));
+            assertEquals(expected.getLong(ContactUtil.INDEX_CONTACT_ID),
+                    actual.getLong(ContactUtil.INDEX_CONTACT_ID));
+            assertEquals(expected.getString(ContactUtil.INDEX_LOOKUP_KEY),
+                    actual.getString(ContactUtil.INDEX_LOOKUP_KEY));
+            assertEquals(expected.getString(ContactUtil.INDEX_DISPLAY_NAME),
+                    actual.getString(ContactUtil.INDEX_DISPLAY_NAME));
+            assertEquals(expected.getString(ContactUtil.INDEX_PHOTO_URI),
+                    actual.getString(ContactUtil.INDEX_PHOTO_URI));
+            assertEquals(expected.getString(ContactUtil.INDEX_PHONE_EMAIL),
+                    actual.getString(ContactUtil.INDEX_PHONE_EMAIL));
+            assertEquals(expected.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE),
+                    actual.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE));
+            assertEquals(expected.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL),
+                    actual.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL));
+        }
+    }
+
+    public void testIncompleteBuild() {
+        final FrequentContactsCursorBuilder builder = new FrequentContactsCursorBuilder();
+        assertNull(builder.build());
+        assertNull(builder.setFrequents(TestDataFactory.getStrequentContactsCursor()).build());
+        builder.resetBuilder();
+        assertNull(builder.build());
+        assertNull(builder.setAllContacts(TestDataFactory.getAllContactListCursor()).build());
+    }
+
+    public void testBuildOnce() {
+        final Cursor cursor = new FrequentContactsCursorBuilder()
+            .setAllContacts(TestDataFactory.getAllContactListCursor())
+            .setFrequents(TestDataFactory.getStrequentContactsCursor())
+            .build();
+        assertNotNull(cursor);
+        verifyBuiltCursor(TestDataFactory.getFrequentContactListCursor(), cursor);
+    }
+
+    public void testBuildTwice() {
+        final FrequentContactsCursorBuilder builder = new FrequentContactsCursorBuilder();
+        final Cursor firstCursor = builder
+            .setAllContacts(TestDataFactory.getAllContactListCursor())
+            .setFrequents(TestDataFactory.getStrequentContactsCursor())
+            .build();
+        assertNotNull(firstCursor);
+        builder.resetBuilder();
+        assertNull(builder.build());
+
+        final Cursor secondCursor = builder
+                .setAllContacts(TestDataFactory.getAllContactListCursor())
+                .setFrequents(TestDataFactory.getStrequentContactsCursor())
+                .build();
+        assertNotNull(firstCursor);
+        verifyBuiltCursor(TestDataFactory.getFrequentContactListCursor(), secondCursor);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/MemoryCacheManagerTest.java b/tests/src/com/android/messaging/datamodel/MemoryCacheManagerTest.java
new file mode 100644
index 0000000..a4d8849
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/MemoryCacheManagerTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.test.AndroidTestCase;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.datamodel.MemoryCacheManager.MemoryCache;
+
+import org.mockito.Mockito;
+
+@SmallTest
+public class MemoryCacheManagerTest extends AndroidTestCase {
+
+    public void testRegisterCachesGetReclaimed() {
+        final MemoryCache mockMemoryCache = Mockito.mock(MemoryCache.class);
+        final MemoryCache otherMockMemoryCache = Mockito.mock(MemoryCache.class);
+        final MemoryCacheManager memoryCacheManager = new MemoryCacheManager();
+
+        memoryCacheManager.registerMemoryCache(mockMemoryCache);
+        memoryCacheManager.registerMemoryCache(otherMockMemoryCache);
+        memoryCacheManager.reclaimMemory();
+        memoryCacheManager.unregisterMemoryCache(otherMockMemoryCache);
+        memoryCacheManager.reclaimMemory();
+
+        Mockito.verify(mockMemoryCache, Mockito.times(2)).reclaim();
+        Mockito.verify(otherMockMemoryCache, Mockito.times(1)).reclaim();
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/ParticipantRefreshTest.java b/tests/src/com/android/messaging/datamodel/ParticipantRefreshTest.java
new file mode 100644
index 0000000..c0d5c0a
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/ParticipantRefreshTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeContentProvider;
+import com.android.messaging.FakeContext;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.util.ContactUtil;
+
+import org.junit.Assert;
+import org.mockito.Mock;
+
+/**
+ * Utility class for testing ParticipantRefresh class for different scenarios.
+ */
+@SmallTest
+public class ParticipantRefreshTest extends BugleTestCase {
+    private FakeContext mContext;
+    FakeFactory mFakeFactory;
+    @Mock protected UIIntents mMockUIIntents;
+    protected FakeDataModel mFakeDataModel;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mContext = new FakeContext(getTestContext());
+
+        final ContentProvider provider = new MessagingContentProvider();
+        provider.attachInfo(mContext, null);
+        mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
+
+        mFakeDataModel = new FakeDataModel(mContext);
+        mFakeFactory = FakeFactory.registerWithFakeContext(getTestContext(), mContext)
+                .withDataModel(mFakeDataModel)
+                .withUIIntents(mMockUIIntents);
+    }
+
+    /**
+     * Add some phonelookup result into take PhoneLookup content provider. This will be
+     * used for doing phone lookup during participant refresh.
+     */
+    private void addPhoneLookup(final String phone, final Object[][] lookupResult) {
+        final Uri uri = ContactUtil.lookupPhone(mContext, phone).getUri();
+        final FakeContentProvider phoneLookup = new FakeContentProvider(mContext,
+                uri, false);
+        phoneLookup.addOverrideData(uri, null, null, ContactUtil.PhoneLookupQuery.PROJECTION,
+                lookupResult);
+        mFakeFactory.withProvider(uri, phoneLookup);
+    }
+
+    /**
+     * Add some participant to test database.
+     */
+    private void addParticipant(final String normalizedDestination, final long contactId,
+            final String name, final String photoUrl) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final ContentValues values = new ContentValues();
+
+        values.put(ParticipantColumns.NORMALIZED_DESTINATION, normalizedDestination);
+        values.put(ParticipantColumns.CONTACT_ID, contactId);
+        values.put(ParticipantColumns.FULL_NAME, name);
+        values.put(ParticipantColumns.PROFILE_PHOTO_URI, photoUrl);
+
+        db.beginTransaction();
+        try {
+            db.insert(DatabaseHelper.PARTICIPANTS_TABLE, null, values);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    /**
+     * Verify that participant in the database has expected contacdtId, name and photoUrl fields.
+     */
+    private void verifyParticipant(final String normalizedDestination, final long contactId,
+            final String name, final String photoUrl) {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        db.beginTransaction();
+        try {
+            final String selection = ParticipantColumns.NORMALIZED_DESTINATION + "=?";
+            final String[] selectionArgs = new String[] { normalizedDestination };
+
+            final Cursor cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
+                    ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null);
+
+            if (cursor == null || cursor.getCount() != 1) {
+                Assert.fail("Should have participants for:" + normalizedDestination);
+                return;
+            }
+
+            cursor.moveToFirst();
+            final int currentContactId = cursor.getInt(ParticipantsQuery.INDEX_CONTACT_ID);
+            final String currentName = cursor.getString(ParticipantsQuery.INDEX_FULL_NAME);
+            final String currentPhotoUrl =
+                    cursor.getString(ParticipantsQuery.INDEX_PROFILE_PHOTO_URI);
+            if (currentContactId != contactId) {
+                Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
+                        " expected=" + contactId + " actual=" + currentContactId);
+                return;
+            }
+
+            if (!TextUtils.equals(currentName, name)) {
+                Assert.fail("Name doesn't match. normalizedNumber=" + normalizedDestination +
+                        " expected=" + name + " actual=" + currentName);
+                return;
+            }
+
+            if (!TextUtils.equals(currentPhotoUrl, photoUrl)) {
+                Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
+                        " expected=" + photoUrl + " actual=" + currentPhotoUrl);
+                return;
+            }
+
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    /**
+     * Verify that incremental refresh will resolve previously not resolved participants.
+     */
+    public void testIncrementalRefreshNotResolvedSingleMatch() {
+        addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
+                null, null);
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that incremental refresh will resolve previously not resolved participants.
+     */
+    public void testIncrementalRefreshNotResolvedMultiMatch() {
+        addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
+                null, null);
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
+                { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that incremental refresh will not touch already-resolved participants.
+     */
+    public void testIncrementalRefreshResolvedSingleMatch() {
+        addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that full refresh will correct already-resolved participants if needed
+     */
+    public void testFullRefreshResolvedSingleMatch() {
+        addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that incremental refresh will not touch participant that is marked as not found.
+     */
+    public void testIncrementalRefreshNotFound() {
+        addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
+                null, null);
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that full refresh will resolve participant that is marked as not found.
+     */
+    public void testFullRefreshNotFound() {
+        addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
+                null, null);
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that refresh take consideration of current contact_id when having multiple matches.
+     */
+    public void testFullRefreshResolvedMultiMatch1() {
+        addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
+                { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that refresh take consideration of current contact_id when having multiple matches.
+     */
+    public void testFullRefreshResolvedMultiMatch2() {
+        addParticipant("650-123-1233", 2, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
+                { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that refresh take first contact in case current contact_id no longer matches.
+     */
+    public void testFullRefreshResolvedMultiMatch3() {
+        addParticipant("650-123-1233", 3, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {
+                { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
+                { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
+        });
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
+    }
+
+    /**
+     * Verify that refresh take first contact in case current contact_id no longer matches.
+     */
+    public void testFullRefreshResolvedBeforeButNotFoundNow() {
+        addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
+        addPhoneLookup("650-123-1233", new Object[][] {});
+
+        ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
+        verifyParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
+                null, null);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/ActionServiceSystemTest.java b/tests/src/com/android/messaging/datamodel/action/ActionServiceSystemTest.java
new file mode 100644
index 0000000..725f159
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/ActionServiceSystemTest.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.Factory;
+import com.android.messaging.FakeContext;
+import com.android.messaging.FakeContext.FakeContextHost;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.BugleServiceTestCase;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener;
+import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
+
+@MediumTest
+public class ActionServiceSystemTest extends BugleServiceTestCase<ActionServiceImpl>
+        implements ActionCompletedListener, ActionExecutedListener, FakeContextHost {
+    private static final String TAG = "ActionServiceSystemTest";
+
+    static {
+        // Set flag during loading of test cases to prevent application initialization starting
+        BugleTestCase.setTestsRunning();
+    }
+
+    @Override
+    public void onActionSucceeded(final ActionMonitor monitor,
+            final Action action, final Object data, final Object result) {
+        final TestChatAction test = (TestChatAction) action;
+        assertEquals("Expect correct action parameter", parameter, test.parameter);
+        final ResultTracker tracker = (ResultTracker) data;
+        tracker.completionResult = result;
+        synchronized(tracker) {
+            tracker.notifyAll();
+        }
+    }
+
+    @Override
+    public void onActionFailed(final ActionMonitor monitor, final Action action,
+            final Object data, final Object result) {
+        final TestChatAction test = (TestChatAction) action;
+        assertEquals("Expect correct action parameter", parameter, test.parameter);
+        final ResultTracker tracker = (ResultTracker) data;
+        tracker.completionResult = result;
+        synchronized(tracker) {
+            tracker.notifyAll();
+        }
+    }
+
+    @Override
+    public void onActionExecuted(final ActionMonitor monitor, final Action action,
+            final Object data, final Object result) {
+        final TestChatAction test = (TestChatAction) action;
+        assertEquals("Expect correct action parameter", parameter, test.parameter);
+        final ResultTracker tracker = (ResultTracker) data;
+        tracker.executionResult = result;
+    }
+
+    public ActionServiceSystemTest() {
+        super(ActionServiceImpl.class);
+    }
+
+    public void testChatActionSucceeds() {
+        final ResultTracker tracker = new ResultTracker();
+
+        final ActionService service = DataModel.get().getActionService();
+        final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
+        final TestChatAction initial = new TestChatAction(monitor.getActionKey(), parameter);
+
+        assertNull("Expect completion result to start null", tracker.completionResult);
+        assertNull("Expect execution result to start null", tracker.executionResult);
+
+        final Parcel parcel = Parcel.obtain();
+        parcel.writeParcelable(initial, 0);
+        parcel.setDataPosition(0);
+        final TestChatAction action = parcel.readParcelable(mContext.getClassLoader());
+
+        synchronized(mWorker) {
+            try {
+                action.start(monitor);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for execution", false);
+            }
+        }
+
+        assertEquals("Expect to see 1 server request queued", 1,
+                mWorker.getRequestsMade().size());
+        final Action request = mWorker.getRequestsMade().get(0);
+        assertTrue("Expect Test type", request instanceof TestChatAction);
+
+        final Bundle response = new Bundle();
+        response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
+        synchronized(tracker) {
+            try {
+                request.markBackgroundWorkStarting();
+                request.markBackgroundWorkQueued();
+
+                request.markBackgroundWorkStarting();
+                request.markBackgroundCompletionQueued();
+                service.handleResponseFromBackgroundWorker(request, response);
+                // Wait for callback across threads
+                tracker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for response processing", false);
+            }
+        }
+
+        // TODO
+        //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
+        assertEquals("Expect completion result set", processResponseResult,
+                tracker.completionResult);
+    }
+
+    public void testChatActionFails() {
+        final ResultTracker tracker = new ResultTracker();
+
+        final ActionService service = DataModel.get().getActionService();
+        final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
+        final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
+
+        assertNull("Expect completion result to start null", tracker.completionResult);
+        assertNull("Expect execution result to start null", tracker.executionResult);
+
+        synchronized(mWorker) {
+            try {
+                action.start(monitor);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for requests", false);
+            }
+        }
+
+        assertEquals("Expect to see 1 server request queued", 1,
+                mWorker.getRequestsMade().size());
+        final Action request = mWorker.getRequestsMade().get(0);
+        assertTrue("Expect Test type", request instanceof TestChatAction);
+
+        synchronized(tracker) {
+            try {
+                request.markBackgroundWorkStarting();
+                request.markBackgroundWorkQueued();
+
+                request.markBackgroundWorkStarting();
+                request.markBackgroundCompletionQueued();
+                service.handleFailureFromBackgroundWorker(request, new Exception("It went wrong"));
+                // Wait for callback across threads
+                tracker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for response processing", false);
+            }
+        }
+
+        // TODO
+        //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
+        assertEquals("Expect completion result set", processFailureResult,
+                tracker.completionResult);
+    }
+
+    public void testChatActionNoMonitor() {
+        final ActionService service = DataModel.get().getActionService();
+        final TestChatAction action =
+                new TestChatAction(Action.generateUniqueActionKey(null), parameter);
+
+        synchronized(mWorker) {
+            try {
+                action.start();
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for execution", false);
+            }
+        }
+
+        assertEquals("Expect to see 1 server request queued", 1,
+                mWorker.getRequestsMade().size());
+        Action request = mWorker.getRequestsMade().get(0);
+        assertTrue("Expect Test type", request instanceof TestChatAction);
+
+        final Bundle response = new Bundle();
+        response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
+        synchronized(mWorker) {
+            try {
+                service.handleResponseFromBackgroundWorker(request, response);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for response processing", false);
+            }
+        }
+
+        assertEquals("Expect to see second server request queued",
+                2, mWorker.getRequestsMade().size());
+        request = mWorker.getRequestsMade().get(1);
+        assertTrue("Expect other type",
+                request instanceof TestChatActionOther);
+    }
+
+    public void testChatActionUnregisterListener() {
+        final ResultTracker tracker = new ResultTracker();
+
+        final ActionService service = DataModel.get().getActionService();
+        final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
+        final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
+
+        assertNull("Expect completion result to start null", tracker.completionResult);
+        assertNull("Expect execution result to start null", tracker.executionResult);
+
+        synchronized(mWorker) {
+            try {
+                action.start(monitor);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for execution", false);
+            }
+        }
+
+        assertEquals("Expect to see 1 server request queued", 1,
+                mWorker.getRequestsMade().size());
+        final Action request = mWorker.getRequestsMade().get(0);
+        assertTrue("Expect Test type", request instanceof TestChatAction);
+
+        monitor.unregister();
+
+        final Bundle response = new Bundle();
+        synchronized(mWorker) {
+            try {
+                request.markBackgroundWorkStarting();
+                request.markBackgroundWorkQueued();
+
+                request.markBackgroundWorkStarting();
+                request.markBackgroundCompletionQueued();
+                service.handleResponseFromBackgroundWorker(request, response);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for response processing", false);
+            }
+        }
+
+        //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
+        assertEquals("Expect completion never called", null, tracker.completionResult);
+    }
+
+    StubBackgroundWorker mWorker;
+    FakeContext mContext;
+    StubLoader mLoader;
+
+    private static final String parameter = "parameter";
+    private static final Object executeActionResult = "executeActionResult";
+    private static final String processResponseResult = "processResponseResult";
+    private static final Object processFailureResult = "processFailureResult";
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        Log.d(TAG, "ChatActionTest setUp");
+
+        mContext = new FakeContext(getContext(), this);
+        mWorker = new StubBackgroundWorker();
+        FakeFactory.registerWithFakeContext(getContext(), mContext)
+                .withDataModel(new FakeDataModel(mContext)
+                .withBackgroundWorkerForActionService(mWorker)
+                .withActionService(new ActionService()));
+
+        mLoader = new StubLoader();
+        setContext(Factory.get().getApplicationContext());
+    }
+
+    @Override
+    public String getServiceClassName() {
+        return ActionServiceImpl.class.getName();
+    }
+
+    @Override
+    public void startServiceForStub(final Intent intent) {
+        this.startService(intent);
+    }
+
+    @Override
+    public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
+        this.getService().onStartCommand(intent, flags, startId);
+    }
+
+    public static class TestChatAction extends Action implements Parcelable {
+        public static String RESPONSE_TEST = "response_test";
+        public static String KEY_PARAMETER = "parameter";
+
+        protected TestChatAction(final String key, final String parameter) {
+            super(key);
+            this.actionParameters.putString(KEY_PARAMETER, parameter);
+            // Cache parameter as a member variable
+            this.parameter = parameter;
+        }
+
+        // An example parameter
+        public final String parameter;
+
+        /**
+         * Process the action locally - runs on datamodel service thread
+         */
+        @Override
+        protected Object executeAction() {
+            requestBackgroundWork();
+            return executeActionResult;
+        }
+
+        /**
+         * Process the response from the server - runs on datamodel service thread
+         */
+        @Override
+        protected Object processBackgroundResponse(final Bundle response) {
+            requestBackgroundWork(new TestChatActionOther(null, parameter));
+            return response.get(RESPONSE_TEST);
+        }
+
+        /**
+         * Called in case of failures when sending requests - runs on datamodel service thread
+         */
+        @Override
+        protected Object processBackgroundFailure() {
+            return processFailureResult;
+        }
+
+        private TestChatAction(final Parcel in) {
+            super(in);
+            // Cache parameter as a member variable
+            parameter = actionParameters.getString(KEY_PARAMETER);
+        }
+
+        public static final Parcelable.Creator<TestChatAction> CREATOR
+                = new Parcelable.Creator<TestChatAction>() {
+            @Override
+            public TestChatAction createFromParcel(final Parcel in) {
+                return new TestChatAction(in);
+            }
+
+            @Override
+            public TestChatAction[] newArray(final int size) {
+                return new TestChatAction[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel parcel, final int flags) {
+            writeActionToParcel(parcel, flags);
+        }
+    }
+
+    public static class TestChatActionOther extends Action implements Parcelable {
+        protected TestChatActionOther(final String key, final String parameter) {
+            super(generateUniqueActionKey(key));
+            this.parameter = parameter;
+        }
+
+        public final String parameter;
+
+        private TestChatActionOther(final Parcel in) {
+            super(in);
+            parameter = in.readString();
+        }
+
+        public static final Parcelable.Creator<TestChatActionOther> CREATOR
+                = new Parcelable.Creator<TestChatActionOther>() {
+            @Override
+            public TestChatActionOther createFromParcel(final Parcel in) {
+                return new TestChatActionOther(in);
+            }
+
+            @Override
+            public TestChatActionOther[] newArray(final int size) {
+                return new TestChatActionOther[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel parcel, final int flags) {
+            writeActionToParcel(parcel, flags);
+            parcel.writeString(parameter);
+        }
+    }
+
+    /**
+     * An operation that notifies a listener upon completion
+     */
+    public static class TestChatActionMonitor extends ActionMonitor {
+        /**
+         * Create action state wrapping an BlockUserAction instance
+         * @param account - account in which to block the user
+         * @param baseKey - suggested action key from BlockUserAction
+         * @param data - optional action specific data that is handed back to listener
+         * @param listener - action completed listener
+         */
+        public TestChatActionMonitor(final String baseKey, final Object data,
+                final ActionCompletedListener completed, final ActionExecutedListener executed) {
+            super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
+            setCompletedListener(completed);
+            setExecutedListener(executed);
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/ActionServiceTest.java b/tests/src/com/android/messaging/datamodel/action/ActionServiceTest.java
new file mode 100644
index 0000000..19c6c00
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/ActionServiceTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.Factory;
+import com.android.messaging.FakeContext;
+import com.android.messaging.FakeContext.FakeContextHost;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.BugleServiceTestCase;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
+import com.android.messaging.datamodel.action.ActionMonitor.ActionStateChangedListener;
+import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
+
+import java.util.ArrayList;
+
+@MediumTest
+public class ActionServiceTest extends BugleServiceTestCase<ActionServiceImpl>
+        implements FakeContextHost, ActionStateChangedListener, ActionCompletedListener {
+    private static final String TAG = "ActionServiceTest";
+
+    @Override
+    public void onActionStateChanged(final Action action, final int state) {
+        mStates.add(state);
+    }
+
+    @Override
+    public void onActionSucceeded(final ActionMonitor monitor,
+            final Action action, final Object data, final Object result) {
+        final TestChatAction test = (TestChatAction) action;
+        assertNotSame(test.dontRelyOnMe, dontRelyOnMe);
+        // This will be true - but only briefly
+        assertEquals(test.dontRelyOnMe, becauseIChange);
+
+        final ResultTracker tracker = (ResultTracker) data;
+        tracker.completionResult = result;
+        synchronized(tracker) {
+            tracker.notifyAll();
+        }
+    }
+
+    @Override
+    public void onActionFailed(final ActionMonitor monitor, final Action action,
+            final Object data, final Object result) {
+        final TestChatAction test = (TestChatAction) action;
+        assertNotSame(test.dontRelyOnMe, dontRelyOnMe);
+        // This will be true - but only briefly
+        assertEquals(test.dontRelyOnMe, becauseIChange);
+
+        final ResultTracker tracker = (ResultTracker) data;
+        tracker.completionResult = result;
+        synchronized(tracker) {
+            tracker.notifyAll();
+        }
+    }
+
+    /**
+     * For a chat action verify that the service intent is constructed and queued correctly and
+     * that when that intent is processed it actually executes the action.
+     */
+    public void testChatServiceCreatesIntentAndExecutesAction() {
+        final ResultTracker tracker = new ResultTracker();
+
+        final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
+        final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
+
+        action.dontRelyOnMe = dontRelyOnMe;
+        assertFalse("Expect service initially stopped", mServiceStarted);
+
+        synchronized(mWorker) {
+            try {
+                action.start(monitor);
+                // Wait for callback across threads
+                mWorker.wait(2000);
+                mServiceStarted = true;
+            } catch (final InterruptedException e) {
+                assertTrue("Interrupted waiting for execution", false);
+            }
+        }
+
+        assertTrue("Expect service started", mServiceStarted);
+
+        assertEquals("Expect three states ", mStates.size(), 3);
+        assertEquals("State-0 should be STATE_QUEUED", (int)mStates.get(0),
+                ActionMonitor.STATE_QUEUED);
+        assertEquals("State-1 should be STATE_EXECUTING", (int)mStates.get(1),
+                ActionMonitor.STATE_EXECUTING);
+        assertEquals("State-2 should be STATE_COMPLETE", (int)mStates.get(2),
+                ActionMonitor.STATE_COMPLETE);
+    }
+
+    StubBackgroundWorker mWorker;
+    FakeContext mContext;
+    StubLoader mLoader;
+    ActionService mService;
+
+    ArrayList<Integer> mStates;
+
+    private static final String parameter = "parameter";
+    private static final Object dontRelyOnMe = "dontRelyOnMe";
+    private static final Object becauseIChange = "becauseIChange";
+    private static final Object executeActionResult = "executeActionResult";
+    private static final Object processResponseResult = "processResponseResult";
+    private static final Object processFailureResult = "processFailureResult";
+
+    public ActionServiceTest() {
+        super(ActionServiceImpl.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        Log.d(TAG, "ChatActionTest setUp");
+
+        sLooper = Looper.myLooper();
+
+        mWorker = new StubBackgroundWorker();
+        mContext = new FakeContext(getContext(), this);
+        FakeFactory.registerWithFakeContext(getContext(),mContext)
+                .withDataModel(new FakeDataModel(mContext)
+                .withBackgroundWorkerForActionService(mWorker)
+                .withActionService(new ActionService()));
+
+        mStates = new ArrayList<Integer>();
+        setContext(Factory.get().getApplicationContext());
+    }
+
+    @Override
+    public String getServiceClassName() {
+        return ActionServiceImpl.class.getName();
+    }
+
+    boolean mServiceStarted = false;
+
+    @Override
+    public void startServiceForStub(final Intent intent) {
+        // Do nothing until later
+        assertFalse(mServiceStarted);
+        mServiceStarted = true;
+    }
+
+    @Override
+    public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
+        assertTrue(mServiceStarted);
+    }
+
+    private static Looper sLooper;
+    public static void assertRunsOnOtherThread() {
+        assertTrue (Looper.myLooper() != Looper.getMainLooper());
+        assertTrue (Looper.myLooper() != sLooper);
+    }
+
+    public static class TestChatAction extends Action implements Parcelable {
+        public static String RESPONSE_TEST = "response_test";
+        public static String KEY_PARAMETER = "parameter";
+
+        protected TestChatAction(final String key, final String parameter) {
+            super(key);
+            this.actionParameters.putString(KEY_PARAMETER, parameter);
+        }
+
+        transient Object dontRelyOnMe;
+
+        /**
+         * Process the action locally - runs on service thread
+         */
+        @Override
+        protected Object executeAction() {
+            this.dontRelyOnMe = becauseIChange;
+            assertRunsOnOtherThread();
+            return executeActionResult;
+        }
+
+        /**
+         * Process the response from the server - runs on service thread
+         */
+        @Override
+        protected Object processBackgroundResponse(final Bundle response) {
+            assertRunsOnOtherThread();
+            return processResponseResult;
+        }
+
+        /**
+         * Called in case of failures when sending requests - runs on service thread
+         */
+        @Override
+        protected Object processBackgroundFailure() {
+            assertRunsOnOtherThread();
+            return processFailureResult;
+        }
+
+        private TestChatAction(final Parcel in) {
+            super(in);
+        }
+
+        public static final Parcelable.Creator<TestChatAction> CREATOR
+                = new Parcelable.Creator<TestChatAction>() {
+            @Override
+            public TestChatAction createFromParcel(final Parcel in) {
+                return new TestChatAction(in);
+            }
+
+            @Override
+            public TestChatAction[] newArray(final int size) {
+                return new TestChatAction[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel parcel, final int flags) {
+            writeActionToParcel(parcel, flags);
+        }
+    }
+
+    /**
+     * An operation that notifies a listener upon state changes, execution and completion
+     */
+    public static class TestChatActionMonitor extends ActionMonitor {
+        public TestChatActionMonitor(final String baseKey, final Object data,
+                final ActionStateChangedListener listener, final ActionCompletedListener executed) {
+            super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
+            setStateChangedListener(listener);
+            setCompletedListener(executed);
+            assertEquals("Initial state should be STATE_CREATED", mState, STATE_CREATED);
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/ActionTest.java b/tests/src/com/android/messaging/datamodel/action/ActionTest.java
new file mode 100644
index 0000000..c24884d
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/ActionTest.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.DataModelImpl;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubChatActionMonitor;
+
+import java.util.ArrayList;
+
+@MediumTest
+public class ActionTest extends BugleTestCase {
+    private static final String parameter = "parameter";
+    private static final Object executeActionResult = "executeActionResult";
+    private static final Object processResponseResult = "processResponseResult";
+    private static final Object processFailureResult = "processFailureResult";
+
+    private static final String mActionKey = "TheActionKey";
+    private static final Object mData = "PrivateData";
+    private StubChatActionMonitor mMonitor;
+    private TestChatAction mAction;
+
+    private ArrayList<StubChatActionMonitor.StateTransition> mTransitions;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext())
+                .withDataModel(new DataModelImpl(getContext()));
+
+        mMonitor = new StubChatActionMonitor(ActionMonitor.STATE_CREATED, mActionKey,
+                mData);
+        mAction = new TestChatAction(mActionKey, parameter);
+        mTransitions = mMonitor.getTransitions();
+    }
+
+    private void verifyState(final int count, final int from, final int to) {
+        assertEquals(to, mMonitor.getState());
+        assertEquals(mTransitions.size(), count);
+        verifyTransition(count-1, from , to);
+    }
+
+    private void verifyTransition(final int index, final int from, final int to) {
+        assertTrue(mTransitions.size() > index);
+        assertEquals(mAction, mTransitions.get(index).action);
+        assertEquals(from, mTransitions.get(index).from);
+        assertEquals(to, mTransitions.get(index).to);
+    }
+
+    @SmallTest
+    public void testActionStartTransitionsCorrectly() {
+        mMonitor.setState(ActionMonitor.STATE_CREATED);
+
+        ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.markStart();
+        assertEquals("After start state: STATE_QUEUED", ActionMonitor.STATE_QUEUED,
+                mMonitor.getState());
+        verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
+
+        ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
+
+        assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+    }
+
+    @SmallTest
+    public void testActionStartAssertsFromIncorrectState() {
+        mMonitor.setState(ActionMonitor.STATE_UNDEFINED);
+
+        ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        try {
+            mAction.markStart();
+            fail("Expect assertion when starting from STATE_UNDEFINED");
+        } catch (final IllegalStateException ex){
+        }
+        ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
+
+        assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+    }
+
+    public void testActionTransitionsEndToEndWithRequests() {
+        assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
+                mMonitor.getState());
+
+        ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.markStart();
+
+        verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
+
+        mAction.markBeginExecute();
+
+        verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
+
+        final Object result = mAction.executeAction();
+        mAction.requestBackgroundWork();
+
+        assertEquals("Check executeAction result", result, executeActionResult);
+
+        mAction.markEndExecute(result);
+
+        verifyState(3, ActionMonitor.STATE_EXECUTING,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
+
+        mAction.markBackgroundWorkStarting();
+
+        verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
+
+        mAction.markBackgroundWorkQueued();
+
+        verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
+
+        mAction.markBackgroundWorkStarting();
+
+        verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
+
+        final Bundle response = null;
+
+        mAction.markBackgroundCompletionQueued();
+
+        verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED);
+
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.processBackgroundWorkResponse(response);
+
+        verifyTransition(7, ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED,
+                ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE);
+
+        verifyState(9, ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE,
+                ActionMonitor.STATE_COMPLETE);
+
+        assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+    }
+
+    public void testActionTransitionsEndToEndFailsRequests() {
+        assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
+                mMonitor.getState());
+
+        ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.markStart();
+
+        verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
+
+        mAction.markBeginExecute();
+
+        verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
+
+        final Object result = mAction.executeAction();
+        mAction.requestBackgroundWork();
+
+        assertEquals("Check executeAction result", result, executeActionResult);
+
+        mAction.markEndExecute(result);
+
+        verifyState(3, ActionMonitor.STATE_EXECUTING,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
+
+        mAction.markBackgroundWorkStarting();
+
+        verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
+
+        mAction.markBackgroundWorkQueued();
+
+        verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
+
+        mAction.markBackgroundWorkStarting();
+
+        verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
+                ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
+
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.processBackgroundWorkFailure();
+
+        verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
+                ActionMonitor.STATE_COMPLETE);
+
+        assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+    }
+
+    public void testActionTransitionsEndToEndNoRequests() {
+        assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
+                mMonitor.getState());
+
+        ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.markStart();
+
+        verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
+
+        mAction.markBeginExecute();
+
+        verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
+
+        final Object result = mAction.executeAction();
+
+        assertEquals("Check executeAction result", result, executeActionResult);
+
+        assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+        assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
+
+        mAction.markEndExecute(result);
+
+        verifyState(3, ActionMonitor.STATE_EXECUTING,
+                ActionMonitor.STATE_COMPLETE);
+
+        assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
+        assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
+    }
+
+    public static class TestChatAction extends Action implements Parcelable {
+        protected TestChatAction(final String key, final String parameter) {
+            super(key);
+            this.parameter = parameter;
+        }
+
+        public final String parameter;
+
+        /**
+         * Process the action locally - runs on service thread
+         */
+        @Override
+        protected Object executeAction() {
+            assertEquals("Check parameter", parameter, ActionTest.parameter);
+            return executeActionResult;
+        }
+
+        /**
+         * Process the response from the server - runs on service thread
+         */
+        @Override
+        protected Object processBackgroundResponse(final Bundle response) {
+            assertEquals("Check parameter", parameter, ActionTest.parameter);
+            return processResponseResult;
+        }
+
+        /**
+         * Called in case of failures when sending requests - runs on service thread
+         */
+        @Override
+        protected Object processBackgroundFailure() {
+            assertEquals("Check parameter", parameter, ActionTest.parameter);
+            return processFailureResult;
+        }
+
+        private TestChatAction(final Parcel in) {
+            super(in);
+            parameter = in.readString();
+        }
+
+        public static final Parcelable.Creator<TestChatAction> CREATOR
+                = new Parcelable.Creator<TestChatAction>() {
+            @Override
+            public TestChatAction createFromParcel(final Parcel in) {
+                return new TestChatAction(in);
+            }
+
+            @Override
+            public TestChatAction[] newArray(final int size) {
+                return new TestChatAction[size];
+            }
+        };
+
+        @Override
+        public void writeToParcel(final Parcel parcel, final int flags) {
+            writeActionToParcel(parcel, flags);
+            parcel.writeString(parameter);
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/ActionTestHelpers.java b/tests/src/com/android/messaging/datamodel/action/ActionTestHelpers.java
new file mode 100644
index 0000000..00aa267
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/ActionTestHelpers.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActionTestHelpers {
+    private static final String TAG = "DataModelTestHelpers";
+
+    static class StubLoader extends ContentObserver {
+        ArrayList<Uri> mUriList = new ArrayList<Uri>();
+
+        StubLoader() {
+            super(null);
+        }
+
+        public void clear() {
+            mUriList.clear();
+        }
+
+        @Override
+        public void onChange(final boolean selfChange) {
+            // Handle change.
+            mUriList.add(null);
+        }
+
+        // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
+        // Only supported on platform 16 and above...
+        @Override
+        public void onChange(final boolean selfChange, final Uri uri) {
+            // Handle change.
+            mUriList.add(uri);
+        }
+    }
+
+    static class StubBackgroundWorker extends BackgroundWorker {
+        public StubBackgroundWorker() {
+            super();
+            mActions = new ArrayList<Action>();
+        }
+
+        ArrayList<Action> mActions;
+        public ArrayList<Action> getRequestsMade() {
+            return mActions;
+        }
+
+        @Override
+        public void queueBackgroundWork(final List<Action> actions) {
+            mActions.addAll(actions);
+
+            synchronized(this) {
+                this.notifyAll();
+            }
+        }
+    }
+
+    static class ResultTracker {
+        public Object executionResult;
+        public Object completionResult;
+    }
+
+    static class StubChatActionMonitor extends ActionMonitor {
+        static public class StateTransition {
+            Action action;
+            int from;
+            int to;
+            public StateTransition(final Action action, final int from, final int to) {
+                this.action = action;
+                this.from = from;
+                this.to = to;
+            }
+        }
+
+        private final ArrayList<StateTransition> mTransitions;
+        public ArrayList<StateTransition> getTransitions() {
+            return mTransitions;
+        }
+
+        protected StubChatActionMonitor(final int initialState, final String actionKey,
+                final Object data) {
+            super(initialState, actionKey, data);
+            mTransitions =  new ArrayList<StateTransition>();
+        }
+
+        @Override
+        protected void updateState(final Action action, final int expectedState,
+                final int state) {
+            mTransitions.add(new StateTransition(action, mState, state));
+            super.updateState(action, expectedState, state);
+        }
+
+        public void setState(final int state) {
+            mState = state;
+        }
+
+        public int getState() {
+            return mState;
+        }
+    }
+
+    public static class StubActionService extends ActionService {
+        public static class StubActionServiceCallLog {
+            public final Action action;
+            public final Action request;
+            public final Bundle response;
+            public final Exception exception;
+            public final Action update;
+
+            public StubActionServiceCallLog(final Action action,
+                    final Action request,
+                    final Bundle response,
+                    final Exception exception,
+                    final Action update) {
+                this.action = action;
+                this.request = request;
+                this.response = response;
+                this.exception = exception;
+                this.update = update;
+            }
+        }
+
+        private final ArrayList<StubActionServiceCallLog> mServiceCalls =
+                new ArrayList<StubActionServiceCallLog>();
+
+        public ArrayList<StubActionServiceCallLog> getCalls() {
+            return mServiceCalls;
+        }
+
+        @Override
+        public void startAction(final Action action) {
+            mServiceCalls.add(new StubActionServiceCallLog(action, null, null, null, null));
+            synchronized(this) {
+                this.notifyAll();
+            }
+        }
+
+        @Override
+        public void handleResponseFromBackgroundWorker(final Action request,
+                final Bundle response) {
+            mServiceCalls.add(new StubActionServiceCallLog(null, request, response, null, null));
+            synchronized(this) {
+                this.notifyAll();
+            }
+        }
+
+        @Override
+        protected void handleFailureFromBackgroundWorker(final Action request,
+                final Exception exception) {
+            mServiceCalls.add(new StubActionServiceCallLog(null, request, null, exception, null));
+            synchronized(this) {
+                this.notifyAll();
+            }
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/GetOrCreateConversationActionTest.java b/tests/src/com/android/messaging/datamodel/action/GetOrCreateConversationActionTest.java
new file mode 100644
index 0000000..24f488a
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/GetOrCreateConversationActionTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.test.mock.MockContentProvider;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeContext;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.sms.MmsUtils;
+
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+
+@SmallTest
+public class GetOrCreateConversationActionTest extends BugleTestCase {
+
+    @Mock GetOrCreateConversationActionListener mockListener;
+
+    public void testGetOrCreateConversation() {
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final ArrayList<String> recipients = new ArrayList<String>();
+        recipients.add("5551234567");
+        recipients.add("5551234568");
+
+        // Generate a list of partially formed participants
+        final ArrayList<ParticipantData> participants = new
+                ArrayList<ParticipantData>();
+
+
+        for (final String recipient : recipients) {
+            participants.add(ParticipantData.getFromRawPhoneBySystemLocale(recipient));
+        }
+
+        // Test that we properly stubbed the SMS provider to return a thread id
+        final long threadId = MmsUtils.getOrCreateThreadId(mContext, recipients);
+        assertEquals(TestDataFactory.SMS_MMS_THREAD_ID_CURSOR_VALUE, threadId);
+
+        ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+        GetOrCreateConversationActionMonitor monitor =
+                GetOrCreateConversationAction.getOrCreateConversation(participants, null,
+                        mockListener);
+
+        assertEquals("Failed to start service once for action", calls.size(), 1);
+        assertTrue("Action not GetOrCreateConversationAction", calls.get(0).action instanceof
+                GetOrCreateConversationAction);
+
+        GetOrCreateConversationAction action = (GetOrCreateConversationAction)
+                calls.get(0).action;
+
+        Object result = action.executeAction();
+
+        assertTrue(result instanceof String);
+
+        // Make sure that we created a new conversation
+        int expectedConversationId = TestDataFactory.NUM_TEST_CONVERSATIONS + 1;
+        assertEquals(expectedConversationId, Integer.parseInt((String) result));
+
+        // Now get the conversation that we just created again
+        monitor = GetOrCreateConversationAction.getOrCreateConversation(participants, null,
+                        mockListener);
+
+        calls = mService.getCalls();
+        assertEquals("Failed to start service for second action", calls.size(), 2);
+        assertTrue("Action not GetOrCreateConversationAction", calls.get(1).action instanceof
+                GetOrCreateConversationAction);
+        action = (GetOrCreateConversationAction)calls.get(1).action;
+        result = action.executeAction();
+
+        assertTrue(result instanceof String);
+
+        final String conversationId = (String) result;
+
+        // Make sure that we found the same conversation id
+        assertEquals(expectedConversationId, Integer.parseInt((String) result));
+
+        final ArrayList<ParticipantData> conversationParticipants =
+                BugleDatabaseOperations.getParticipantsForConversation(db, conversationId);
+
+        assertEquals("Participant count mismatch", recipients.size(),
+                conversationParticipants.size());
+        for(final ParticipantData participant : conversationParticipants) {
+            assertTrue(recipients.contains(participant.getSendDestination()));
+        }
+
+        final Uri conversationParticipantsUri =
+                MessagingContentProvider.buildConversationParticipantsUri(conversationId);
+        final Cursor cursor = mContext.getContentResolver().query(conversationParticipantsUri,
+                ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
+
+        int countSelf = 0;
+        while(cursor.moveToNext()) {
+            final ParticipantData participant = ParticipantData.getFromCursor(cursor);
+            if (participant.isSelf()) {
+                countSelf++;
+            } else {
+                assertTrue(recipients.contains(participant.getSendDestination()));
+            }
+        }
+        cursor.close();
+        assertEquals("Expect one self participant in conversations", 1, countSelf);
+        assertEquals("Cursor count mismatch", recipients.size(), cursor.getCount() - countSelf);
+
+        final String realId = BugleDatabaseOperations.getExistingConversation(db, threadId, false);
+        assertEquals("Conversation already exists", realId, conversationId);
+    }
+
+    private FakeContext mContext;
+    private StubActionService mService;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mContext = new FakeContext(getTestContext());
+
+        final MockContentProvider mockProvider = new MockContentProvider() {
+            @Override
+            public Cursor query(final Uri uri, final String[] projection, final String selection,
+                    final String[] selectionArgs, final String sortOrder) {
+                return TestDataFactory.getSmsMmsThreadIdCursor();
+            }
+        };
+
+        mContext.addContentProvider("mms-sms", mockProvider);
+        final MessagingContentProvider provider = new MessagingContentProvider();
+        final ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.authority = MessagingContentProvider.AUTHORITY;
+        provider.attachInfo(mContext, providerInfo);
+        mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
+
+        mService = new StubActionService();
+        final FakeDataModel fakeDataModel = new FakeDataModel(mContext)
+            .withActionService(mService);
+        FakeFactory.registerWithFakeContext(getTestContext(), mContext)
+                .withDataModel(fakeDataModel);
+        provider.setDatabaseForTest(fakeDataModel.getDatabase());
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/action/ReadWriteDraftMessageActionTest.java b/tests/src/com/android/messaging/datamodel/action/ReadWriteDraftMessageActionTest.java
new file mode 100644
index 0000000..518a722
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/action/ReadWriteDraftMessageActionTest.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.action;
+
+import android.content.ContentProvider;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeContext;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseWrapper;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.MediaScratchFileProvider;
+import com.android.messaging.datamodel.MessagingContentProvider;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
+import com.android.messaging.datamodel.action.ReadDraftDataAction.ReadDraftDataActionListener;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.util.ContentType;
+
+import org.mockito.Mock;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+@SmallTest
+public class ReadWriteDraftMessageActionTest extends BugleTestCase {
+
+    @Mock ReadDraftDataActionListener mockListener;
+
+    // TODO: Add test cases
+    //  1. Make sure drafts can include attachments and multiple parts
+    //  2. Make sure attachments get cleaned up appropriately
+    //  3. Make sure messageId and partIds not reused (currently each draft is a new message).
+    public void testWriteDraft() {
+        final String draftMessage = "draftMessage";
+        final long threadId = 1234567;
+        final boolean senderBlocked = false;
+        final String participantNumber = "5551234567";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
+                senderBlocked);
+        final String selfId = getOrCreateSelfId(db);
+
+        // Should clear/stub DB
+        final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+        final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
+                draftMessage);
+
+        WriteDraftMessageAction.writeDraftMessage(conversationId, message);
+
+        assertEquals("Failed to start service once for action", calls.size(), 1);
+        assertTrue("Action not SaveDraftMessageAction",
+                calls.get(0).action instanceof WriteDraftMessageAction);
+
+        final Action save = calls.get(0).action;
+
+        final Object result = save.executeAction();
+
+        assertTrue("Expect row number string as result", result instanceof String);
+        final String messageId = (String) result;
+
+        // Should check DB
+        final MessageData actual = BugleDatabaseOperations.readMessage(db, messageId);
+        assertNotNull("Database missing draft", actual);
+        assertEquals("Draft text changed", draftMessage, actual.getMessageText());
+    }
+
+    private static String getOrCreateSelfId(final DatabaseWrapper db) {
+        db.beginTransaction();
+        final String selfId = BugleDatabaseOperations.getOrCreateParticipantInTransaction(db,
+                ParticipantData.getSelfParticipant(ParticipantData.DEFAULT_SELF_SUB_ID));
+        db.setTransactionSuccessful();
+        db.endTransaction();
+        return selfId;
+    }
+
+    private static String getOrCreateConversation(final DatabaseWrapper db,
+            final String participantNumber, final long threadId, final boolean senderBlocked) {
+        final ArrayList<ParticipantData> participants =
+                new ArrayList<ParticipantData>();
+        participants.add(ParticipantData.getFromRawPhoneBySystemLocale(participantNumber));
+
+        final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                senderBlocked, participants, false, false, null);
+        assertNotNull("No conversation", conversationId);
+        return conversationId;
+    }
+
+    public void testReadDraft() {
+        final Object data = "data";
+        final String draftMessage = "draftMessage";
+        final long threadId = 1234567;
+        final boolean senderBlocked = false;
+        final String participantNumber = "5552345678";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
+                senderBlocked);
+        final String selfId = getOrCreateSelfId(db);
+
+        // Should clear/stub DB
+        final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+        final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
+                draftMessage);
+
+        BugleDatabaseOperations.updateDraftMessageData(db, conversationId, message,
+                BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+
+        final ActionMonitor monitor =
+                ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
+
+        assertEquals("Unexpected number of calls to service", 1, calls.size());
+        assertTrue("Action not of type ReadDraftMessageAction",
+                calls.get(0).action instanceof ReadDraftDataAction);
+
+        final Action read = calls.get(0).action;
+
+        final Object result = read.executeAction();
+
+        assertTrue(result instanceof ReadDraftDataAction.DraftData);
+        final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
+
+        assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
+        assertEquals("Draft self differs", selfId, draft.message.getSelfId());
+        assertEquals("Draft conversation differs", conversationId,
+                draft.conversation.getConversationId());
+    }
+
+    public void testReadDraftForNewConversation() {
+        final Object data = "data";
+        long threadId = 1234567;
+        final boolean senderBlocked = false;
+        long phoneNumber = 5557654567L;
+        final String notConversationId = "ThisIsNotValidConversationId";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final String selfId = getOrCreateSelfId(db);
+
+        // Unless set a new conversation should have a null draft message
+        final MessageData blank = BugleDatabaseOperations.readDraftMessageData(db,
+                notConversationId, selfId);
+        assertNull(blank);
+
+        String conversationId = null;
+        do {
+            conversationId = BugleDatabaseOperations.getExistingConversation(db,
+                    threadId, senderBlocked);
+            threadId++;
+            phoneNumber++;
+        }
+        while(!TextUtils.isEmpty(conversationId));
+
+        final ArrayList<ParticipantData> participants =
+                new ArrayList<ParticipantData>();
+        participants.add(ParticipantData.getFromRawPhoneBySystemLocale(Long.toString(phoneNumber)));
+
+        conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
+                senderBlocked, participants, false, false, null);
+        assertNotNull("No conversation", conversationId);
+
+        final MessageData actual = BugleDatabaseOperations.readDraftMessageData(db, conversationId,
+                selfId);
+        assertNull(actual);
+
+        // Should clear/stub DB
+        final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+        final ActionMonitor monitor =
+                ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
+
+        assertEquals("Unexpected number of calls to service", 1, calls.size());
+        assertTrue("Action not of type ReadDraftMessageAction",
+                calls.get(0).action instanceof ReadDraftDataAction);
+
+        final Action read = calls.get(0).action;
+
+        final Object result = read.executeAction();
+
+        assertTrue(result instanceof ReadDraftDataAction.DraftData);
+        final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
+
+        assertEquals("Draft message text differs", "", draft.message.getMessageText());
+        assertEquals("Draft self differs", selfId, draft.message.getSelfId());
+        assertEquals("Draft conversation differs", conversationId,
+                draft.conversation.getConversationId());
+    }
+
+    public void testWriteAndReadDraft() {
+        final Object data = "data";
+        final String draftMessage = "draftMessage";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+        final Cursor conversations = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
+                new String[] { ConversationColumns._ID, ConversationColumns.CURRENT_SELF_ID }, null,
+                null, null /* groupBy */, null /* having */, null /* orderBy */);
+
+        if (conversations.moveToFirst()) {
+            final String conversationId = conversations.getString(0);
+            final String selfId = getOrCreateSelfId(db);
+
+            // Should clear/stub DB
+            final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+            final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
+                    draftMessage);
+
+            WriteDraftMessageAction.writeDraftMessage(conversationId, message);
+
+            assertEquals("Failed to start service once for action", calls.size(), 1);
+            assertTrue("Action not SaveDraftMessageAction",
+                    calls.get(0).action instanceof WriteDraftMessageAction);
+
+            final Action save = calls.get(0).action;
+
+            Object result = save.executeAction();
+
+            assertTrue("Expect row number string as result", result instanceof String);
+
+            // Should check DB
+
+            final ActionMonitor monitor =
+                    ReadDraftDataAction.readDraftData(conversationId, null, data,
+                            mockListener);
+
+            assertEquals("Expect two calls queued", 2, calls.size());
+            assertTrue("Expect action", calls.get(1).action instanceof ReadDraftDataAction);
+
+            final Action read = calls.get(1).action;
+
+            result = read.executeAction();
+
+            assertTrue(result instanceof ReadDraftDataAction.DraftData);
+            final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
+
+            assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
+            // The conversation's self id is used as the draft's self id.
+            assertEquals("Draft self differs", conversations.getString(1),
+                    draft.message.getSelfId());
+            assertEquals("Draft conversation differs", conversationId,
+                    draft.conversation.getConversationId());
+        } else {
+            fail("No conversations in database");
+        }
+    }
+
+    public void testUpdateDraft() {
+        final String initialMessage = "initialMessage";
+        final String draftMessage = "draftMessage";
+        final long threadId = 1234567;
+        final boolean senderBlocked = false;
+        final String participantNumber = "5553456789";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
+                senderBlocked);
+        final String selfId = getOrCreateSelfId(db);
+
+        final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
+
+        // Insert initial message
+        MessageData initial = MessageData.createDraftSmsMessage(conversationId, selfId,
+                initialMessage);
+
+        BugleDatabaseOperations.updateDraftMessageData(db, conversationId, initial,
+                BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+
+        initial = BugleDatabaseOperations.readDraftMessageData(db,
+                conversationId, selfId);
+        assertEquals("Initial text mismatch", initialMessage, initial.getMessageText());
+
+        // Now update the draft
+        final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
+                draftMessage);
+        WriteDraftMessageAction.writeDraftMessage(conversationId, message);
+
+        assertEquals("Failed to start service once for action", calls.size(), 1);
+        assertTrue("Action not SaveDraftMessageAction",
+                calls.get(0).action instanceof WriteDraftMessageAction);
+
+        final Action save = calls.get(0).action;
+
+        final Object result = save.executeAction();
+
+        assertTrue("Expect row number string as result", result instanceof String);
+
+        // Check DB
+        final MessageData actual =  BugleDatabaseOperations.readDraftMessageData(db,
+                conversationId, selfId);
+        assertNotNull("Database missing draft", actual);
+        assertEquals("Draft text mismatch", draftMessage, actual.getMessageText());
+        assertNull("Draft messageId should be null", actual.getMessageId());
+    }
+
+    public void testBugleDatabaseDraftOperations() {
+        final String initialMessage = "initialMessage";
+        final String draftMessage = "draftMessage";
+        final long threadId = 1234599;
+        final boolean senderBlocked = false;
+        final String participantNumber = "5553456798";
+        final String subject = "subject here";
+
+        final DatabaseWrapper db = DataModel.get().getDatabase();
+
+        final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
+                senderBlocked);
+        final String selfId = getOrCreateSelfId(db);
+
+        final String text = "This is some text";
+        final Uri mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
+        OutputStream outputStream = null;
+        try {
+            outputStream = mContext.getContentResolver().openOutputStream(mOutputUri);
+            outputStream.write(text.getBytes());
+        } catch (final FileNotFoundException e) {
+            fail("Cannot open output file");
+        } catch (final IOException e) {
+            fail("Cannot write output file");
+        }
+
+        final MessageData initial =
+                MessageData.createDraftMmsMessage(conversationId, selfId, initialMessage, subject);
+        initial.addPart(MessagePartData.createMediaMessagePart(ContentType.MULTIPART_MIXED,
+                mOutputUri, 0, 0));
+
+        final String initialMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
+                conversationId, initial, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+        assertNotNull(initialMessageId);
+
+        final MessageData initialDraft = BugleDatabaseOperations.readMessage(db, initialMessageId);
+        assertNotNull(initialDraft);
+        int cnt = 0;
+        for(final MessagePartData part : initialDraft.getParts()) {
+            if (part.isAttachment()) {
+                assertEquals(part.getContentUri(), mOutputUri);
+            } else {
+                assertEquals(part.getText(), initialMessage);
+            }
+            cnt++;
+        }
+        assertEquals("Wrong number of parts", 2, cnt);
+
+        InputStream inputStream = null;
+        try {
+            inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
+            final byte[] buffer = new byte[256];
+            final int read = inputStream.read(buffer);
+            assertEquals(read, text.getBytes().length);
+        } catch (final FileNotFoundException e) {
+            fail("Cannot open input file");
+        } catch (final IOException e) {
+            fail("Cannot read input file");
+        }
+
+        final String moreText = "This is some more text";
+        final Uri mAnotherUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
+        outputStream = null;
+        try {
+            outputStream = mContext.getContentResolver().openOutputStream(mAnotherUri);
+            outputStream.write(moreText.getBytes());
+        } catch (final FileNotFoundException e) {
+            fail("Cannot open output file");
+        } catch (final IOException e) {
+            fail("Cannot write output file");
+        }
+
+        final MessageData another =
+                MessageData.createDraftMmsMessage(conversationId, selfId, draftMessage, subject);
+        another.addPart(MessagePartData.createMediaMessagePart(ContentType.MMS_MULTIPART_MIXED,
+                mAnotherUri, 0, 0));
+
+        final String anotherMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
+                conversationId, another, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+        assertNotNull(anotherMessageId);
+
+        final MessageData anotherDraft = BugleDatabaseOperations.readMessage(db, anotherMessageId);
+        assertNotNull(anotherDraft);
+        cnt = 0;
+        for(final MessagePartData part : anotherDraft.getParts()) {
+            if (part.isAttachment()) {
+                assertEquals(part.getContentUri(), mAnotherUri);
+            } else {
+                assertEquals(part.getText(), draftMessage);
+            }
+            cnt++;
+        }
+        assertEquals("Wrong number of parts", 2, cnt);
+
+        inputStream = null;
+        try {
+            inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
+            assertNull("Original draft content should have been deleted", inputStream);
+        } catch (final FileNotFoundException e) {
+        }
+        inputStream = null;
+        try {
+            inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
+            final byte[] buffer = new byte[256];
+            final int read = inputStream.read(buffer);
+            assertEquals(read, moreText.getBytes().length);
+        } catch (final FileNotFoundException e) {
+            fail("Cannot open input file");
+        } catch (final IOException e) {
+            fail("Cannot read input file");
+        }
+
+        final MessageData last = null;
+        final String lastPartId = BugleDatabaseOperations.updateDraftMessageData(db,
+                conversationId, last, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
+        assertNull(lastPartId);
+
+        inputStream = null;
+        try {
+            inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
+            assertNull("Original draft content should have been deleted", inputStream);
+        } catch (final FileNotFoundException e) {
+        }
+
+    }
+
+    private StubActionService mService;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final FakeContext context = new FakeContext(getTestContext());
+
+        final ContentProvider bugleProvider = new MessagingContentProvider();
+        final ProviderInfo bugleProviderInfo = new ProviderInfo();
+        bugleProviderInfo.authority = MessagingContentProvider.AUTHORITY;
+        bugleProvider.attachInfo(mContext, bugleProviderInfo);
+        context.addContentProvider(MessagingContentProvider.AUTHORITY, bugleProvider);
+        final ContentProvider mediaProvider = new MediaScratchFileProvider();
+        final ProviderInfo mediaProviderInfo = new ProviderInfo();
+        mediaProviderInfo.authority = MediaScratchFileProvider.AUTHORITY;
+        mediaProvider.attachInfo(mContext, mediaProviderInfo);
+        context.addContentProvider(MediaScratchFileProvider.AUTHORITY, mediaProvider);
+
+        mService = new StubActionService();
+        final FakeDataModel fakeDataModel = new FakeDataModel(context)
+                .withActionService(mService);
+        FakeFactory.registerWithFakeContext(getTestContext(), context)
+                .withDataModel(fakeDataModel);
+
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/data/ConversationMessageDataTest.java b/tests/src/com/android/messaging/datamodel/data/ConversationMessageDataTest.java
new file mode 100644
index 0000000..42b51fd
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/data/ConversationMessageDataTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.data.ConversationMessageData.ConversationMessageViewColumns;
+
+@SmallTest
+public class ConversationMessageDataTest extends BugleTestCase {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext());
+    }
+
+    public void testBindFirstMessage() {
+        final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
+        final ConversationMessageData data = new ConversationMessageData();
+        testCursor.moveToFirst();
+        data.bind(testCursor);
+        // TODO: Add before checking in all bound fields...
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 0).equals(
+                MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
+                0), data.getSenderProfilePhotoUri());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 0),
+                data.getSenderFullName());
+    }
+
+    public void testBindTwice() {
+        final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
+        final ConversationMessageData data = new ConversationMessageData();
+        testCursor.moveToPosition(1);
+        data.bind(testCursor);
+        assertEquals(TestDataFactory.getMessageText(testCursor, 1), data.getText());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.RECEIVED_TIMESTAMP, 1),
+                data.getReceivedTimeStamp());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 1).equals(
+                MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
+                1), data.getSenderProfilePhotoUri());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 1),
+                data.getSenderFullName());
+        testCursor.moveToPosition(2);
+        data.bind(testCursor);
+        assertEquals(TestDataFactory.getMessageText(testCursor, 2), data.getText());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.RECEIVED_TIMESTAMP, 2),
+                data.getReceivedTimeStamp());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 2).equals(
+                MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
+                2), data.getSenderProfilePhotoUri());
+        assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 2),
+                data.getSenderFullName());
+    }
+
+    public void testMessageClustering() {
+        final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
+        final ConversationMessageData data = new ConversationMessageData();
+        testCursor.moveToPosition(0);
+        data.bind(testCursor);
+        assertFalse(data.getCanClusterWithPreviousMessage());
+        assertFalse(data.getCanClusterWithNextMessage());
+
+        testCursor.moveToPosition(1);
+        data.bind(testCursor);
+        assertFalse(data.getCanClusterWithPreviousMessage());
+        assertFalse(data.getCanClusterWithNextMessage());
+
+        testCursor.moveToPosition(2);
+        data.bind(testCursor);
+        assertFalse(data.getCanClusterWithPreviousMessage());
+        assertTrue(data.getCanClusterWithNextMessage());  // 2 and 3 can be clustered
+        testCursor.moveToPosition(3);
+
+        data.bind(testCursor);
+        assertTrue(data.getCanClusterWithPreviousMessage());  // 2 and 3 can be clustered
+        assertFalse(data.getCanClusterWithNextMessage());
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/data/ConversationParticipantsDataTest.java b/tests/src/com/android/messaging/datamodel/data/ConversationParticipantsDataTest.java
new file mode 100644
index 0000000..b250f80
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/data/ConversationParticipantsDataTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.data;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.FakeCursor;
+
+@SmallTest
+public class ConversationParticipantsDataTest extends BugleTestCase {
+    public void testBindParticipants() {
+        final FakeCursor testCursor = TestDataFactory.getConversationParticipantsCursor();
+        final ConversationParticipantsData data = new ConversationParticipantsData();
+        data.bind(testCursor);
+
+        assertEquals(data.getParticipantListExcludingSelf().size(), testCursor.getCount());
+        final ParticipantData participant2 = data.getParticipantById("2");
+        assertNotNull(participant2);
+        assertEquals(participant2.getFirstName(), testCursor.getAt(
+                ParticipantColumns.FIRST_NAME, 1) );
+        assertEquals(participant2.getSendDestination(), testCursor.getAt(
+                ParticipantColumns.SEND_DESTINATION, 1));
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java b/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java
new file mode 100644
index 0000000..033caa2
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.datamodel.data;
+
+import android.content.ContentValues;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.Contacts;
+import android.provider.MediaStore.Images.Media;
+
+import com.android.messaging.datamodel.BugleDatabaseOperations;
+import com.android.messaging.datamodel.DatabaseHelper;
+import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
+import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
+import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
+import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.data.ConversationListItemData.ConversationListViewColumns;
+import com.android.messaging.datamodel.data.ConversationMessageData.ConversationMessageViewColumns;
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContactUtil;
+import com.android.messaging.util.ContentType;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A factory for fake objects that can be useful for multiple tests.
+ */
+public class TestDataFactory {
+    private final static String[] sConversationListCursorColumns = new String[] {
+        ConversationListViewColumns._ID,
+        ConversationListViewColumns.NAME,
+        ConversationListViewColumns.ICON,
+        ConversationListViewColumns.SNIPPET_TEXT,
+        ConversationListViewColumns.PREVIEW_URI,
+        ConversationListViewColumns.SORT_TIMESTAMP,
+        ConversationListViewColumns.READ,
+        ConversationListViewColumns.PREVIEW_CONTENT_TYPE,
+        ConversationListViewColumns.MESSAGE_STATUS,
+    };
+
+    private final static String[] sContactCursorColumns = new String[] {
+            Phone.CONTACT_ID,
+            Phone.DISPLAY_NAME_PRIMARY,
+            Phone.PHOTO_THUMBNAIL_URI,
+            Phone.NUMBER,
+            Phone.TYPE,
+            Phone.LABEL,
+            Phone.LOOKUP_KEY,
+            Phone._ID,
+            Phone.SORT_KEY_PRIMARY,
+    };
+
+    private final static String[] sFrequentContactCursorColumns = new String[] {
+            Contacts._ID,
+            Contacts.DISPLAY_NAME,
+            Contacts.PHOTO_URI,
+            Phone.LOOKUP_KEY,
+    };
+
+    private final static String[] sConversationMessageCursorColumns = new String[] {
+        ConversationMessageViewColumns._ID,
+        ConversationMessageViewColumns.CONVERSATION_ID,
+        ConversationMessageViewColumns.PARTICIPANT_ID,
+        ConversationMessageViewColumns.SENT_TIMESTAMP,
+        ConversationMessageViewColumns.RECEIVED_TIMESTAMP,
+        ConversationMessageViewColumns.STATUS,
+        ConversationMessageViewColumns.SENDER_FULL_NAME,
+        ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
+        ConversationMessageViewColumns.PARTS_IDS,
+        ConversationMessageViewColumns.PARTS_CONTENT_TYPES,
+        ConversationMessageViewColumns.PARTS_CONTENT_URIS,
+        ConversationMessageViewColumns.PARTS_WIDTHS,
+        ConversationMessageViewColumns.PARTS_HEIGHTS,
+        ConversationMessageViewColumns.PARTS_TEXTS,
+        ConversationMessageViewColumns.PARTS_COUNT
+    };
+
+    private final static String[] sGalleryCursorColumns = new String[] {
+        Media._ID,
+        Media.DATA,
+        Media.WIDTH,
+        Media.HEIGHT,
+        Media.MIME_TYPE
+    };
+
+    public static FakeCursor getConversationListCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(1), "name1", "content://icon1",
+                        "snippetText1", "content://snippetUri1", Long.valueOf(10), 1,
+                        ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_INCOMING_COMPLETE},
+                new Object[] { Long.valueOf(2), "name2", "content://icon2",
+                        "snippetText2", "content://snippetUri2", Long.valueOf(20) + 24*60*60*1000,
+                        0, ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_INCOMING_COMPLETE},
+                new Object[] { Long.valueOf(3), "name3", "content://icon3",
+                        "snippetText3", "content://snippetUri3", Long.valueOf(30) + 2*24*60*60*1000,
+                        0, ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_OUTGOING_COMPLETE}
+        };
+        return new FakeCursor(ConversationListItemData.PROJECTION, sConversationListCursorColumns,
+                cursorData);
+    }
+    public static final int CONVERSATION_LIST_CURSOR_READ_MESSAGE_INDEX = 0;
+    public static final int CONVERSATION_LIST_CURSOR_UNREAD_MESSAGE_INDEX = 1;
+
+    public static FakeCursor getEmptyConversationListCursor() {
+        return new FakeCursor(ConversationListItemData.PROJECTION, sConversationListCursorColumns,
+                new Object[][] {});
+    }
+
+    public static FakeCursor getConversationMessageCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(0), Long.valueOf(1), Long.valueOf(1),
+                        Long.valueOf(10), Long.valueOf(10),
+                        MessageData.BUGLE_STATUS_INCOMING_COMPLETE, "Alice", null,
+                        "0", "text/plain", "''", -1, -1, "msg0", 1},
+                new Object[] { Long.valueOf(1), Long.valueOf(1), Long.valueOf(2),
+                        Long.valueOf(20), Long.valueOf(20),
+                        MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Bob", null,
+                        "1", "text/plain", "''", -1, -1, "msg1", 1},
+                new Object[] { Long.valueOf(2), Long.valueOf(1), Long.valueOf(1),
+                        Long.valueOf(30), Long.valueOf(30),
+                        MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Alice", null,
+                        "2", "contentType3", "'content://fakeUri3'", "0", "0", "msg1", 1},
+                new Object[] { Long.valueOf(3), Long.valueOf(1), Long.valueOf(1),
+                        Long.valueOf(40), Long.valueOf(40),
+                        MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Alice", null,
+                        "3|4", "'contentType4'|'text/plain'", "'content://fakeUri4'|''", "0|-1", "0|-1", "''|'msg3'", 2},
+        };
+        return new FakeCursor(
+                ConversationMessageData.getProjection(),
+                sConversationMessageCursorColumns,
+                cursorData);
+    }
+
+    public static String getMessageText(final FakeCursor messageCursor, final int row) {
+        final String allPartsText = messageCursor.getAt(ConversationMessageViewColumns.PARTS_TEXTS, row)
+                .toString();
+        final int partsCount = (Integer) messageCursor.getAt(
+                ConversationMessageViewColumns.PARTS_COUNT, row);
+        final String messageId = messageCursor.getAt(
+                ConversationMessageViewColumns._ID, row).toString();
+        final List<MessagePartData> parts = ConversationMessageData.makeParts(
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_IDS, row).toString(),
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_CONTENT_TYPES, row).toString(),
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_CONTENT_URIS, row).toString(),
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_WIDTHS, row).toString(),
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_HEIGHTS, row).toString(),
+                messageCursor.getAt(ConversationMessageViewColumns.PARTS_TEXTS, row).toString(),
+                partsCount,
+                messageId);
+
+        for (final MessagePartData part : parts) {
+            if (part.isText()) {
+                return part.getText();
+            }
+        }
+        return null;
+    }
+
+    // Indexes where to find consecutive and non consecutive messages from same participant
+    // (respect to index - 1).
+    public static final int MESSAGE_WITH_SAME_PARTICIPANT_AS_PREVIOUS = 3;
+    public static final int MESSAGE_WITH_DIFFERENT_PARTICIPANT_AS_PREVIOUS = 2;
+
+    public static FakeCursor getConversationParticipantsCursor() {
+        final String[] sConversationParticipantsCursorColumns = new String[] {
+                ParticipantColumns._ID,
+                ParticipantColumns.SUB_ID,
+                ParticipantColumns.NORMALIZED_DESTINATION,
+                ParticipantColumns.SEND_DESTINATION,
+                ParticipantColumns.FULL_NAME,
+                ParticipantColumns.FIRST_NAME,
+                ParticipantColumns.PROFILE_PHOTO_URI,
+        };
+
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { 1, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15554567890",
+                        "(555)456-7890", "alice in wonderland", "alice", "alice.png" },
+                new Object[] { 2, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15551011121",
+                        "(555)101-1121", "bob the baker", "bob", "bob.png"},
+                new Object[] { 3, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15551314152",
+                        "(555)131-4152", "charles in charge", "charles", "charles.png" },
+        };
+
+        return new FakeCursor(ParticipantData.ParticipantsQuery.PROJECTION,
+                sConversationParticipantsCursorColumns, cursorData);
+    }
+
+    public static final int CONTACT_LIST_CURSOR_FIRST_LEVEL_CONTACT_INDEX = 0;
+    public static final int CONTACT_LIST_CURSOR_SECOND_LEVEL_CONTACT_INDEX = 2;
+
+    /**
+     * Returns a cursor for the all contacts list consumable by ContactPickerFragment.
+     */
+    public static FakeCursor getAllContactListCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(0), "John Smith", "content://uri1",
+                        "425-555-1234", Phone.TYPE_HOME, "", "0", Long.valueOf(0), 0 },
+                new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
+                        "425-555-1235", Phone.TYPE_MOBILE, "", "1", Long.valueOf(1), 1 },
+                new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
+                        "425-555-1238", Phone.TYPE_HOME, "", "1", Long.valueOf(2), 2 },
+                new Object[] { Long.valueOf(2), "Anna Kinney", "content://uri3",
+                        "425-555-1236", Phone.TYPE_MAIN, "", "3", Long.valueOf(3), 3 },
+                new Object[] { Long.valueOf(3), "Mike Jones", "content://uri3",
+                        "425-555-1236", Phone.TYPE_MAIN, "", "5", Long.valueOf(4), 4 },
+        };
+        return new FakeCursor(ContactUtil.PhoneQuery.PROJECTION, sContactCursorColumns,
+                cursorData);
+    }
+
+    /**
+     * Returns a cursor for the frequent contacts list consumable by ContactPickerFragment.
+     * Note: make it so that this cursor is the generated result of getStrequentContactsCursor()
+     * and getAllContactListCursor(), i.e., expand the entries in getStrequentContactsCursor()
+     * with the details from getAllContactListCursor()
+     */
+    public static FakeCursor getFrequentContactListCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(2), "Anna Kinney", "content://uri3",
+                        "425-555-1236", Phone.TYPE_MAIN, "", "3", Long.valueOf(3), 0 },
+                new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
+                        "425-555-1235", Phone.TYPE_MOBILE, "", "1", Long.valueOf(1), 1},
+                new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
+                        "425-555-1238", Phone.TYPE_HOME, "", "1", Long.valueOf(2), 2 },
+                new Object[] { Long.valueOf(0), "John Smith", "content://uri1",
+                        "425-555-1234", Phone.TYPE_HOME, "", "0", Long.valueOf(0), 3 },
+        };
+        return new FakeCursor(ContactUtil.PhoneQuery.PROJECTION, sContactCursorColumns,
+                cursorData);
+    }
+
+    /**
+     * Returns a strequent (starred + frequent) cursor (like the one produced by android contact
+     * provider's CONTENT_STREQUENT_URI query) that's consumable by FrequentContactsCursorBuilder.
+     */
+    public static FakeCursor getStrequentContactsCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(0), "Anna Kinney", "content://uri1", "3" },
+                new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2", "1" },
+                new Object[] { Long.valueOf(2), "John Smith", "content://uri3", "0" },
+                // Email-only entry that shouldn't be included in the result.
+                new Object[] { Long.valueOf(3), "Email Contact", "content://uri4", "100" },
+        };
+        return new FakeCursor(ContactUtil.FrequentContactQuery.PROJECTION,
+                sFrequentContactCursorColumns, cursorData);
+    }
+
+    public static final int SMS_MMS_THREAD_ID_CURSOR_VALUE = 123456789;
+
+    public static FakeCursor getSmsMmsThreadIdCursor() {
+        final String[] ID_PROJECTION = { BaseColumns._ID };
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(SMS_MMS_THREAD_ID_CURSOR_VALUE) },
+        };
+        return new FakeCursor(ID_PROJECTION, ID_PROJECTION, cursorData);
+    }
+
+    public static FakeCursor getGalleryGridCursor() {
+        final Object[][] cursorData = new Object[][] {
+                new Object[] { Long.valueOf(0), "/sdcard/image1", 100, 100, "image/jpeg" },
+                new Object[] { Long.valueOf(1), "/sdcard/image2", 200, 200, "image/png" },
+                new Object[] { Long.valueOf(2), "/sdcard/image3", 300, 300, "image/jpeg" },
+        };
+        return new FakeCursor(GalleryGridItemData.MEDIA_PROJECTION, sGalleryCursorColumns,
+                cursorData);
+    }
+
+    public static final int NUM_TEST_CONVERSATIONS = 10;
+
+    /**
+     * Create test data in our db.
+     *
+     * Ideally this will create more realistic data with more variety.
+     */
+    public static void createTestData(final SQLiteDatabase db) {
+        BugleDatabaseOperations.clearParticipantIdCache();
+
+        // Timestamp for 1 day ago
+        final long yesterday = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
+
+        final ContentValues conversationValues = new ContentValues();
+        for (int i = 1; i <= NUM_TEST_CONVERSATIONS; i++) {
+            conversationValues.put(ConversationColumns.NAME, "Conversation " + i);
+            final long conversationId = db.insert(DatabaseHelper.CONVERSATIONS_TABLE, null,
+                    conversationValues);
+
+            final ContentValues messageValues = new ContentValues();
+            for (int m = 1; m <= 25; m++) {
+                // Move forward ten minutes per conversation, 1 minute per message.
+                final long messageTime = yesterday + (i * 10 * 60 * 1000) + (m * 60 * 1000);
+                messageValues.put(MessageColumns.RECEIVED_TIMESTAMP, messageTime);
+                messageValues.put(MessageColumns.CONVERSATION_ID, conversationId);
+                messageValues.put(MessageColumns.SENDER_PARTICIPANT_ID,
+                        Math.abs(("" + messageTime).hashCode()) % 2);
+                final long messageId = db.insert(DatabaseHelper.MESSAGES_TABLE, null, messageValues);
+
+                // Create a text part for this message
+                final ContentValues partValues = new ContentValues();
+                partValues.put(PartColumns.MESSAGE_ID, messageId);
+                partValues.put(PartColumns.CONVERSATION_ID, conversationId);
+                partValues.put(PartColumns.TEXT, "Conversation: " + conversationId +
+                        " Message: " + m);
+                db.insert(DatabaseHelper.PARTS_TABLE, null, partValues);
+
+                // Update the snippet for this conversation to the latest message inserted
+                conversationValues.clear();
+                conversationValues.put(ConversationColumns.LATEST_MESSAGE_ID, messageId);
+                final int updatedCount = db.update(DatabaseHelper.CONVERSATIONS_TABLE,
+                        conversationValues,
+                        "_id=?", new String[]{String.valueOf(conversationId)});
+                Assert.isTrue(updatedCount == 1);
+            }
+        }
+    }
+
+    public static List<MessagePartData> getTestDraftAttachments() {
+        final MessagePartData[] retParts = new MessagePartData[] {
+                new MessagePartData(ContentType.IMAGE_JPEG, Uri.parse("content://image"),
+                        100, 100),
+                new MessagePartData(ContentType.VIDEO_3GPP, Uri.parse("content://video"),
+                        100, 100),
+                new MessagePartData(ContentType.TEXT_VCARD, Uri.parse("content://vcard"),
+                        0, 0),
+                new MessagePartData(ContentType.AUDIO_3GPP, Uri.parse("content://audio"),
+                        0, 0)
+        };
+        return Arrays.asList(retParts);
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/media/FakeImageRequest.java b/tests/src/com/android/messaging/datamodel/media/FakeImageRequest.java
new file mode 100644
index 0000000..7f6ac3f
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/media/FakeImageRequest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.text.TextUtils;
+
+import java.util.List;
+
+public class FakeImageRequest implements MediaRequest<FakeImageResource> {
+    public static final String INVALID_KEY = "invalid";
+    private final String mKey;
+    private final int mSize;
+
+    public FakeImageRequest(final String key, final int size) {
+        mKey = key;
+        mSize = size;
+    }
+
+    @Override
+    public String getKey() {
+        return mKey;
+    }
+
+    @Override
+    public FakeImageResource loadMediaBlocking(List<MediaRequest<FakeImageResource>> chainedTask)
+            throws Exception {
+        if (TextUtils.equals(mKey, INVALID_KEY)) {
+            throw new Exception();
+        } else {
+            return new FakeImageResource(mSize, mKey);
+        }
+    }
+
+    @Override
+    public int getCacheId() {
+        return FakeMediaCacheManager.FAKE_IMAGE_CACHE;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public MediaCache<FakeImageResource> getMediaCache() {
+        return (MediaCache<FakeImageResource>) MediaCacheManager.get().getOrCreateMediaCacheById(
+                getCacheId());
+    }
+
+    @Override
+    public int getRequestType() {
+        return MediaRequest.REQUEST_LOAD_MEDIA;
+    }
+
+    @Override
+    public MediaRequestDescriptor<FakeImageResource> getDescriptor() {
+        return null;
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/media/FakeImageResource.java b/tests/src/com/android/messaging/datamodel/media/FakeImageResource.java
new file mode 100644
index 0000000..969854f
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/media/FakeImageResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+public class FakeImageResource extends RefCountedMediaResource {
+    private boolean mClosed = false;
+    private boolean mCached = false;
+    private final int mSize;
+    private final String mImageId;
+
+    public FakeImageResource(final int size, final String imageId) {
+        super(null);
+        mSize = size;
+        mImageId = imageId;
+    }
+
+    public boolean isClosed() {
+        return mClosed;
+    }
+
+    public String getImageId() {
+        return mImageId;
+    }
+
+    public void setCached(final boolean cached) {
+        mCached = cached;
+    }
+
+    public boolean getCached() {
+        return mCached;
+    }
+
+    @Override
+    public int getMediaSize() {
+        return mSize;
+    }
+
+    @Override
+    protected void close() {
+        mClosed = true;
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/media/FakeMediaCacheManager.java b/tests/src/com/android/messaging/datamodel/media/FakeMediaCacheManager.java
new file mode 100644
index 0000000..34b3a55
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/media/FakeMediaCacheManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+public class FakeMediaCacheManager extends MediaCacheManager {
+    // List of available fake cache ids.
+    public static final int FAKE_IMAGE_CACHE = 1;
+    public static final int FAKE_BATCH_IMAGE_CACHE = 2;
+
+    @Override
+    public MediaCache<?> createMediaCacheById(final int id) {
+        switch (id) {
+            case FAKE_IMAGE_CACHE:
+                // Make a cache of only 3 KB of data.
+                return new MediaCache<FakeImageResource>(3, FAKE_IMAGE_CACHE, "FakeImageCache");
+
+            case FAKE_BATCH_IMAGE_CACHE:
+                return new MediaCache<FakeImageResource>(10, FAKE_BATCH_IMAGE_CACHE,
+                        "FakeBatchImageCache");
+        }
+        return null;
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/media/ImageRequestTest.java b/tests/src/com/android/messaging/datamodel/media/ImageRequestTest.java
new file mode 100644
index 0000000..3e0f4e0
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/media/ImageRequestTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import android.content.ContentResolver;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.util.ImageUtils;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+import java.io.IOException;
+
+@SmallTest
+public class ImageRequestTest extends BugleTestCase {
+    private static final int DOWNSAMPLE_IMAGE_SIZE = 2;
+
+    @Spy protected ImageUtils spyImageUtils;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext())
+                   .withMemoryCacheManager(new MemoryCacheManager())
+                   .withMediaCacheManager(new BugleMediaCacheManager());
+        spyImageUtils = Mockito.spy(new ImageUtils());
+        ImageUtils.set(spyImageUtils);
+    }
+
+    public void testLoadImageUnspecifiedSize() {
+        final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
+        final Uri uri = Uri.parse(uriString);
+        final UriImageRequest imageRequest = new UriImageRequest(getContext(),
+                new UriImageRequestDescriptor(uri));
+        try {
+            final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
+            final ArgumentCaptor<BitmapFactory.Options> options =
+                    ArgumentCaptor.forClass(BitmapFactory.Options.class);
+            Mockito.verify(spyImageUtils).calculateInSampleSize(
+                    options.capture(),
+                    Matchers.eq(ImageRequest.UNSPECIFIED_SIZE),
+                    Matchers.eq(ImageRequest.UNSPECIFIED_SIZE));
+            assertEquals(1, options.getValue().inSampleSize);
+            assertNotNull(imageResource);
+            assertNotNull(imageResource.getBitmap());
+
+            // Make sure there's no scaling on the bitmap.
+            final int bitmapWidth = imageResource.getBitmap().getWidth();
+            final int bitmapHeight = imageResource.getBitmap().getHeight();
+            assertEquals(options.getValue().outWidth, bitmapWidth);
+            assertEquals(options.getValue().outHeight, bitmapHeight);
+        } catch (final IOException e) {
+            fail("IO exception while trying to load image resource");
+        }
+    }
+
+    public void testLoadImageWithDownsampling() {
+        final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
+        final Uri uri = Uri.parse(uriString);
+        final UriImageRequest imageRequest = new UriImageRequest(getContext(),
+                new UriImageRequestDescriptor(uri, DOWNSAMPLE_IMAGE_SIZE, DOWNSAMPLE_IMAGE_SIZE,
+                        false, true /* isStatic */, false /* cropToCircle */,
+                        ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
+                        ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */));
+        try {
+            final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
+            final ArgumentCaptor<BitmapFactory.Options> options =
+                    ArgumentCaptor.forClass(BitmapFactory.Options.class);
+            Mockito.verify(spyImageUtils).calculateInSampleSize(
+                    options.capture(),
+                    Matchers.eq(DOWNSAMPLE_IMAGE_SIZE), Matchers.eq(DOWNSAMPLE_IMAGE_SIZE));
+            assertNotSame(1, options.getValue().inSampleSize);
+            assertNotNull(imageResource);
+            assertNotNull(imageResource.getBitmap());
+
+            // Make sure there's down sampling on the bitmap.
+            final int bitmapWidth = imageResource.getBitmap().getWidth();
+            final int bitmapHeight = imageResource.getBitmap().getHeight();
+            assertTrue(bitmapWidth >= DOWNSAMPLE_IMAGE_SIZE &&
+                    bitmapHeight >= DOWNSAMPLE_IMAGE_SIZE &&
+                    (bitmapWidth <= DOWNSAMPLE_IMAGE_SIZE * 4 ||
+                    bitmapHeight <= DOWNSAMPLE_IMAGE_SIZE * 4));
+        } catch (final IOException e) {
+            fail("IO exception while trying to load image resource");
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/datamodel/media/MediaResourceManagerTest.java b/tests/src/com/android/messaging/datamodel/media/MediaResourceManagerTest.java
new file mode 100644
index 0000000..c5054ad
--- /dev/null
+++ b/tests/src/com/android/messaging/datamodel/media/MediaResourceManagerTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.datamodel.media;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
+
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+public class MediaResourceManagerTest extends BugleTestCase {
+    private static final int KB = 1024;
+
+    // Loaded image resource from the MediaResourceManager callback.
+    private FakeImageResource mImageResource;
+    private BindableMediaRequest<FakeImageResource> mImageRequest;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext())
+                .withMemoryCacheManager(new MemoryCacheManager())
+                .withMediaCacheManager(new FakeMediaCacheManager());
+    }
+
+    public void testLoadFromCache() {
+        final MediaResourceManager mediaResourceManager =
+                new MediaResourceManager();
+        MediaCacheManager.get().reclaim();
+        assertNotNull(mediaResourceManager);
+
+        // Load one image of 1KB
+        loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
+        assertEquals("image1", mImageResource.getImageId());
+        final FakeImageResource loadedResource = mImageResource;
+
+        // Load the same image.
+        loadImage(mediaResourceManager, "image1", 1 * KB, true /* shouldBeCached */, false);
+        assertEquals(loadedResource, mImageResource);
+    }
+
+    public void testCacheEviction() {
+        final MediaResourceManager mediaResourceManager =
+                new MediaResourceManager();
+        MediaCacheManager.get().reclaim();
+        assertNotNull(mediaResourceManager);
+
+        // Load one image of 1KB
+        loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
+        assertEquals("image1", mImageResource.getImageId());
+
+        // Load another image
+        loadImage(mediaResourceManager, "image2", 2 * KB, false /* shouldBeCached */, false);
+        assertEquals("image2", mImageResource.getImageId());
+
+        // Load another image. This should fill the cache and cause eviction of image1.
+        loadImage(mediaResourceManager, "image3", 2 * KB, false /* shouldBeCached */, false);
+        assertEquals("image3", mImageResource.getImageId());
+
+        // Load image1. It shouldn't be cached any more.
+        loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
+        assertEquals("image1", mImageResource.getImageId());
+    }
+
+    public void testReclaimMemoryFromMediaCache() {
+        final MediaResourceManager mediaResourceManager =
+                new MediaResourceManager();
+        MediaCacheManager.get().reclaim();
+        assertNotNull(mediaResourceManager);
+
+        // Load one image of 1KB
+        loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
+        assertEquals("image1", mImageResource.getImageId());
+
+        // Purge everything from the cache, now the image should no longer be cached.
+        MediaCacheManager.get().reclaim();
+
+        // The image resource should have no ref left.
+        assertEquals(0, mImageResource.getRefCount());
+        assertTrue(mImageResource.isClosed());
+        loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
+        assertEquals("image1", mImageResource.getImageId());
+    }
+
+    public void testLoadInvalidImage() {
+        final MediaResourceManager mediaResourceManager =
+                new MediaResourceManager();
+        MediaCacheManager.get().reclaim();
+        assertNotNull(mediaResourceManager);
+
+        // Test the failure case with invalid resource.
+        loadImage(mediaResourceManager, FakeImageRequest.INVALID_KEY, 1 * KB, false,
+                true /* shouldFail */);
+    }
+
+    public void testLoadImageSynchronously() {
+        final MediaResourceManager mediaResourceManager =
+                new MediaResourceManager();
+        MediaCacheManager.get().reclaim();
+        assertNotNull(mediaResourceManager);
+
+        // Test a normal sync load.
+        final FakeImageRequest request = new FakeImageRequest("image1", 1 * KB);
+        final FakeImageResource resource = mediaResourceManager.requestMediaResourceSync(request);
+        assertNotNull(resource);
+        assertFalse(resource.isClosed());
+        assertNotSame(0, resource.getRefCount());
+        resource.release();
+
+        // Test a failed sync load.
+        final FakeImageRequest invalidRequest =
+                new FakeImageRequest(FakeImageRequest.INVALID_KEY, 1 * KB);
+        assertNull(mediaResourceManager.requestMediaResourceSync(invalidRequest));
+    }
+
+    private void loadImage(final MediaResourceManager manager, final String key,
+            final int size, final boolean shouldBeCached, final boolean shouldFail) {
+        try {
+            final CountDownLatch signal = new CountDownLatch(1);
+            mImageRequest = AsyncMediaRequestWrapper.createWith(new FakeImageRequest(key, size),
+                    createAssertListener(shouldBeCached, shouldFail, signal));
+            mImageRequest.bind("1");
+            manager.requestMediaResourceAsync(mImageRequest);
+
+            // Wait for the asynchronous callback before proceeding.
+            signal.await();
+        } catch (final InterruptedException e) {
+            fail("Something interrupted the signal await.");
+        }
+    }
+
+    private MediaResourceLoadListener<FakeImageResource> createAssertListener(
+            final boolean shouldBeCached, final boolean shouldFail, final CountDownLatch signal) {
+        return new MediaResourceLoadListener<FakeImageResource>() {
+            @Override
+            public void onMediaResourceLoaded(final MediaRequest<FakeImageResource> request,
+                    final FakeImageResource resource, final boolean isCached) {
+                assertEquals(mImageRequest, request);
+                assertNotNull(resource);
+                assertFalse(resource.isClosed());
+                assertNotSame(0, resource.getRefCount());
+                assertFalse(shouldFail);
+                assertEquals(shouldBeCached, resource.getCached());
+                resource.setCached(true);
+                mImageResource = resource;
+                signal.countDown();
+            }
+
+            @Override
+            public void onMediaResourceLoadError(
+                    final MediaRequest<FakeImageResource> request, final Exception exception) {
+                assertTrue(shouldFail);
+                mImageResource = null;
+                signal.countDown();
+            }};
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/ActivityInstrumentationTestCaseIntent.java b/tests/src/com/android/messaging/ui/ActivityInstrumentationTestCaseIntent.java
new file mode 100644
index 0000000..5ea6aa7
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/ActivityInstrumentationTestCaseIntent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+
+
+/**
+ * Purpose of this class is providing a workaround for https://b/14561718
+ */
+public class ActivityInstrumentationTestCaseIntent extends Intent {
+    public ActivityInstrumentationTestCaseIntent(Context packageContext, Class<?> cls) {
+        super(packageContext, cls);
+    }
+    @Override
+    public Intent setComponent(ComponentName component) {
+        // Ignore the ComponentName set, as the one ActivityUnitTest does is wrong (and actually
+        // unnecessary).
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/ui/BugleActivityInstrumentationTestCase.java b/tests/src/com/android/messaging/ui/BugleActivityInstrumentationTestCase.java
new file mode 100644
index 0000000..60cddff
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/BugleActivityInstrumentationTestCase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Activity;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.TestUtil;
+
+/**
+ * Helper class that extends ActivityInstrumentationTestCase2 to provide some extra common
+ * initialization (eg. Mockito boilerplate).
+ */
+public class BugleActivityInstrumentationTestCase<T extends Activity>
+    extends android.test.ActivityInstrumentationTestCase2<T> {
+
+    static {
+        // Set flag during loading of test cases to prevent application initialization starting
+        BugleTestCase.setTestsRunning();
+    }
+
+    public BugleActivityInstrumentationTestCase(final Class<T> activityClass) {
+        super(activityClass);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+      setActivityInitialTouchMode(false);
+      TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        TestUtil.testTeardown(this);
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/ui/BugleActivityTest.java b/tests/src/com/android/messaging/ui/BugleActivityTest.java
new file mode 100644
index 0000000..05e32fa
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/BugleActivityTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.DataModel;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public abstract class BugleActivityTest extends BugleActivityUnitTestCase<BugleActionBarActivity> {
+    @Mock protected DataModel mDataModel;
+
+    public BugleActivityTest() {
+        super(BugleActionBarActivity.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Create activity
+        final ActivityInstrumentationTestCaseIntent intent =
+                new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
+                TestActivity.class);
+        startActivity(intent, null, null);
+
+        FakeFactory.register(getInstrumentation().getTargetContext())
+            .withDataModel(mDataModel);
+    }
+
+    public void testOnResumeDataModelCallback() {
+        getInstrumentation().callActivityOnStart(getActivity());
+        getInstrumentation().callActivityOnResume(getActivity());
+        Mockito.verify(mDataModel).onActivityResume();
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/BugleActivityUnitTestCase.java b/tests/src/com/android/messaging/ui/BugleActivityUnitTestCase.java
new file mode 100644
index 0000000..dcbd785
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/BugleActivityUnitTestCase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.app.Activity;
+import android.view.ContextThemeWrapper;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.R;
+import com.android.messaging.TestUtil;
+
+/**
+ * Base class for activity unit test cases, provides boilerplate setup/teardown.
+ */
+public abstract class BugleActivityUnitTestCase<T extends Activity> extends
+    android.test.ActivityUnitTestCase<T> {
+
+    static {
+        // Set flag during loading of test cases to prevent application initialization starting
+        BugleTestCase.setTestsRunning();
+    }
+
+    public BugleActivityUnitTestCase(final Class<T> activityClass) {
+        super(activityClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
+
+        setActivityContext(new ContextThemeWrapper(getInstrumentation().getTargetContext(),
+                R.style.Theme_AppCompat_Light_DarkActionBar));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        TestUtil.testTeardown(this);
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/CustomHeaderViewPagerTest.java b/tests/src/com/android/messaging/ui/CustomHeaderViewPagerTest.java
new file mode 100644
index 0000000..373fb41
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/CustomHeaderViewPagerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import androidx.viewpager.widget.ViewPager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SimpleCursorAdapter;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+
+public class CustomHeaderViewPagerTest extends ViewTest<CustomHeaderViewPager> {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getInstrumentation().getTargetContext());
+    }
+
+    public void testBindFirstLevel() {
+        final CustomHeaderViewPager view = new CustomHeaderViewPager(getActivity(), null);
+        final SimpleCursorAdapter adapter =
+                new SimpleCursorAdapter(getActivity(), 0, null, null, null, 0);
+        final CustomHeaderPagerViewHolder[] viewHolders = {
+                new FakeListViewHolder(getActivity(), adapter),
+                new FakeListViewHolder(getActivity(), adapter)
+        };
+
+        view.setViewHolders(viewHolders);
+        final ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
+        final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.tab_strip);
+        final ViewPagerTabStrip realTab = (ViewPagerTabStrip) tabStrip.getChildAt(0);
+
+        assertEquals(2, realTab.getChildCount());
+        View headerTitleButton = realTab.getChildAt(1);
+        // Click on the first page. Now the view pager should switch to that page accordingly.
+        clickButton(headerTitleButton);
+        assertEquals(1, pager.getCurrentItem());
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        // All set up should be done by creating a CustomHeaderViewPager which handles inflating
+        // the layout
+        return 0;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/FakeListViewHolder.java b/tests/src/com/android/messaging/ui/FakeListViewHolder.java
new file mode 100644
index 0000000..d4de885
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/FakeListViewHolder.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui;
+
+import android.content.Context;
+import android.widget.CursorAdapter;
+
+import com.android.messaging.R;
+
+/**
+ * A fake {@link CustomHeaderPagerListViewHolder} for CustomHeaderViewPager tests only.
+ */
+public class FakeListViewHolder extends CustomHeaderPagerListViewHolder {
+    public FakeListViewHolder(final Context context, final CursorAdapter adapter) {
+        super(context, adapter);
+    }
+
+    @Override
+    protected int getLayoutResId() {
+        return 0;
+    }
+
+    @Override
+    protected int getPageTitleResId() {
+        return android.R.string.untitled;
+    }
+
+    @Override
+    protected int getEmptyViewResId() {
+        return R.id.empty_view;
+    }
+
+    @Override
+    protected int getListViewResId() {
+        return android.R.id.list;
+    }
+
+    @Override
+    protected int getEmptyViewTitleResId() {
+        return R.string.contact_list_empty_text;
+    }
+
+    @Override
+    protected int getEmptyViewImageResId() {
+        return R.drawable.ic_oobe_freq_list;
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/ui/FragmentTestCase.java b/tests/src/com/android/messaging/ui/FragmentTestCase.java
new file mode 100644
index 0000000..eb65dc6
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/FragmentTestCase.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.res.Configuration;
+import android.view.View;
+
+/**
+ * Helper class that extends Bugle.ui.ActivityInstrumentationTestCase to provide common behavior
+ * across fragment tests.
+ */
+public abstract class FragmentTestCase<T extends Fragment>
+    extends BugleActivityInstrumentationTestCase<TestActivity> {
+
+    protected T mFragment;
+    protected Class<T> mFragmentClass;
+
+    public FragmentTestCase(final Class<T> fragmentClass) {
+        super(TestActivity.class);
+        mFragmentClass = fragmentClass;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+    }
+
+    protected T getFragment() {
+        // Fragment creation deferred (typically until test time) so that factory/appcontext is
+        // ready.
+        if (mFragment == null) {
+            try {
+                mFragment = mFragmentClass.newInstance();
+            } catch (final InstantiationException e) {
+                throw new IllegalStateException("Failed to instantiate fragment");
+            } catch (final IllegalAccessException e) {
+                throw new IllegalStateException("Failed to instantiate fragment");
+            }
+        }
+
+        return mFragment;
+    }
+
+    protected void attachFragment() {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final FragmentManager fragmentManager = getActivity().getFragmentManager();
+                fragmentManager.beginTransaction().add(mFragment, null /* tag */).commit();
+            }
+        });
+
+        getInstrumentation().waitForIdleSync();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // In landscape mode, sleep for a second first.
+        // The reason is: our UI tests don't wait for the UI thread to finish settling down
+        // before exiting (because they can't know when the UI thread is done). In portrait mode,
+        // things generally work fine here -- the UI thread is done by the time the test is done.
+        // In landscape mode, though, since the launcher is in portrait mode, there is a lot of
+        // extra work that happens in our UI when the app launches into landscape mode, and the
+        // UI is often not done by the time the test finishes running. So then our teardown
+        // nulls out the Factory, and then the UI keeps running and derefs the null factory,
+        // and things blow up.
+        // So ... as a cheap hack, sleep for one second before finishing the teardown of UI
+        // tests, but only do it in landscape mode (so that developers running it in portrait
+        // mode can still run the tests faster).
+        if (this.getInstrumentation().getTargetContext().getResources().
+                getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        super.tearDown();
+    }
+
+    protected void clickButton(final View view) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.performClick();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    protected void setFocus(final View view, final boolean focused) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (focused) {
+                    view.requestFocus();
+                } else {
+                    view.clearFocus();
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/ui/MultiAttachmentLayoutTest.java b/tests/src/com/android/messaging/ui/MultiAttachmentLayoutTest.java
new file mode 100644
index 0000000..db3ff3a
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/MultiAttachmentLayoutTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.datamodel.data.MessagePartData;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+@MediumTest
+public class MultiAttachmentLayoutTest extends ViewTest<MultiAttachmentLayout> {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getTargetContext();
+        FakeFactory.register(context);
+    }
+
+    @Override
+    protected MultiAttachmentLayout getView() {
+        if (mView == null) {
+            // View creation deferred (typically until test time) so that factory/appcontext is
+            // ready.
+            mView = new MultiAttachmentLayout(getActivity(), null);
+            mView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
+        }
+        return mView;
+    }
+
+    protected void verifyContent(
+            final MultiAttachmentLayout view,
+            final int imageCount,
+            final int plusCount) {
+        final int count = view.getChildCount();
+        int actualImageCount = 0;
+        final boolean needPlusText = plusCount > 0;
+        boolean hasPlusText = false;
+        for (int i = 0; i < count; i++) {
+            final View child = view.getChildAt(i);
+            if (child instanceof AsyncImageView) {
+                actualImageCount++;
+            } else if (child instanceof TextView) {
+                assertTrue(plusCount > 0);
+                assertTrue(((TextView) child).getText().toString().contains("" + plusCount));
+                hasPlusText = true;
+            } else {
+                // Nothing other than image and overflow text view should appear in this layout.
+                fail("unexpected view in layout. view = " + child);
+            }
+        }
+        assertEquals(imageCount, actualImageCount);
+        assertEquals(needPlusText, hasPlusText);
+    }
+
+    public void testBindTwoAttachments() {
+        final MultiAttachmentLayout view = getView();
+        final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri1"), 100, 100);
+        final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri2"), 100, 100);
+
+        view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2),
+                null /* transitionRect */, 2);
+        verifyContent(view, 2, 0);
+    }
+
+    public void testBindFiveAttachments() {
+        final MultiAttachmentLayout view = getView();
+        final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri1"), 100, 100);
+        final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri2"), 100, 100);
+        final MessagePartData testAttachment3 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri3"), 100, 100);
+        final MessagePartData testAttachment4 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri4"), 100, 100);
+        final MessagePartData testAttachment5 = MessagePartData.createMediaMessagePart(
+                "image/jpeg", Uri.parse("content://uri5"), 100, 100);
+
+        view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2, testAttachment3,
+                testAttachment4, testAttachment5), null /* transitionRect */, 5);
+        verifyContent(view, 4, 1);
+    }
+
+    public void testBindTwice() {
+        // Put the above two tests together so we can simulate binding twice.
+        testBindTwoAttachments();
+        testBindFiveAttachments();
+    }
+
+    private Iterable<MessagePartData> createAttachmentList(final MessagePartData... attachments) {
+        return Collections.unmodifiableList(Arrays.asList(attachments));
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return 0;   // We construct the view with getView().
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/messaging/ui/ViewTest.java b/tests/src/com/android/messaging/ui/ViewTest.java
new file mode 100644
index 0000000..c4e8431
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/ViewTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui;
+
+import android.view.View;
+
+
+/**
+ * Base class for view tests. Derived class just has to provide a layout id. Tests can then just
+ * call getView() to get a created view and test its behavior.
+ */
+public abstract class ViewTest<T extends View> extends BugleActivityUnitTestCase<TestActivity> {
+    public ViewTest() {
+        super(TestActivity.class);
+    }
+
+    protected T mView;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Create activity
+        final ActivityInstrumentationTestCaseIntent intent =
+                new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
+                TestActivity.class);
+        startActivity(intent, null, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected T getView() {
+        if (mView == null) {
+            // View creation deferred (typically until test time) so that factory/appcontext is
+            // ready.
+            mView = (T) getActivity().getLayoutInflater().inflate(getLayoutIdForView(), null);
+        }
+        return mView;
+    }
+
+    protected void clickButton(final View view) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.performClick();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    protected abstract int getLayoutIdForView();
+}
diff --git a/tests/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragmentTest.java b/tests/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragmentTest.java
new file mode 100644
index 0000000..d723a40
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/attachmentchooser/AttachmentChooserFragmentTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.attachmentchooser;
+
+import android.app.Fragment;
+import android.widget.CheckBox;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.FragmentTestCase;
+import com.android.messaging.ui.TestActivity.FragmentEventListener;
+import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
+import com.android.messaging.ui.conversationlist.ConversationListFragment;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link ConversationListFragment}.
+ */
+@LargeTest
+public class AttachmentChooserFragmentTest extends FragmentTestCase<AttachmentChooserFragment> {
+
+    @Mock protected DataModel mockDataModel;
+    @Mock protected DraftMessageData mockDraftMessageData;
+    @Mock protected AttachmentChooserFragmentHost mockHost;
+
+    private static final String CONVERSATION_ID = "cid";
+
+    /** A custom argument matcher that checks whether the set argument passed in is a set
+     * with identical attachment data as the given set.
+     */
+    private class IsSetOfGivenAttachments implements ArgumentMatcher<Set<MessagePartData>> {
+        private final Set<MessagePartData> mGivenParts;
+        public IsSetOfGivenAttachments(final Set<MessagePartData> givenParts) {
+            mGivenParts = givenParts;
+        }
+
+        @Override
+        public boolean matches(final Set<MessagePartData> actualSet) {
+            if (actualSet.size() != mGivenParts.size()) {
+                return false;
+            }
+            return mGivenParts.containsAll(actualSet) && actualSet.containsAll(mGivenParts);
+        }
+     }
+
+    public AttachmentChooserFragmentTest() {
+        super(AttachmentChooserFragment.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(this.getInstrumentation().getTargetContext())
+            .withDataModel(mockDataModel);
+    }
+
+    private void loadWith(final List<MessagePartData> attachments) {
+        Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        Mockito.doReturn(mockDraftMessageData)
+            .when(mockDataModel)
+            .createDraftMessageData(Mockito.anyString());
+        Mockito.doReturn(attachments)
+            .when(mockDraftMessageData)
+            .getReadOnlyAttachments();
+        Mockito.when(mockDataModel.createDraftMessageData(
+                Matchers.anyString()))
+            .thenReturn(mockDraftMessageData);
+
+        // Create fragment synchronously to avoid need for volatile, synchronization etc.
+        final AttachmentChooserFragment fragment = getFragment();
+        // Binding to model happens when attaching fragment to activity, so hook into test
+        // activity to do so.
+        getActivity().setFragmentEventListener(new FragmentEventListener() {
+            @Override
+            public void onAttachFragment(final Fragment attachedFragment) {
+                if (fragment == attachedFragment) {
+                    fragment.setConversationId(CONVERSATION_ID);
+                }
+            }
+        });
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fragment.setHost(mockHost);
+                getActivity().setFragment(fragment);
+                Mockito.verify(mockDataModel).createDraftMessageData(
+                        Mockito.matches(CONVERSATION_ID));
+                Mockito.verify(mockDraftMessageData).loadFromStorage(
+                        Matchers.eq(fragment.mBinding), Matchers.eq((MessageData) null),
+                        Matchers.eq(false));
+            }
+        });
+        // Now load the cursor
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fragment.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    public void testUnselect() {
+        final List<MessagePartData> attachments = TestDataFactory.getTestDraftAttachments();
+        loadWith(attachments);
+        final AttachmentGridView attachmentGridView = (AttachmentGridView)
+                getFragment().getView().findViewById(R.id.grid);
+        assertEquals("bad view count", attachments.size(),
+                attachmentGridView.getAdapter().getCount());
+
+        final AttachmentGridItemView itemView = (AttachmentGridItemView)
+                attachmentGridView.getChildAt(0);
+        assertEquals(attachmentGridView, itemView.testGetHostInterface());
+        final CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
+        assertEquals(true, checkBox.isChecked());
+        assertEquals(true, attachmentGridView.isItemSelected(itemView.mAttachmentData));
+        clickButton(checkBox);
+        assertEquals(false, checkBox.isChecked());
+        assertEquals(false, attachmentGridView.isItemSelected(itemView.mAttachmentData));
+
+        final AttachmentGridItemView itemView2 = (AttachmentGridItemView)
+                attachmentGridView.getChildAt(1);
+        final CheckBox checkBox2 = (CheckBox) itemView2.findViewById(R.id.checkbox);
+        clickButton(checkBox2);
+
+        getFragment().confirmSelection();
+        final MessagePartData[] attachmentsToRemove = new MessagePartData[] {
+                itemView.mAttachmentData, itemView2.mAttachmentData };
+        Mockito.verify(mockDraftMessageData).removeExistingAttachments(Matchers.argThat(
+                new IsSetOfGivenAttachments(new HashSet<>(Arrays.asList(attachmentsToRemove)))));
+        Mockito.verify(mockDraftMessageData).saveToStorage(Matchers.eq(getFragment().mBinding));
+        Mockito.verify(mockHost).onConfirmSelection();
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/contact/ContactListItemViewTest.java b/tests/src/com/android/messaging/ui/contact/ContactListItemViewTest.java
new file mode 100644
index 0000000..de4c583
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/contact/ContactListItemViewTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.Contacts;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.data.ContactListItemData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.ContactIconView;
+import com.android.messaging.ui.ViewTest;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public class ContactListItemViewTest extends ViewTest<ContactListItemView> {
+
+    @Mock ContactListItemView.HostInterface mockHost;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getTargetContext();
+        FakeFactory.register(context)
+            .withDataModel(new FakeDataModel(context));
+    }
+
+    protected void verifyAddedContactForData(final ContactListItemData data,
+            final ContactListItemView view) {
+        Mockito.verify(mockHost).onContactListItemClicked(data, view);
+    }
+
+    protected void verifyContent(
+            final ContactListItemView view,
+            final String contactName,
+            final String contactDetail,
+            final String avatarUrl,
+            final boolean showAvatar) {
+        final TextView contactNameView = (TextView) view.findViewById(R.id.contact_name);
+        final TextView contactDetailView = (TextView) view.findViewById(R.id.contact_details);
+        final ContactIconView avatarView = (ContactIconView) view.findViewById(R.id.contact_icon);
+
+        assertNotNull(contactNameView);
+        assertEquals(contactName, contactNameView.getText());
+        assertNotNull(contactDetail);
+        assertEquals(contactDetail, contactDetailView.getText());
+        assertNotNull(avatarView);
+        if (showAvatar) {
+            assertTrue(avatarView.mImageRequestBinding.isBound());
+            assertEquals(View.VISIBLE, avatarView.getVisibility());
+        } else {
+            assertFalse(avatarView.mImageRequestBinding.isBound());
+            assertEquals(View.INVISIBLE, avatarView.getVisibility());
+        }
+    }
+
+    public void testBindFirstLevel() {
+        final ContactListItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
+        final int row = TestDataFactory.CONTACT_LIST_CURSOR_FIRST_LEVEL_CONTACT_INDEX;
+        cursor.moveToPosition(row);
+        view.bind(cursor, mockHost, false, null);
+        verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
+                (String) cursor.getAt(Phone.NUMBER, row),
+                (String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), true);
+    }
+
+    public void testBindSecondLevel() {
+        final ContactListItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
+        final int row = TestDataFactory.CONTACT_LIST_CURSOR_SECOND_LEVEL_CONTACT_INDEX;
+        cursor.moveToPosition(row);
+        view.bind(cursor, mockHost, false, null);
+        verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
+                (String) cursor.getAt(Phone.NUMBER, row),
+                (String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), false);
+    }
+
+    public void testClickAddedContact() {
+        final ContactListItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
+        cursor.moveToFirst();
+
+        view.bind(cursor, mockHost, false, null);
+        view.performClick();
+        verifyAddedContactForData(view.mData, view);
+    }
+
+    public void testBindTwice() {
+        final ContactListItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
+
+        cursor.moveToFirst();
+        view.bind(cursor, mockHost, false, null);
+
+        cursor.moveToNext();
+        view.bind(cursor, mockHost, false, null);
+        verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, 1),
+                (String) cursor.getAt(Phone.NUMBER, 1),
+                (String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, 1), true);
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.contact_list_item_view;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/contact/ContactPickerFragmentTest.java b/tests/src/com/android/messaging/ui/contact/ContactPickerFragmentTest.java
new file mode 100644
index 0000000..4983cd3
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/contact/ContactPickerFragmentTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.contact;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.View;
+import android.widget.ListView;
+
+import androidx.test.filters.LargeTest;
+import androidx.viewpager.widget.ViewPager;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.action.ActionTestHelpers;
+import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
+import com.android.messaging.datamodel.action.GetOrCreateConversationAction;
+import com.android.messaging.datamodel.data.ContactPickerData;
+import com.android.messaging.datamodel.data.ParticipantData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.CustomHeaderViewPagerAdapter;
+import com.android.messaging.ui.FragmentTestCase;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.contact.ContactPickerFragment.ContactPickerFragmentHost;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.List;
+
+/**
+ * Unit tests for {@link ContactPickerFragment}.
+ */
+@LargeTest
+public class ContactPickerFragmentTest
+    extends FragmentTestCase<ContactPickerFragment> {
+
+    @Mock protected ContactPickerData mMockContactPickerData;
+    @Mock protected UIIntents mMockUIIntents;
+    @Mock protected ContactPickerFragmentHost mockHost;
+    protected FakeDataModel mFakeDataModel;
+    private ActionTestHelpers.StubActionService mService;
+
+    public ContactPickerFragmentTest() {
+        super(ContactPickerFragment.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Context context = getInstrumentation().getTargetContext();
+        mService = new StubActionService();
+        mFakeDataModel = new FakeDataModel(context)
+            .withContactPickerData(mMockContactPickerData)
+            .withActionService(mService);
+        FakeFactory.register(context)
+                .withDataModel(mFakeDataModel)
+                .withUIIntents(mMockUIIntents);
+    }
+
+    /**
+     * Helper method to initialize the ContactPickerFragment and its data.
+     */
+    private ContactPickerFragmentTest initFragment(final int initialMode) {
+        Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final ContactPickerFragment fragment = getFragment();
+                fragment.setHost(mockHost);
+                fragment.setContactPickingMode(initialMode, false);
+
+                getActivity().setFragment(fragment);
+                Mockito.verify(mMockContactPickerData).init(fragment.getLoaderManager(),
+                        fragment.mBinding);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return this;
+    }
+
+    /**
+     * Bind the datamodel with all contacts cursor to populate the all contacts list in the
+     * fragment.
+     */
+    private ContactPickerFragmentTest loadWithAllContactsCursor(final Cursor cursor) {
+        Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getFragment().onAllContactsCursorUpdated(cursor);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return this;
+    }
+
+    /**
+     * Bind the datamodel with frequent contacts cursor to populate the contacts list in the
+     * fragment.
+     */
+    private ContactPickerFragmentTest loadWithFrequentContactsCursor(final Cursor cursor) {
+        Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getFragment().onFrequentContactsCursorUpdated(cursor);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return this;
+    }
+
+    /**
+     * Test the initial state of the fragment before loading data.
+     */
+    public void testInitialState() {
+        initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT);
+
+        // Make sure that the frequent contacts view is shown by default.
+        final ViewPager pager = (ViewPager) getFragment().getView().findViewById(R.id.pager);
+        final View currentPagedView = pager.getChildAt(pager.getCurrentItem());
+        final View frequentContactsView = ((CustomHeaderViewPagerAdapter) pager.getAdapter())
+                .getViewHolder(0).getView(null);
+        assertEquals(frequentContactsView, currentPagedView);
+    }
+
+    /**
+     * Verifies that list view gets correctly populated given a cursor.
+     */
+    public void testLoadAllContactsList() {
+        final Cursor cursor = TestDataFactory.getAllContactListCursor();
+        initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
+                .loadWithAllContactsCursor(cursor);
+        final ListView listView = (ListView) getFragment().getView()
+                .findViewById(R.id.all_contacts_list);
+        assertEquals(cursor.getCount(), listView.getCount());
+    }
+
+    /**
+     * Verifies that list view gets correctly populated given a cursor.
+     */
+    public void testLoadFrequentContactsList() {
+        final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
+        initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
+                .loadWithFrequentContactsCursor(cursor);
+        final ListView listView = (ListView) getFragment().getView()
+                .findViewById(R.id.frequent_contacts_list);
+        assertEquals(cursor.getCount(), listView.getCount());
+    }
+
+    public void testPickInitialContact() {
+        final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
+        initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
+                .loadWithFrequentContactsCursor(cursor);
+        final ListView listView = (ListView) getFragment().getView()
+                .findViewById(R.id.frequent_contacts_list);
+        // Click on the first contact to add it.
+        final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
+        clickButton(cliv);
+        final ContactRecipientAutoCompleteView chipsView = (ContactRecipientAutoCompleteView)
+                getFragment().getView()
+                .findViewById(R.id.recipient_text_view);
+        // Verify the contact is added to the chips view.
+        final List<ParticipantData> participants =
+                chipsView.getRecipientParticipantDataForConversationCreation();
+        assertEquals(1, participants.size());
+        assertEquals(cliv.mData.getDestination(), participants.get(0).getSendDestination());
+        assertTrue(mService.getCalls().get(0).action instanceof GetOrCreateConversationAction);
+    }
+
+    public void testLeaveChipsMode() {
+        final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
+        initFragment(ContactPickerFragment.MODE_CHIPS_ONLY)
+                .loadWithFrequentContactsCursor(cursor);
+        // Click on the add more participants button
+        // TODO: Figure out a way to click on the add more participants button now that
+        // it's part of the menu.
+        // final ImageButton AddMoreParticipantsButton = (ImageButton) getFragment().getView()
+        //         .findViewById(R.id.add_more_participants_button);
+        // clickButton(AddMoreParticipantsButton);
+        // Mockito.verify(mockHost).onInitiateAddMoreParticipants();
+    }
+
+    public void testPickMoreContacts() {
+        final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
+        initFragment(ContactPickerFragment.MODE_PICK_MORE_CONTACTS)
+                .loadWithFrequentContactsCursor(cursor);
+        final ListView listView = (ListView) getFragment().getView()
+                .findViewById(R.id.frequent_contacts_list);
+        // Click on the first contact to add it.
+        final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
+        clickButton(cliv);
+        // Verify that we don't attempt to create a conversation right away.
+        assertEquals(0, mService.getCalls().size());
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversation/ComposeMessageViewTest.java b/tests/src/com/android/messaging/ui/conversation/ComposeMessageViewTest.java
new file mode 100644
index 0000000..9d55b6e
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversation/ComposeMessageViewTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.isNull;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.view.View;
+import android.widget.EditText;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftForSendTask;
+import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftTaskCallback;
+import com.android.messaging.datamodel.data.MessageData;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.ViewTest;
+import com.android.messaging.ui.conversation.ComposeMessageView.IComposeMessageViewHost;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.FakeMediaUtil;
+import com.android.messaging.util.ImeUtil;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+@MediumTest
+public class ComposeMessageViewTest extends ViewTest<ComposeMessageView> {
+    private Context mContext;
+
+    @Mock protected DataModel mockDataModel;
+    @Mock protected DraftMessageData mockDraftMessageData;
+    @Mock protected BugleGservices mockBugleGservices;
+    @Mock protected ImeUtil mockImeUtil;
+    @Mock protected IComposeMessageViewHost mockIComposeMessageViewHost;
+    @Mock protected MediaPlayer mockMediaPlayer;
+    @Mock protected ConversationInputManager mockInputManager;
+    @Mock protected ConversationData mockConversationData;
+
+    Binding<ConversationData> mConversationBinding;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        FakeFactory.register(mContext)
+                .withDataModel(mockDataModel)
+                .withBugleGservices(mockBugleGservices)
+                .withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
+
+        Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
+        mConversationBinding = BindingBase.createBinding(this);
+        mConversationBinding.bind(mockConversationData);
+    }
+
+    @Override
+    protected ComposeMessageView getView() {
+        final ComposeMessageView view = super.getView();
+        view.setInputManager(mockInputManager);
+        view.setConversationDataModel(BindingBase.createBindingReference(mConversationBinding));
+        return view;
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.compose_message_view;
+    }
+
+    public void testSend() {
+        Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
+                .thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
+        Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(true);
+        Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(true);
+        final ComposeMessageView view = getView();
+
+        final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
+                "Sample Message");
+
+        Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
+                .thenReturn(true);
+        Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
+        Mockito.when(mockDraftMessageData.prepareMessageForSending(
+                Matchers.<BindingBase<DraftMessageData>>any()))
+                .thenReturn(message);
+        Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
+        Mockito.doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                // Synchronously pass the draft check and callback.
+                ((CheckDraftTaskCallback)invocation.getArguments()[2]).onDraftChecked(
+                        mockDraftMessageData, CheckDraftForSendTask.RESULT_PASSED);
+                return null;
+            }
+        }).when(mockDraftMessageData).checkDraftForAction(Mockito.anyBoolean(), Mockito.anyInt(),
+                Mockito.<CheckDraftTaskCallback>any(),
+                Mockito.<Binding<DraftMessageData>>any());
+
+        view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
+
+        final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
+        final View sendButton = view.findViewById(R.id.send_message_button);
+
+        view.requestDraftMessage(false);
+
+        Mockito.verify(mockDraftMessageData).loadFromStorage(any(BindingBase.class),
+                isNull(), Mockito.eq(false));
+
+        view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
+
+        assertEquals(message.getMessageText(), composeEditText.getText().toString());
+
+        sendButton.performClick();
+        Mockito.verify(mockIComposeMessageViewHost).sendMessage(
+                Mockito.argThat(o -> {
+                    assertEquals(message.getMessageText(), o.getMessageText());
+                    return true;
+                }));
+    }
+
+    public void testNotDefaultSms() {
+        Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
+                .thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
+        Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(false);
+        Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(false);
+        final ComposeMessageView view = getView();
+
+        final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
+                "Sample Message");
+
+        Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
+                .thenReturn(true);
+        Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
+        Mockito.when(mockDraftMessageData.prepareMessageForSending(
+                Matchers.<BindingBase<DraftMessageData>>any()))
+                .thenReturn(message);
+        Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
+
+        view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
+
+        final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
+        final View sendButton = view.findViewById(R.id.send_message_button);
+
+        view.requestDraftMessage(false);
+
+        Mockito.verify(mockDraftMessageData).loadFromStorage(any(BindingBase.class),
+                isNull(), Mockito.eq(false));
+
+        view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
+
+        assertEquals(message.getMessageText(), composeEditText.getText().toString());
+
+        sendButton.performClick();
+        Mockito.verify(mockIComposeMessageViewHost).warnOfMissingActionConditions(
+                any(Boolean.class), any(Runnable.class));
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversation/ConversationActivityUiStateTest.java b/tests/src/com/android/messaging/ui/conversation/ConversationActivityUiStateTest.java
new file mode 100644
index 0000000..0fec12e
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversation/ConversationActivityUiStateTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.text.TextUtils;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.ui.contact.ContactPickerFragment;
+import com.android.messaging.ui.conversation.ConversationActivityUiState.ConversationActivityUiStateHost;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+@SmallTest
+public class ConversationActivityUiStateTest extends BugleTestCase {
+    @Mock protected ConversationActivityUiStateHost mockListener;
+
+    /**
+     * Test the Ui state where we start off with the contact picker to pick the first contact.
+     */
+    public void testPickInitialContact() {
+        final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
+        uiState.setHost(mockListener);
+        assertTrue(uiState.shouldShowContactPickerFragment());
+        assertFalse(uiState.shouldShowConversationFragment());
+        assertEquals(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT,
+                uiState.getDesiredContactPickingMode());
+        uiState.onGetOrCreateConversation("conversation1");
+        Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
+                Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT),
+                Mockito.eq(
+                        ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
+                Mockito.anyBoolean());
+        assertTrue(uiState.shouldShowContactPickerFragment());
+        assertTrue(uiState.shouldShowConversationFragment());
+        assertTrue(TextUtils.equals("conversation1", uiState.getConversationId()));
+        assertEquals(ContactPickerFragment.MODE_CHIPS_ONLY,
+                uiState.getDesiredContactPickingMode());
+    }
+
+    /**
+     * Test the Ui state where we have both the chips view and the conversation view and we
+     * start message compose.
+     */
+    public void testHybridUiStateStartCompose() {
+        final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
+        uiState.testSetUiState(
+                ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
+        uiState.setHost(mockListener);
+
+        // Start message compose.
+        uiState.onStartMessageCompose();
+        Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
+                Mockito.eq(
+                        ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
+                Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
+                Mockito.anyBoolean());
+        assertFalse(uiState.shouldShowContactPickerFragment());
+        assertTrue(uiState.shouldShowConversationFragment());
+    }
+
+    /**
+     * Test the Ui state where we have both the chips view and the conversation view and we
+     * try to add a participant.
+     */
+    public void testHybridUiStateAddParticipant() {
+        final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
+        uiState.testSetUiState(
+                ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
+        uiState.setHost(mockListener);
+
+        uiState.onAddMoreParticipants();
+        Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
+                Mockito.eq(
+                        ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
+                Mockito.eq(
+                        ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
+                Mockito.anyBoolean());
+        assertTrue(uiState.shouldShowContactPickerFragment());
+        assertFalse(uiState.shouldShowConversationFragment());
+        assertEquals(ContactPickerFragment.MODE_PICK_MORE_CONTACTS,
+                uiState.getDesiredContactPickingMode());
+    }
+
+    /**
+     * Test the Ui state where we are trying to add more participants and commit.
+     */
+    public void testCommitAddParticipant() {
+        final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
+        uiState.testSetUiState(
+                ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS);
+        uiState.setHost(mockListener);
+
+        uiState.onGetOrCreateConversation("conversation1");
+
+        // After adding more contacts, the terminal state is always conversation only (i.e. we
+        // don't go back to hybrid mode).
+        Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
+                Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
+                Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
+                Mockito.anyBoolean());
+        assertFalse(uiState.shouldShowContactPickerFragment());
+        assertTrue(uiState.shouldShowConversationFragment());
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversation/ConversationFragmentTest.java b/tests/src/com/android/messaging/ui/conversation/ConversationFragmentTest.java
new file mode 100644
index 0000000..030306a
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversation/ConversationFragmentTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.database.Cursor;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.filters.LargeTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.datamodel.MemoryCacheManager;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.datamodel.media.MediaResourceManager;
+import com.android.messaging.ui.FragmentTestCase;
+import com.android.messaging.ui.PlainTextEditText;
+import com.android.messaging.ui.TestActivity.FragmentEventListener;
+import com.android.messaging.ui.conversation.ConversationFragment.ConversationFragmentHost;
+import com.android.messaging.ui.conversationlist.ConversationListFragment;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.ImeUtil;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+/**
+ * Unit tests for {@link ConversationListFragment}.
+ */
+@LargeTest
+public class ConversationFragmentTest extends FragmentTestCase<ConversationFragment> {
+
+    @Mock protected DataModel mockDataModel;
+    @Mock protected ConversationData mockConversationData;
+    @Mock protected DraftMessageData mockDraftMessageData;
+    @Mock protected MediaResourceManager mockMediaResourceManager;
+    @Mock protected BugleGservices mockBugleGservices;
+    @Mock protected ConversationFragmentHost mockHost;
+    @Mock protected MemoryCacheManager mockMemoryCacheManager;
+
+    private ImeUtil mSpiedImeUtil;
+
+    private static final String CONVERSATION_ID = "cid";
+
+
+    public ConversationFragmentTest() {
+        super(ConversationFragment.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+      ImeUtil.clearInstance();
+      mSpiedImeUtil = Mockito.spy(new ImeUtil());
+      FakeFactory.register(this.getInstrumentation().getTargetContext())
+          .withDataModel(mockDataModel)
+          .withBugleGservices(mockBugleGservices)
+          .withMemoryCacheManager(mockMemoryCacheManager);
+    }
+
+    /**
+     * Helper that will do the 'binding' of ConversationFragmentTest with ConversationData and
+     * leave fragment in 'ready' state.
+     * @param cursor
+     */
+    private void loadWith(final Cursor cursor) {
+        Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        Mockito.when(mockConversationData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        Mockito.doReturn(mockDraftMessageData)
+            .when(mockDataModel)
+            .createDraftMessageData(Mockito.anyString());
+        Mockito.doReturn(mockDraftMessageData)
+            .when(mockDataModel)
+            .createDraftMessageData(null);
+        Mockito.when(mockDataModel.createConversationData(
+                Matchers.any(Activity.class),
+                Matchers.any(ConversationDataListener.class),
+                Matchers.anyString()))
+            .thenReturn(mockConversationData);
+
+        // Create fragment synchronously to avoid need for volatile, synchronization etc.
+        final ConversationFragment fragment = getFragment();
+        // Binding to model happens when attaching fragment to activity, so hook into test
+        // activity to do so.
+        getActivity().setFragmentEventListener(new FragmentEventListener() {
+            @Override
+            public void onAttachFragment(final Fragment attachedFragment) {
+                if (fragment == attachedFragment) {
+                    fragment.setConversationInfo(getActivity(), CONVERSATION_ID, null);
+                }
+            }
+        });
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fragment.setHost(mockHost);
+                getActivity().setFragment(fragment);
+                Mockito.verify(mockDataModel).createConversationData(
+                        getActivity(), fragment, CONVERSATION_ID);
+                Mockito.verify(mockConversationData).init(fragment.getLoaderManager(),
+                        fragment.mBinding);
+            }
+        });
+        // Wait for initial layout pass to work around crash in recycler view
+        getInstrumentation().waitForIdleSync();
+        // Now load the cursor
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fragment.onConversationMessagesCursorUpdated(mockConversationData, cursor, null,
+                        false);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    /**
+     * Verifies that list view gets correctly populated given a cursor.
+     */
+    public void testLoadListView() {
+        final Cursor cursor = TestDataFactory.getConversationMessageCursor();
+        loadWith(cursor);
+        final RecyclerView listView =
+                (RecyclerView) getFragment().getView().findViewById(android.R.id.list);
+        assertEquals("bad cursor", cursor.getCount(), listView.getAdapter().getItemCount());
+        assertEquals("bad cursor count", cursor.getCount(), listView.getChildCount());
+    }
+
+    public void testClickComposeMessageView() {
+        final Cursor cursor = TestDataFactory.getConversationMessageCursor();
+        loadWith(cursor);
+
+        final PlainTextEditText composeEditText = (PlainTextEditText) getFragment().getView()
+                .findViewById(R.id.compose_message_text);
+        setFocus(composeEditText, false);
+        Mockito.verify(mockHost, Mockito.never()).onStartComposeMessage();
+        setFocus(composeEditText, true);
+        Mockito.verify(mockHost).onStartComposeMessage();
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversation/ConversationInputManagerTest.java b/tests/src/com/android/messaging/ui/conversation/ConversationInputManagerTest.java
new file mode 100644
index 0000000..6dff635
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversation/ConversationInputManagerTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.conversation;
+
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.widget.EditText;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.ConversationData;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.SubscriptionListData;
+import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputHost;
+import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputSink;
+import com.android.messaging.ui.mediapicker.MediaPicker;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.ImeUtil;
+import com.android.messaging.util.ImeUtil.ImeStateHost;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+@SmallTest
+public class ConversationInputManagerTest extends BugleTestCase {
+    @Spy protected ImeUtil spyImeUtil;
+    @Mock protected BugleGservices mockBugleGservices;
+    @Mock protected FragmentManager mockFragmentManager;
+    @Mock protected ConversationInputHost mockConversationInputHost;
+    @Mock protected ConversationInputSink mockConversationInputSink;
+    @Mock protected ImeStateHost mockImeStateHost;
+    @Mock protected ConversationData mockConversationData;
+    @Mock protected DraftMessageData mockDraftMessageData;
+    @Mock protected MediaPicker mockMediaPicker;
+    @Mock protected SubscriptionListData mockSubscriptionListData;
+    @Mock protected FragmentTransaction mockFragmentTransaction;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getTestContext())
+                .withBugleGservices(mockBugleGservices);
+        spyImeUtil = Mockito.spy(new ImeUtil());
+        ImeUtil.set(spyImeUtil);
+    }
+
+    private ConversationInputManager initNewInputManager(final Bundle savedState) {
+        // Set up the mocks.
+        Mockito.when(mockConversationInputHost.getSimSelectorView())
+                .thenReturn(new SimSelectorView(getTestContext(), null));
+        Mockito.when(mockConversationInputHost.createMediaPicker()).thenReturn(mockMediaPicker);
+        Mockito.when(mockConversationInputSink.getComposeEditText())
+                .thenReturn(new EditText(getTestContext()));
+        Mockito.doReturn(mockFragmentTransaction).when(mockFragmentTransaction).replace(
+                Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
+                Mockito.anyString());
+        Mockito.when(mockFragmentManager.findFragmentByTag(MediaPicker.FRAGMENT_TAG))
+                .thenReturn(null);
+        Mockito.when(mockFragmentManager.beginTransaction()).thenReturn(mockFragmentTransaction);
+        Mockito.when(mockSubscriptionListData.hasData()).thenReturn(true);
+        Mockito.when(mockConversationData.getSubscriptionListData())
+                .thenReturn(mockSubscriptionListData);
+        Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
+        Mockito.doReturn(true).when(mockDraftMessageData).isBound(Mockito.anyString());
+
+        final Binding<ConversationData> dataBinding = BindingBase.createBinding(this);
+        dataBinding.bind(mockConversationData);
+        final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
+        draftBinding.bind(mockDraftMessageData);
+        final ConversationInputManager inputManager = new ConversationInputManager(getTestContext(),
+                mockConversationInputHost, mockConversationInputSink, mockImeStateHost,
+                mockFragmentManager, dataBinding, draftBinding, savedState);
+        return inputManager;
+    }
+
+    public void testShowHideInputs() {
+        final ConversationInputManager inputManager = initNewInputManager(new Bundle());
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
+        inputManager.showHideMediaPicker(true /* show */, true /* animate */);
+        Mockito.verify(mockFragmentTransaction).replace(
+                Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
+                Mockito.anyString());
+        Mockito.verify(mockMediaPicker).open(Mockito.anyInt(), Mockito.eq(true /* animate */));
+
+        assertEquals(true, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
+        inputManager.showHideMediaPicker(false /* show */, true /* animate */);
+        Mockito.verify(mockMediaPicker).dismiss(Mockito.eq(true /* animate */));
+
+        assertEquals(false, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+    }
+
+    public void testShowTwoInputsSequentially() {
+        // First show the media picker, then show the IME keyboard.
+        final ConversationInputManager inputManager = initNewInputManager(new Bundle());
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
+        inputManager.showHideMediaPicker(true /* show */, true /* animate */);
+
+        assertEquals(true, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
+        inputManager.showHideImeKeyboard(true /* show */, true /* animate */);
+
+        assertEquals(false, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(true, inputManager.isImeKeyboardVisible());
+    }
+
+    public void testOnKeyboardShow() {
+        final ConversationInputManager inputManager = initNewInputManager(new Bundle());
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
+        inputManager.showHideMediaPicker(true /* show */, true /* animate */);
+
+        assertEquals(true, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
+        inputManager.testNotifyImeStateChanged(true /* imeOpen */);
+
+        assertEquals(false, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(true, inputManager.isImeKeyboardVisible());
+    }
+
+    public void testRestoreState() {
+        final ConversationInputManager inputManager = initNewInputManager(new Bundle());
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
+        inputManager.showHideMediaPicker(true /* show */, true /* animate */);
+
+        assertEquals(true, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+
+        Bundle savedInstanceState = new Bundle();
+        inputManager.onSaveInputState(savedInstanceState);
+
+        // Now try to restore the state
+        final ConversationInputManager restoredInputManager =
+                initNewInputManager(savedInstanceState);
+
+        // Make sure the state is preserved.
+        assertEquals(true, restoredInputManager.isMediaPickerVisible());
+        assertEquals(false, restoredInputManager.isSimSelectorVisible());
+        assertEquals(false, restoredInputManager.isImeKeyboardVisible());
+    }
+
+    public void testBackPress() {
+        final ConversationInputManager inputManager = initNewInputManager(new Bundle());
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
+        inputManager.showHideMediaPicker(true /* show */, true /* animate */);
+
+        assertEquals(true, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+
+        Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
+        assertEquals(true, inputManager.onBackPressed());
+
+        assertEquals(false, inputManager.isMediaPickerVisible());
+        assertEquals(false, inputManager.isSimSelectorVisible());
+        assertEquals(false, inputManager.isImeKeyboardVisible());
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversation/ConversationMessageViewTest.java b/tests/src/com/android/messaging/ui/conversation/ConversationMessageViewTest.java
new file mode 100644
index 0000000..6833df2
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversation/ConversationMessageViewTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversation;
+
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.ViewTest;
+import com.android.messaging.ui.conversation.ConversationMessageView.ConversationMessageViewHost;
+import com.android.messaging.util.Dates;
+
+import org.mockito.Mock;
+
+@MediumTest
+public class ConversationMessageViewTest extends ViewTest<ConversationMessageView> {
+    @Mock ConversationMessageViewHost mockHost;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getInstrumentation().getTargetContext());
+    }
+
+    @Override
+    protected ConversationMessageView getView() {
+        final ConversationMessageView view = super.getView();
+        view.setHost(mockHost);
+        return view;
+    }
+
+    protected void verifyContent(final ConversationMessageView view, final String messageText,
+            final boolean showTimestamp, final String timestampText) {
+
+        final TextView messageTextView = (TextView) view.findViewById(R.id.message_text);
+        final TextView statusTextView = (TextView) view.findViewById(R.id.message_status);
+
+        assertNotNull(messageTextView);
+        assertEquals(messageText, messageTextView.getText());
+
+        if (showTimestamp) {
+            assertEquals(View.VISIBLE, statusTextView.getVisibility());
+            assertEquals(timestampText, statusTextView.getText());
+        } else {
+            assertEquals(View.GONE, statusTextView.getVisibility());
+        }
+    }
+
+    public void testBind() {
+        final ConversationMessageView view = getView();
+
+        final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
+        cursor.moveToFirst();
+
+        view.bind(cursor);
+        verifyContent(view, TestDataFactory.getMessageText(cursor, 0), true, Dates
+                .getMessageTimeString((Long) cursor.getAt("received_timestamp", 0)).toString());
+    }
+
+    public void testBindTwice() {
+        final ConversationMessageView view = getView();
+
+        final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
+        cursor.moveToFirst();
+        view.bind(cursor);
+
+        cursor.moveToNext();
+        view.bind(cursor);
+        verifyContent(view, TestDataFactory.getMessageText(cursor, 1), true, Dates
+                .getMessageTimeString((Long) cursor.getAt("received_timestamp", 1)).toString());
+    }
+
+    public void testBindLast() {
+        final ConversationMessageView view = getView();
+
+        final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
+        final int lastPos = cursor.getCount() - 1;
+        cursor.moveToPosition(lastPos);
+
+        view.bind(cursor);
+        verifyContent(view, TestDataFactory.getMessageText(cursor, lastPos), true, Dates
+                .getMessageTimeString((Long) cursor.getAt("received_timestamp", lastPos))
+                .toString());
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.conversation_message_view;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversationlist/ConversationListFragmentTest.java b/tests/src/com/android/messaging/ui/conversationlist/ConversationListFragmentTest.java
new file mode 100644
index 0000000..c3da81c
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversationlist/ConversationListFragmentTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.filters.LargeTest;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.data.ConversationListData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.FragmentTestCase;
+import com.android.messaging.ui.UIIntents;
+import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+/**
+ * Unit tests for {@link ConversationListFragment}.
+ */
+@LargeTest
+public class ConversationListFragmentTest
+    extends FragmentTestCase<ConversationListFragment> {
+
+    @Mock protected ConversationListData mMockConversationListData;
+    @Mock protected ConversationListFragmentHost mMockConversationHostListHost;
+    @Mock protected UIIntents mMockUIIntents;
+    protected FakeDataModel mFakeDataModel;
+
+    public ConversationListFragmentTest() {
+        super(ConversationListFragment.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Context context = getInstrumentation().getTargetContext();
+        mFakeDataModel = new FakeDataModel(context)
+            .withConversationListData(mMockConversationListData);
+        FakeFactory.register(context)
+                .withDataModel(mFakeDataModel)
+                .withUIIntents(mMockUIIntents);
+    }
+
+    /**
+     * Helper that will do the 'binding' of ConversationListFragmentTest with ConversationListData
+     * and leave fragment in 'ready' state.
+     * @param cursor
+     */
+    private void loadWith(final Cursor cursor) {
+        Mockito.when(mMockConversationListData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+
+        final ConversationListFragment fragment = getFragment();
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fragment.setHost(mMockConversationHostListHost);
+                getActivity().setFragment(fragment);
+                Mockito.verify(mMockConversationListData).init(fragment.getLoaderManager(),
+                        fragment.mListBinding);
+                fragment.onConversationListCursorUpdated(mMockConversationListData, cursor);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    /**
+     * Verifies that list view gets correctly populated given a cursor.
+     */
+    public void testLoadListView() {
+        final Cursor cursor = TestDataFactory.getConversationListCursor();
+        loadWith(cursor);
+        final RecyclerView listView =
+                (RecyclerView) getFragment().getView().findViewById(android.R.id.list);
+        //assertEquals(cursor.getCount(), listView.getCount());
+        assertEquals(cursor.getCount(), listView.getChildCount());
+    }
+
+    /**
+     * Verifies that 'empty list' promo is rendered with an empty cursor.
+     */
+    public void testEmptyView() {
+        loadWith(TestDataFactory.getEmptyConversationListCursor());
+        final RecyclerView listView =
+                (RecyclerView) getFragment().getView().findViewById(android.R.id.list);
+        final View emptyMessageView =
+                getFragment().getView().findViewById(R.id.no_conversations_view);
+        assertEquals(View.VISIBLE, emptyMessageView.getVisibility());
+        assertEquals(0, listView.getChildCount());
+    }
+
+    /**
+     * Verifies that the button to start a new conversation works.
+     */
+    public void testStartNewConversation() {
+        final Cursor cursor = TestDataFactory.getConversationListCursor();
+        loadWith(cursor);
+        final ImageView startNewConversationButton = (ImageView)
+                getFragment().getView().findViewById(R.id.start_new_conversation_button);
+
+        clickButton(startNewConversationButton);
+        Mockito.verify(mMockConversationHostListHost).onCreateConversationClick();
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/conversationlist/ConversationListItemViewTest.java b/tests/src/com/android/messaging/ui/conversationlist/ConversationListItemViewTest.java
new file mode 100644
index 0000000..c96ab44
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/conversationlist/ConversationListItemViewTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.conversationlist;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.messaging.Factory;
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.data.ConversationListItemData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.UIIntentsImpl;
+import com.android.messaging.ui.ViewTest;
+import com.android.messaging.util.Dates;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+@MediumTest
+public class ConversationListItemViewTest extends ViewTest<ConversationListItemView> {
+
+    @Mock private ConversationListItemView.HostInterface mockHost;
+    private FakeCursor mCursor;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getTargetContext();
+        FakeFactory.register(context)
+            .withDataModel(new FakeDataModel(context))
+            .withUIIntents(new UIIntentsImpl());
+        mCursor = TestDataFactory.getConversationListCursor();
+    }
+
+
+    protected void verifyLaunchedConversationForId(final String id,
+            final ConversationListItemView conversationView) {
+        // Must be a short click.
+        final ArgumentMatcher<ConversationListItemData> itemDataIdMatcher =
+                arg -> TextUtils.equals(id, arg.getConversationId());
+        Mockito.verify(mockHost).onConversationClicked(
+                Mockito.argThat(itemDataIdMatcher), Mockito.eq(false),
+                Mockito.eq(conversationView));
+    }
+
+    protected void verifyContent(
+            final ConversationListItemView view, final FakeCursor cursor, final int index) {
+        /* ConversationQueryColumns.NAME */
+        final String  conversationQueryColumnsName = "name";
+        final String name = (String) cursor.getAt(conversationQueryColumnsName, index);
+
+        /* ConversationQueryColumns.SNIPPET_TEXT */
+        final String  conversationQueryColumnsSnippetText = "snippet_text";
+        final String snippet = (String) cursor.getAt(conversationQueryColumnsSnippetText, index);
+
+        /* ConversationQueryColumns.SORT_TIMESTAMP */
+        final String  conversationQueryColumnsSortTimestamp = "sort_timestamp";
+        final String timestamp = Dates.getConversationTimeString(
+                (Long) cursor.getAt(conversationQueryColumnsSortTimestamp, index)).toString();
+
+        final boolean unread = !isRead(cursor, index);
+        verifyContent(view, name,  snippet, timestamp, unread);
+    }
+
+    protected void verifyContent(
+            final ConversationListItemView view,
+            final String conversationName,
+            final String snippet,
+            final String timestamp,
+            final boolean unread) {
+        final TextView conversationNameView =
+                (TextView) view.findViewById(R.id.conversation_name);
+        final TextView snippetTextView = (TextView) view.findViewById(R.id.conversation_snippet);
+        final TextView timestampTextView = (TextView) view.findViewById(
+                R.id.conversation_timestamp);
+        final AsyncImageView imagePreviewView =
+                (AsyncImageView) view.findViewById(R.id.conversation_image_preview);
+
+        final Context context = Factory.get().getApplicationContext();
+        assertNotNull(conversationNameView);
+        assertEquals(conversationName, conversationNameView.getText());
+        assertNotNull(snippetTextView);
+        if (unread) {
+            assertEquals(ConversationListItemView.UNREAD_SNIPPET_LINE_COUNT,
+                    snippetTextView.getMaxLines());
+            assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
+                    snippetTextView.getCurrentTextColor());
+            assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
+                    conversationNameView.getCurrentTextColor());
+
+        } else {
+            assertEquals(ConversationListItemView.NO_UNREAD_SNIPPET_LINE_COUNT,
+                    snippetTextView.getMaxLines());
+            assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
+                    snippetTextView.getCurrentTextColor());
+            assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
+                    conversationNameView.getCurrentTextColor());
+        }
+
+        assertEquals(View.VISIBLE, imagePreviewView.getVisibility());
+        assertTrue(snippetTextView.getText().toString().contains(snippet));
+        assertEquals(timestamp, timestampTextView.getText());
+    }
+
+    protected boolean isRead(final FakeCursor cursor, final int index) {
+        return 1 == ((Integer) cursor.getAt("read", index)).intValue();
+    }
+
+    public void testBindUnread() {
+        final ConversationListItemView view = getView();
+        final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_UNREAD_MESSAGE_INDEX;
+        mCursor.moveToPosition(messageIndex);
+        assertFalse(isRead(mCursor, messageIndex));
+        view.bind(mCursor, mockHost);
+        verifyContent(view, mCursor, messageIndex);
+    }
+
+    public void testBindRead() {
+        final ConversationListItemView view = getView();
+
+        final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_READ_MESSAGE_INDEX;
+        mCursor.moveToPosition(messageIndex);
+        assertTrue(isRead(mCursor, messageIndex));
+        view.bind(mCursor, mockHost);
+        verifyContent(view, mCursor, messageIndex);
+    }
+
+    public void testClickLaunchesConversation() {
+        final ConversationListItemView view = getView();
+        final View swipeableContainer = view.findViewById(R.id.swipeableContainer);
+        mCursor.moveToFirst();
+        view.bind(mCursor, mockHost);
+        swipeableContainer.performClick();
+        verifyLaunchedConversationForId(
+                mCursor.getAt("_id" /* ConversationQueryColumns._ID */, 0).toString(), view);
+    }
+
+    public void testBindTwice() {
+        final ConversationListItemView view = getView();
+
+        mCursor.moveToFirst();
+        view.bind(mCursor, mockHost);
+
+        mCursor.moveToNext();
+        view.bind(mCursor, mockHost);
+        verifyContent(view, mCursor, mCursor.getPosition());
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.conversation_list_item_view;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/mediapicker/AudioRecordViewTest.java b/tests/src/com/android/messaging/ui/mediapicker/AudioRecordViewTest.java
new file mode 100644
index 0000000..a38dac2
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/mediapicker/AudioRecordViewTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.media.MediaPlayer;
+import android.media.MediaRecorder.OnErrorListener;
+import android.media.MediaRecorder.OnInfoListener;
+import android.net.Uri;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.data.MessagePartData;
+import com.android.messaging.ui.ViewTest;
+import com.android.messaging.util.FakeMediaUtil;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public class AudioRecordViewTest extends ViewTest<AudioRecordView> {
+
+    @Mock AudioRecordView.HostInterface mockHost;
+    @Mock LevelTrackingMediaRecorder mockRecorder;
+    @Mock MediaPlayer mockMediaPlayer;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        FakeFactory.register(getInstrumentation().getContext())
+                .withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
+    }
+
+    private void verifyAudioSubmitted() {
+        Mockito.verify(mockHost).onAudioRecorded(Matchers.any(MessagePartData.class));
+    }
+
+    private AudioRecordView initView() {
+        final AudioRecordView view = getView();
+        view.testSetMediaRecorder(mockRecorder);
+        view.setHostInterface(mockHost);
+        return view;
+    }
+
+    public void testRecording() {
+        Mockito.when(mockRecorder.isRecording()).thenReturn(false);
+        Mockito.when(mockRecorder.startRecording(Matchers.<OnErrorListener>any(),
+                Matchers.<OnInfoListener>any(), Matchers.anyInt())).thenReturn(true);
+        Mockito.when(mockRecorder.stopRecording()).thenReturn(Uri.parse("content://someaudio/2"));
+        final AudioRecordView view = initView();
+        view.onRecordButtonTouchDown();
+        Mockito.verify(mockRecorder).startRecording(Matchers.<OnErrorListener>any(),
+                Matchers.<OnInfoListener>any(), Matchers.anyInt());
+        Mockito.when(mockRecorder.isRecording()).thenReturn(true);
+        // Record for 1 second to make it meaningful.
+        sleepNoThrow(1000);
+        view.onRecordButtonTouchUp();
+        // We added some buffer to the end of the audio recording, so sleep for sometime and
+        // verify audio is recorded.
+        sleepNoThrow(700);
+        Mockito.verify(mockRecorder).stopRecording();
+        verifyAudioSubmitted();
+    }
+
+    private void sleepNoThrow(final long duration) {
+        try {
+            Thread.sleep(duration);
+        } catch (final InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.mediapicker_audio_chooser;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/mediapicker/CameraManagerTest.java b/tests/src/com/android/messaging/ui/mediapicker/CameraManagerTest.java
new file mode 100644
index 0000000..7417c32
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/mediapicker/CameraManagerTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
+import android.os.AsyncTask;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
+
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+@SmallTest
+public class CameraManagerTest extends BugleTestCase {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Force each test to set up a camera wrapper to match their needs
+        CameraManager.setCameraWrapper(null);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        MockCameraFactory.cleanup();
+    }
+
+    public void testNoCameraDeviceGetInfo() {
+        CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper());
+        assertEquals(false, CameraManager.get().hasAnyCamera());
+        assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
+        boolean threw = false;
+        try {
+            CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        } catch (AssertionError e) {
+            threw = true;
+        }
+        if (!threw) {
+            fail("selectCamera should have thrown");
+        }
+    }
+
+    public void testFrontFacingOnlyGetInfo() {
+        CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT)
+        ));
+        assertEquals(true, CameraManager.get().hasAnyCamera());
+        assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
+        assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
+    }
+
+    public void testBackFacingOnlyGetInfo() {
+        CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
+        ));
+        assertEquals(true, CameraManager.get().hasAnyCamera());
+        assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
+        assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
+    }
+
+    public void testFrontAndBackGetInfo() {
+        CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
+        ));
+        assertEquals(true, CameraManager.get().hasAnyCamera());
+        assertEquals(true, CameraManager.get().hasFrontAndBackCamera());
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
+        assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
+    }
+
+    public void testSwapCamera() {
+        CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
+                MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
+        ));
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
+        assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
+        CameraManager.get().swapCamera();
+        assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
+    }
+
+    public void testOpenCamera() {
+        Camera backCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK);
+        Camera frontCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT);
+        CameraWrapper wrapper = MockCameraFactory.createCameraWrapper(frontCamera, backCamera);
+        CameraManager.setCameraWrapper(wrapper);
+        CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
+        CameraManager.get().openCamera();
+        CameraManager.get().openCamera();
+        CameraManager.get().openCamera();
+        waitForPendingAsyncTasks();
+        Mockito.verify(wrapper, Mockito.never()).open(0);
+        Mockito.verify(wrapper).open(1);
+        Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
+        Mockito.verify(wrapper, Mockito.never()).release(backCamera);
+        CameraManager.get().swapCamera();
+        waitForPendingAsyncTasks();
+        Mockito.verify(wrapper).open(0);
+        Mockito.verify(wrapper).open(1);
+        Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
+        Mockito.verify(wrapper).release(backCamera);
+        InOrder inOrder = Mockito.inOrder(wrapper);
+        inOrder.verify(wrapper).open(1);
+        inOrder.verify(wrapper).release(backCamera);
+        inOrder.verify(wrapper).open(0);
+    }
+
+    private void waitForPendingAsyncTasks() {
+        try {
+            final Object lockObject = new Object();
+
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... voids) {
+                    return null;
+                }
+
+                @Override
+                protected void onPostExecute(Void aVoid) {
+                    super.onPostExecute(aVoid);
+                    synchronized (lockObject) {
+                        lockObject.notifyAll();
+                    }
+                }
+            }.execute();
+
+            synchronized (lockObject) {
+                lockObject.wait(500);
+            }
+        } catch (InterruptedException e) {
+            fail();
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java b/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java
new file mode 100644
index 0000000..304cc74
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.provider.MediaStore.Images.Media;
+import android.view.View;
+import android.widget.CheckBox;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeCursor;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.data.GalleryGridItemData;
+import com.android.messaging.datamodel.data.TestDataFactory;
+import com.android.messaging.ui.AsyncImageView;
+import com.android.messaging.ui.ViewTest;
+import com.android.messaging.util.UriUtil;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public class GalleryGridItemViewTest extends ViewTest<GalleryGridItemView> {
+
+    @Mock GalleryGridItemView.HostInterface mockHost;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getTargetContext();
+        FakeFactory.register(context)
+            .withDataModel(new FakeDataModel(context));
+    }
+
+    protected void verifyClickedItem(final View view, final GalleryGridItemData data) {
+        Mockito.verify(mockHost).onItemClicked(view, data, false /* longClick */);
+    }
+
+    protected void verifyContent(
+            final GalleryGridItemView view,
+            final String imageUrl,
+            final boolean showCheckbox,
+            final boolean isSelected) {
+        final AsyncImageView imageView = (AsyncImageView) view.findViewById(R.id.thumbnail);
+        final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkbox);
+
+        assertNotNull(imageView);
+        assertTrue(imageView.mImageRequestBinding.isBound());
+        assertTrue(imageView.mImageRequestBinding.getData().getKey().startsWith(imageUrl));
+        assertNotNull(checkBox);
+        if (showCheckbox) {
+            assertEquals(View.VISIBLE, checkBox.getVisibility());
+            assertEquals(isSelected, checkBox.isChecked());
+        } else {
+            assertNotSame(View.VISIBLE, checkBox.getVisibility());
+        }
+    }
+
+    public void testBind() {
+        Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
+        Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
+                .thenReturn(false);
+        final GalleryGridItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
+        cursor.moveToFirst();
+        final String path = (String) cursor.getAt(Media.DATA, 0);
+        view.bind(cursor, mockHost);
+        verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
+                false, false);
+    }
+
+    public void testBindMultiSelectUnSelected() {
+        Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
+        Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
+                .thenReturn(false);
+        final GalleryGridItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
+        cursor.moveToFirst();
+        final String path = (String) cursor.getAt(Media.DATA, 0);
+        view.bind(cursor, mockHost);
+        verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
+                true, false);
+    }
+
+    public void testBindMultiSelectSelected() {
+        Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
+        Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
+                .thenReturn(true);
+        final GalleryGridItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
+        cursor.moveToFirst();
+        final String path = (String) cursor.getAt(Media.DATA, 0);
+        view.bind(cursor, mockHost);
+        verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
+                true, true);
+    }
+
+    public void testClick() {
+        Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
+        Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
+                .thenReturn(false);
+        final GalleryGridItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
+        cursor.moveToFirst();
+        view.bind(cursor, mockHost);
+        view.performClick();
+        verifyClickedItem(view, view.mData);
+    }
+
+    public void testBindTwice() {
+        Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
+        Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
+                .thenReturn(false);
+        final GalleryGridItemView view = getView();
+        final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
+
+        cursor.moveToFirst();
+        view.bind(cursor, mockHost);
+
+        cursor.moveToNext();
+        final String path = (String) cursor.getAt(Media.DATA, 1);
+        view.bind(cursor, mockHost);
+        verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
+                true, false);
+    }
+
+    @Override
+    protected int getLayoutIdForView() {
+        return R.layout.gallery_grid_item_view;
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java b/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java
new file mode 100644
index 0000000..4e7c2d2
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+import com.android.messaging.FakeFactory;
+import com.android.messaging.R;
+import com.android.messaging.datamodel.FakeDataModel;
+import com.android.messaging.datamodel.binding.Binding;
+import com.android.messaging.datamodel.binding.BindingBase;
+import com.android.messaging.datamodel.data.DraftMessageData;
+import com.android.messaging.datamodel.data.MediaPickerData;
+import com.android.messaging.ui.FragmentTestCase;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public class MediaPickerTest extends FragmentTestCase<MediaPicker> {
+    @Mock protected MediaPickerData mMockMediaPickerData;
+    @Mock protected DraftMessageData mMockDraftMessageData;
+    protected FakeDataModel mFakeDataModel;
+
+    public MediaPickerTest() {
+        super(MediaPicker.class);
+    }
+
+    @Override
+    protected MediaPicker getFragment() {
+        if (mFragment == null) {
+            mFragment = new MediaPicker(getInstrumentation().getTargetContext());
+        }
+        return mFragment;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getTargetContext();
+        mFakeDataModel = new FakeDataModel(context)
+                   .withMediaPickerData(mMockMediaPickerData);
+        FakeFactory.register(context)
+                   .withDataModel(mFakeDataModel);
+    }
+
+    /**
+     * Helper method to initialize the MediaPicker and its data.
+     */
+    private void initFragment(final int supportedMediaTypes, final Integer[] expectedLoaderIds,
+            final boolean filterTabBeforeAttach) {
+        Mockito.when(mMockMediaPickerData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        Mockito.when(mMockDraftMessageData.isBound(Matchers.anyString()))
+            .thenReturn(true);
+        final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
+        draftBinding.bind(mMockDraftMessageData);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final MediaPicker fragment = getFragment();
+                if (filterTabBeforeAttach) {
+                    fragment.setSupportedMediaTypes(supportedMediaTypes);
+                    getActivity().setFragment(fragment);
+                } else {
+                    getActivity().setFragment(fragment);
+                    fragment.setSupportedMediaTypes(supportedMediaTypes);
+                }
+                fragment.setDraftMessageDataModel(draftBinding);
+                Mockito.verify(mMockMediaPickerData,
+                        Mockito.atLeastOnce()).init(
+                        Matchers.eq(fragment.getLoaderManager()));
+                fragment.open(MediaPicker.MEDIA_TYPE_ALL, false);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    public void testDefaultTabs() {
+        Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
+        initFragment(MediaPicker.MEDIA_TYPE_ALL, new Integer[] {
+                MediaPickerData.GALLERY_MEDIA_LOADER },
+                false);
+        final MediaPicker mediaPicker = getFragment();
+        final View view = mediaPicker.getView();
+        assertNotNull(view);
+        final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
+        assertEquals(tabStrip.getChildCount(), 4);
+        for (int i = 0; i < tabStrip.getChildCount(); i++) {
+            final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
+            assertEquals(View.VISIBLE, tabButton.getVisibility());
+            assertEquals(i == 0, tabButton.isSelected());
+        }
+    }
+
+    public void testFilterTabsBeforeAttach() {
+        Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
+        initFragment(MediaPicker.MEDIA_TYPE_IMAGE, new Integer[] {
+                MediaPickerData.GALLERY_MEDIA_LOADER },
+                true);
+        final MediaPicker mediaPicker = getFragment();
+        final View view = mediaPicker.getView();
+        assertNotNull(view);
+        final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
+        assertEquals(tabStrip.getChildCount(), 4);
+        for (int i = 0; i < tabStrip.getChildCount(); i++) {
+            final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
+            assertEquals(i == 0, tabButton.isSelected());
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/ui/mediapicker/MockCameraFactory.java b/tests/src/com/android/messaging/ui/mediapicker/MockCameraFactory.java
new file mode 100644
index 0000000..789a78f
--- /dev/null
+++ b/tests/src/com/android/messaging/ui/mediapicker/MockCameraFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.ui.mediapicker;
+
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
+
+import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class MockCameraFactory {
+    private static Map<Camera, CameraInfo> sCameraInfos = new HashMap<Camera, CameraInfo>();
+
+    public static Camera createCamera(int facing) {
+        Camera camera = Mockito.mock(Camera.class);
+        CameraInfo cameraInfo = new CameraInfo();
+        cameraInfo.facing = facing;
+        sCameraInfos.put(camera, cameraInfo);
+        return camera;
+    }
+
+    public static void getCameraInfo(Camera camera, CameraInfo outCameraInfo) {
+        CameraInfo cameraInfo = sCameraInfos.get(camera);
+        outCameraInfo.facing = cameraInfo.facing;
+        outCameraInfo.orientation = cameraInfo.orientation;
+        outCameraInfo.canDisableShutterSound = cameraInfo.canDisableShutterSound;
+    }
+
+    public static CameraWrapper createCameraWrapper(final Camera... cameras) {
+        CameraWrapper wrapper = Mockito.mock(CameraWrapper.class);
+        Mockito.when(wrapper.getNumberOfCameras()).thenReturn(cameras.length);
+        Mockito.when(wrapper.open(Mockito.anyInt())).then(new Answer<Camera>() {
+            @Override
+            public Camera answer(InvocationOnMock invocation) {
+                return cameras[(Integer) invocation.getArguments()[0]];
+            }
+        });
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                getCameraInfo(
+                        cameras[(Integer) invocation.getArguments()[0]],
+                        (CameraInfo) invocation.getArguments()[1]
+                );
+                return null;
+            }
+        }).when(wrapper).getCameraInfo(Mockito.anyInt(), Mockito.any(CameraInfo.class));
+        return wrapper;
+    }
+
+    public static void cleanup() {
+        sCameraInfos.clear();
+    }
+}
diff --git a/tests/src/com/android/messaging/util/BugleGservicesTest.java b/tests/src/com/android/messaging/util/BugleGservicesTest.java
new file mode 100644
index 0000000..e8f1a22
--- /dev/null
+++ b/tests/src/com/android/messaging/util/BugleGservicesTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+
+@SmallTest
+public class BugleGservicesTest extends BugleTestCase {
+
+    public void testGServiceGet() {
+        final BugleGservices bugleGservices = new FakeBugleGservices();
+
+        assertEquals(BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT,
+                bugleGservices.getString(
+                        BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX,
+                        BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT));
+    }
+}
diff --git a/tests/src/com/android/messaging/util/ContactUtilTest.java b/tests/src/com/android/messaging/util/ContactUtilTest.java
new file mode 100644
index 0000000..0a3cfe8
--- /dev/null
+++ b/tests/src/com/android/messaging/util/ContactUtilTest.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.messaging.BugleTestCase;
+import com.android.messaging.FakeFactory;
+
+import org.junit.Assert;
+
+import java.util.ArrayList;
+
+/*
+ * Class for testing ContactUtil.
+ */
+@LargeTest
+public class ContactUtilTest extends BugleTestCase {
+    private static final String TEST_NAME_PREFIX = "BugleTest:";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // TODO: This test will actually mess with contacts on your phone.
+        // Ideally we would use a fake content provider to give us contact data...
+        FakeFactory.registerWithoutFakeContext(getTestContext());
+
+        // add test contacts.
+        addTestContact("John", "650-123-1233", "john@gmail.com", false);
+        addTestContact("Joe", "(650)123-1233", "joe@gmail.com", false);
+        addTestContact("Jim", "650 123 1233", "jim@gmail.com", false);
+        addTestContact("Samantha", "650-123-1235", "samantha@gmail.com", true);
+        addTestContact("Adrienne", "650-123-1236", "adrienne@gmail.com", true);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        deleteTestContacts();
+        super.tearDown();
+    }
+
+    /**
+     * Add a test contact based on contact name, phone and email.
+     */
+    private void addTestContact(
+            final String name, final String phone, final String email, final boolean starred)
+            throws Exception {
+        final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+
+        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
+                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
+                .build());
+
+        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+                .withValue(ContactsContract.Data.MIMETYPE,
+                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
+                        TEST_NAME_PREFIX + name).build());
+
+        if (phone != null) {
+            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+                    .withValue(ContactsContract.Data.MIMETYPE,
+                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
+                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
+                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
+                            ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
+                    .build());
+        }
+
+        if (email != null) {
+            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+                    .withValue(ContactsContract.Data.MIMETYPE,
+                            ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
+                    .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
+                    .withValue(ContactsContract.CommonDataKinds.Email.TYPE,
+                            ContactsContract.CommonDataKinds.Email.TYPE_WORK)
+                    .build());
+        }
+
+        mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+
+        // Star the whole contact if needed.
+        if (starred) {
+            final ContentValues values = new ContentValues();
+            values.put(Contacts.STARRED, 1);
+            getContext().getContentResolver().update(Contacts.CONTENT_URI, values,
+                    Contacts.DISPLAY_NAME + "= ?", new String[] { TEST_NAME_PREFIX + name });
+        }
+    }
+
+    /**
+     * Remove test contacts added during test setup.
+     */
+    private void deleteTestContacts() {
+        final Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                Uri.encode(TEST_NAME_PREFIX));
+        final Cursor cur =
+                mContext.getContentResolver().query(contactUri, null, null, null, null);
+        try {
+            if (cur.moveToFirst()) {
+                do {
+                    final String lookupKey = cur.getString(cur.getColumnIndex(Contacts.LOOKUP_KEY));
+                    final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
+                    mContext.getContentResolver().delete(uri, null, null);
+                } while (cur.moveToNext());
+            }
+        } catch (final Exception e) {
+            LogUtil.e(LogUtil.BUGLE_TAG, "Failed to delete test contacts", e);
+        }
+    }
+
+    /**
+     * Verify ContactUtil.getPhone will return all phones, including the ones added for test.
+     */
+    public void ingoredTestGetPhones() {
+        final Cursor cur = ContactUtil.getPhones(getContext())
+                .performSynchronousQuery();
+
+        LogUtil.i(LogUtil.BUGLE_TAG, "testGetPhones: Number of phones on the device:" +
+                cur.getCount());
+
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
+    }
+
+    /**
+     * Verify ContactUtil.filterPhone will work on name based matches.
+     */
+    public void ingoredTestFilterPhonesByName() {
+        final Cursor cur = ContactUtil.filterPhones(getContext(), TEST_NAME_PREFIX)
+                .performSynchronousQuery();
+
+        if (cur.getCount() != 5) {
+            Assert.fail("Cursor should have size of 5");
+            return;
+        }
+
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
+    }
+
+    /**
+     * Verify ContactUtil.filterPhone will work on partial number matches.
+     */
+    public void ingoredTestFilterPhonesByPartialNumber() {
+        final String[] filters = new String[] { "650123", "650-123", "(650)123", "650 123" };
+
+        for (final String filter : filters) {
+            final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
+                    .performSynchronousQuery();
+
+            LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByPartialNumber: Number of phones:" +
+                    cur.getCount());
+
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
+        }
+    }
+
+    /**
+     * Verify ContactUtil.filterPhone will work on full number matches.
+     */
+    public void ingoredTestFilterPhonesByFullNumber() {
+        final String[] filters = new String[] {
+                "6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
+
+        for (final String filter : filters) {
+            final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
+                    .performSynchronousQuery();
+
+            LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByFullNumber: Number of phones:" +
+                    cur.getCount());
+
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+        }
+    }
+
+    /**
+     * Verify ContactUtil.lookPhone will work on number including area code.
+     */
+    public void ingoredTestLookupPhoneWithAreaCode() {
+        final String[] filters = new String[] {
+                "6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
+
+        for (final String filter : filters) {
+            final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
+                    .performSynchronousQuery();
+
+            LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithAreaCode: Number of phones:" +
+                    cur.getCount());
+
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+        }
+    }
+
+    /**
+     * Verify ContactUtil.lookPhone will work on number without area code.
+     */
+    public void ingoredTestLookupPhoneWithoutAreaCode() {
+        final String[] filters = new String[] {
+                "1231233", "123-1233", "123 1233" };
+
+        for (final String filter : filters) {
+            final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
+                    .performSynchronousQuery();
+
+            LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithoutAreaCode: Number of phones:" +
+                    cur.getCount());
+
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
+            verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
+        }
+    }
+
+    public void ingoredTestGetFrequentPhones() {
+        final Cursor cur = ContactUtil.getFrequentContacts(getContext())
+                .performSynchronousQuery();
+
+        LogUtil.i(LogUtil.BUGLE_TAG, "testGetFrequentPhones: Number of phones on the device:" +
+                cur.getCount());
+
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
+    }
+
+    /**
+     * Verify ContactUtil.filterEmails will work on partial email.
+     */
+    public void ingoredTestFilterEmails() {
+        final Cursor cur = ContactUtil.filterEmails(getContext(), "john@")
+                .performSynchronousQuery();
+
+        LogUtil.i(LogUtil.BUGLE_TAG, "testFilterEmails: Number of emails:" +
+                cur.getCount());
+
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+    }
+
+    /**
+     * Verify ContactUtil.lookupEmail will work on full email.
+     */
+    public void ingoredTestLookupEmail() {
+        final Cursor cur = ContactUtil.lookupEmail(getContext(), "john@gmail.com")
+                .performSynchronousQuery();
+
+        LogUtil.i(LogUtil.BUGLE_TAG, "testLookupEmail: Number of emails:" +
+                cur.getCount());
+
+        verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
+    }
+
+    /**
+     * Utility method to check whether cursor contains a particular contact.
+     */
+    private void verifyCursorContains(final Cursor cursor, final String nameToVerify) {
+        if (cursor.moveToFirst()) {
+            do {
+                final String name = cursor.getString(ContactUtil.INDEX_DISPLAY_NAME);
+                if (TextUtils.equals(name, nameToVerify)) {
+                    return;
+                }
+            } while (cursor.moveToNext());
+        }
+        Assert.fail("Cursor should have " + nameToVerify);
+    }
+}
diff --git a/tests/src/com/android/messaging/util/FakeBugleGservices.java b/tests/src/com/android/messaging/util/FakeBugleGservices.java
new file mode 100644
index 0000000..f7d90da
--- /dev/null
+++ b/tests/src/com/android/messaging/util/FakeBugleGservices.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+/**
+ * Fake implementation which just returns the default values.
+ */
+public class FakeBugleGservices extends BugleGservices {
+    public FakeBugleGservices() {
+    }
+
+    @Override
+    public void registerForChanges(final Runnable r) {
+    }
+
+    @Override
+    public long getLong(final String key, final long defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public int getInt(final String key, final int defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public boolean getBoolean(final String key, final boolean defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public String getString(final String key, final String defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public float getFloat(String key, float defaultValue) {
+        return defaultValue;
+    }
+
+}
diff --git a/tests/src/com/android/messaging/util/FakeBuglePrefs.java b/tests/src/com/android/messaging/util/FakeBuglePrefs.java
new file mode 100644
index 0000000..b3429a6
--- /dev/null
+++ b/tests/src/com/android/messaging/util/FakeBuglePrefs.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+
+/**
+ * Fake implementation which just returns the default values and ignores put operations.
+ */
+public class FakeBuglePrefs extends BuglePrefs {
+    public FakeBuglePrefs() {
+    }
+
+    @Override
+    public int getInt(final String key, final int defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public long getLong(final String key, final long defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public boolean getBoolean(final String key, final boolean defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public String getString(final String key, final String defaultValue) {
+        return defaultValue;
+    }
+
+    @Override
+    public byte[] getBytes(String key) {
+        return null;
+    }
+
+    @Override
+    public void putInt(final String key, final int value) {
+    }
+
+    @Override
+    public void putLong(final String key, final long value) {
+    }
+
+    @Override
+    public void putBoolean(final String key, final boolean value) {
+    }
+
+    @Override
+    public void putString(final String key, final String value) {
+    }
+
+    @Override
+    public void putBytes(String key, byte[] value) {
+    }
+
+    @Override
+    public String getSharedPreferencesName() {
+        return "FakeBuglePrefs";
+    }
+
+    @Override
+    public void onUpgrade(int oldVersion, int newVersion) {
+    }
+
+    @Override
+    public void remove(String key) {
+    }
+}
diff --git a/tests/src/com/android/messaging/util/FakeMediaUtil.java b/tests/src/com/android/messaging/util/FakeMediaUtil.java
new file mode 100644
index 0000000..e37ff0c
--- /dev/null
+++ b/tests/src/com/android/messaging/util/FakeMediaUtil.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.messaging.util;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+
+public class FakeMediaUtil extends MediaUtil {
+    private final MediaPlayer mMediaPlayer;
+    public FakeMediaUtil(final MediaPlayer mediaPlayer) {
+        mMediaPlayer = mediaPlayer;
+    }
+
+    @Override
+    public void playSound(Context context, int resId, OnCompletionListener completionListener) {
+        if (completionListener != null) {
+            completionListener.onCompletion();
+        }
+    }
+}
diff --git a/tests/src/com/android/messaging/util/YouTubeUtilTest.java b/tests/src/com/android/messaging/util/YouTubeUtilTest.java
new file mode 100644
index 0000000..072d3e5
--- /dev/null
+++ b/tests/src/com/android/messaging/util/YouTubeUtilTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.messaging.BugleTestCase;
+
+/*
+ * Class for testing YouTubeUtil.
+ */
+@SmallTest
+public class YouTubeUtilTest extends BugleTestCase {
+    public void testGetYoutubePreviewImageLink() {
+        final String videoId = "dQw4w9WgXcQ";
+        final String videoThumbnailUrl = YouTubeUtil.YOUTUBE_STATIC_THUMBNAIL_PREFIX + videoId
+                + YouTubeUtil.YOUTUBE_STATIC_THUMBNAIL_END;
+
+        // Check known valid youtube links to videos
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/watch?v=" + videoId),
+                videoThumbnailUrl);
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("https://www.youtube.com/watch?v=" + videoId
+                        + "&feature=youtu.be"), videoThumbnailUrl);
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("www.youtube.com/watch?v=" + videoId),
+                videoThumbnailUrl);
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/embed/" + videoId),
+                videoThumbnailUrl);
+        assertEquals(YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/v/" + videoId),
+                videoThumbnailUrl);
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("https://youtube.googleapis.com/v/"
+                        + videoId), videoThumbnailUrl);
+        assertEquals(
+                YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/apiplayer?video_id="
+                        + videoId), videoThumbnailUrl);
+        // This is the type of links that are used as shares from YouTube and will be the most
+        // likely case that we see
+        assertEquals(YouTubeUtil.getYoutubePreviewImageLink("http://youtu.be/" + videoId),
+                videoThumbnailUrl);
+
+        // Try links that shouldn't work
+        assertNull(YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com"));
+    }
+}
\ No newline at end of file
diff --git a/tools/buglesql b/tools/buglesql
new file mode 100755
index 0000000..c9ac8ef
--- /dev/null
+++ b/tools/buglesql
@@ -0,0 +1,43 @@
+#!/bin/bash
+#  Copyright (C) 2015 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.
+
+usage='buglesql [-c] [-r] sql
+  -c display in columns with headers (default)
+  -r display as records'
+
+opts='-column -header'
+
+while test $# -gt 0
+do
+    case $1 in
+        -c)
+            opts='-column -header'
+            shift
+            ;;
+        -r)
+            opts='-line'
+            shift
+            ;;
+        *)
+            break;
+    esac
+done
+
+if [ $# -lt 1 ]; then
+    echo "$usage"
+    exit 1
+fi
+
+adb shell su -c sqlite3 $opts data/data/com.android.messaging/databases/bugle_db "$1"
diff --git a/tools/dumpapkversion.sh b/tools/dumpapkversion.sh
new file mode 100755
index 0000000..48ff590
--- /dev/null
+++ b/tools/dumpapkversion.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#  Copyright (C) 2015 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.
+for i in `find . -name \*.apk`
+do
+	echo -n $i
+	echo -n " "
+	aapt dump badging $i | grep versionCode | sed -E 's/^.*versionCode/versionCode/'
+done
diff --git a/tools/messagegen/fillsms b/tools/messagegen/fillsms
new file mode 100644
index 0000000..dc2e507
--- /dev/null
+++ b/tools/messagegen/fillsms
@@ -0,0 +1,298 @@
+#!/bin/bash
+#  Copyright (C) 2015 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.
+###################################################################
+## Script that generates SMS and MMS messages and fills the Android
+## telephony provider mmssms.db. This is used for testing SMS/MMS.
+###################################################################
+
+AREA_CODE=605
+
+TABLE_CANONICAL_ADDRESSES_START_ID=100
+TABLE_THREADS_START_ID=100
+TABLE_SMS_START_ID=1000
+
+START_TIMESTAMP_IN_SECONDS=1357683093 # 1/8/2013 2:11:33 PM
+TIMESTAMP_INC_IN_SECONDS=120
+
+PART_DIR="/data/data/com.android.providers.telephony/app_parts"
+
+USAGE='fillsms [-f] [-x] <device_phone_number> <# of threads> <# of sms per thread> <# of mms per thread> <image list file> <sql file>
+    -f -- Only generates the SQL file, do not push to the device
+    -x -- Only execute a SQL file
+    -g -- For GB devices
+Examples:
+    # Generate 2 threads each with 10 SMSes and 10 MMSes on device with phone
+    # number +16508619525. MMS messages use images listed in ./images, which list
+    # *.jpg and *.gif files in local directory. The SQL commands are in sql.txt
+    fillsms +16508619525 2 10 10 images sql.txt
+
+    # Same as above but only creating the SQL command file without pushing to
+    # device
+    fillsms -f +16508619525 2 10 10 images sql.txt
+
+    # Just push the sql.txt to device without generating new SQLs
+    fillsms -x +16508619525 2 10 10 images sql.txt
+'
+
+SMIL='<smil> <head> <layout> <root-layout height="%dpx" width="%dpx"> <region fit="meet" height="%dpx" id="Image" left="0" top="0" width="%dpx"/></root-layout> </layout> </head> <body> <par dur="5000ms"> <img region="Image" src="%s"/> </par> </body> </smil>'
+
+MAX_WORDS_PER_MESSAGE=15
+
+DICT=american-english
+
+# don't actually run the sql on device
+opt_sql_only=0
+opt_exec_only=0
+opt_for_gb=0
+
+while test $# -gt 0
+do
+  case $1 in
+    -f)
+      opt_sql_only=1
+      shift
+      ;;
+    -x)
+      opt_exec_only=1
+      shift
+      ;;
+    -g)
+      opt_for_gb=1
+      shift
+      ;;
+    *)
+      break;
+  esac
+done
+
+
+if [ $opt_sql_only -eq "1" -a $opt_exec_only -eq "1" ]; then
+  echo "-f and -x can not coexist"
+  echo "$USAGE"
+  exit 1
+fi
+
+if [ $# -lt 6 ]; then
+  echo "$USAGE"
+  exit 1
+fi
+device_phone=$1
+shift
+num_of_threads=$1
+shift
+sms_per_thread=$1
+shift
+mms_per_thread=$1
+shift
+image_list_file=$1
+shift
+sql_file=$1
+shift
+echo $image_list_file
+
+dict_lines=`wc -l < $DICT`
+image_files=`wc -l < $image_list_file`
+echo $image_files
+
+if [ $mms_per_thread -gt "0" ]; then
+  if [ ! -f $image_list_file ]; then
+    echo "No image files for creating MMS messages"
+    exit 1
+  fi
+fi
+
+echoerr ()
+{
+  echo "$@" 1>&2;
+}
+
+random_value ()
+{
+  echo $(( $RANDOM % $1 + 1 ))
+}
+
+dict_word ()
+{
+  local v=$(random_value $dict_lines)
+  sed $v"q;d" $DICT
+}
+
+gen_message ()
+{
+  local words=$(random_value $MAX_WORDS_PER_MESSAGE)
+  local message=
+  for k in `seq 1 $words`;
+  do
+    local word=$(dict_word)
+    message="$message $word"
+  done
+  echo $message | sed -e "s/'//g"
+}
+
+random_image ()
+{
+  local v=$(random_value $image_files)
+  sed $v"q;d" $image_list_file
+}
+
+add_sql ()
+{
+  echo $1 >> $sql_file
+}
+
+adb_sql ()
+{
+  echo $1
+  adb shell sqlite3 data/data/com.android.providers.telephony/databases/mmssms.db "$1"
+}
+
+adb_sql_with_quotes ()
+{
+  echo $1
+  adb shell "sqlite3 data/data/com.android.providers.telephony/databases/mmssms.db \"$1\""
+}
+######################################################################################
+######################################################################################
+
+if [ $opt_exec_only -eq "0" ]; then
+  # clean up sql file
+  rm -f $sql_file
+
+  add_sql "PRAGMA trusted_schema=1;"
+  # add sql to clean up database
+  add_sql "delete from pdu where _id>=$TABLE_SMS_START_ID;"
+  add_sql "delete from part where _id>=$TABLE_SMS_START_ID;"
+  add_sql "delete from addr where _id>=$TABLE_SMS_START_ID;"
+  add_sql "delete from sms where _id>=$TABLE_SMS_START_ID;"
+  add_sql "delete from threads where _id>=$TABLE_THREADS_START_ID;"
+  add_sql "delete from canonical_addresses where _id>=$TABLE_CANONICAL_ADDRESSES_START_ID;"
+
+  for i in `seq 1 $num_of_threads`;
+  do
+    echo
+    echo "Creating thread $i ......"
+    echo
+
+    # Get random phone number
+    value=$(random_value 1000)
+    middle=$(printf '%03d' $value)
+    value=$(random_value 10000)
+    last=$(printf '%04d' $value)
+    phone="+1$AREA_CODE$middle$last"
+    echo $phone
+    echo
+
+    timestamp=$(( $START_TIMESTAMP_IN_SECONDS + 5 * $TIMESTAMP_INC_IN_SECONDS * $i ))
+
+    # Generate threads
+    addr_id=$(( $TABLE_CANONICAL_ADDRESSES_START_ID + $i ))
+    add_sql "insert into canonical_addresses (_id,address) values ($addr_id,'$phone');"
+
+    thread_id=$(( $TABLE_THREADS_START_ID + $i ))
+    add_sql "insert into threads (_id,date,message_count,recipient_ids,snippet,snippet_cs,read,type,error,has_attachment) values ($thread_id, $timestamp, $sms_per_thread, $addr_id, 'snippet', 0, 1, 0, 0, 0);"
+
+    # Generate SMS
+    if [ $sms_per_thread -gt "0" ]; then
+      add_sql "PRAGMA trusted_schema=1;"
+      half_timestamp_inc=$(( 500 + ((($sms_per_thread + $mms_per_thread) * $TIMESTAMP_INC_IN_SECONDS) * 500 / $sms_per_thread) ))
+      for j in `seq 1 $sms_per_thread`;
+      do
+        message=$(gen_message)
+        date=$(( ( 1000 * $timestamp ) - $half_timestamp_inc * ( 2 * ($sms_per_thread - $j) + ( $i % 2 ) ) ))
+        message_id=$(( $TABLE_SMS_START_ID + $sms_per_thread * $i * 2 + (2 * $j) ))
+        message_type=$(( $j % 2 + 1 ))
+        add_sql "insert into sms (_id,thread_id,address,person,date,status,type,body,read,seen) values ($message_id, $thread_id, '$phone', '$phone', $date, -1, $message_type, '$message', 1, 1);"
+      done
+    fi
+
+    # Generate MMS
+    if [ $mms_per_thread -gt "0" ]; then
+      half_timestamp_inc=$(( 1 + ((($sms_per_thread + $mms_per_thread) * $TIMESTAMP_INC_IN_SECONDS) / ( 2 * $mms_per_thread) ) ))
+      for j in `seq 1 $mms_per_thread`;
+      do
+        image_line=$(random_image)
+        image=`echo $image_line | awk '{ print $1 }'`
+        width=`echo $image_line | awk '{ print $2 }'`
+        height=`echo $image_line | awk '{ print $3 }'`
+        size=`echo $image_line | awk '{ print $4 }'`
+        date=$(( $timestamp - $half_timestamp_inc * ( 2 * ($mms_per_thread - $j) + ( ($i+1) % 2 ) ) ))
+        message_id=$(( $TABLE_SMS_START_ID + $sms_per_thread * $i * 2 + (2 * $j + 1) ))
+        message_type=$(( $j % 2 + 1 ))
+        if [ $message_type -eq '1' ]; then
+          m_type=132
+        else
+          m_type=128
+        fi
+        if [ $opt_for_gb -eq "0" ]; then
+          add_sql "insert into pdu (_id,thread_id,date,date_sent,msg_box,read,m_id,sub,sub_cs,ct_t,m_cls,m_type,v,m_size,pri,rr,tr_id,d_rpt,locked,seen,text_only) values ($message_id, $thread_id, $date, 0, $message_type, 1, 'hmma3p5s1a3m526@w.tmomail.net', 'no subject', 106, 'application/vnd.wap.multipart.related', 'personal', $m_type, 18, $size, 129, 129 , '$message_id', 129, 0, 1, 0);"
+        else
+          add_sql "insert into pdu (_id,thread_id,date,msg_box,read,m_id,sub,sub_cs,ct_t,m_cls,m_type,v,m_size,pri,rr,tr_id,d_rpt,locked,seen) values ($message_id, $thread_id, $date, $message_type, 1, 'hmma3p5s1a3m526@w.tmomail.net', 'no subject', 106, 'application/vnd.wap.multipart.related', 'personal', $m_type, 18, $size, 129, 129 , '$message_id', 129, 0, 1);"
+        fi
+        id_1=$(( $message_id ))
+        id_2=$(( $message_id + 1 ))
+        smil=$(printf "$SMIL" $height $width $height $width $image)
+        add_sql "insert into part (_id,mid,seq,ct,cid,cl,text) values ($id_1, $message_id, -1, 'application/smil', '<smil>', 'smil.xml', '$smil');"
+        image_no_suffix=${image%.*}
+        add_sql "insert into part (_id,mid,seq,ct,cid,cl,_data) values ($id_2, $message_id, 0, 'image/jpeg', '$image_no_suffix', '$image', '$PART_DIR/$image');"
+        if [ $message_type -eq '1' ]; then
+          add_sql "insert into addr (_id,msg_id,address,type,charset) values ($id_1, $message_id, '$phone', 137, 106);"
+          add_sql "insert into addr (_id,msg_id,address,type,charset) values ($id_2, $message_id, '$device_phone', 151, 106);"
+        else
+          add_sql "insert into addr (_id,msg_id,address,type,charset) values ($id_1, $message_id, 'insert-address-token', 137, 106);"
+          add_sql "insert into addr (_id,msg_id,address,type,charset) values ($id_2, $message_id, '$phone', 151, 106);"
+        fi
+      done
+    fi
+  done
+fi
+
+# Push to device
+if [ $opt_sql_only -eq "0" ]; then
+  # make sure we have access
+  adb root
+
+  # Push all local jpgs or gifs to device, being lazy here.
+  if [ $mms_per_thread -gt "0" ]; then
+    for file in `ls *.jpg *.gif`;
+    do
+      echo "adb push $file $PART_DIR/$file"
+      adb push $file $PART_DIR/$file
+    done
+  fi
+
+  echo "adb push $sql_file /data/fillsms"
+  adb push $sql_file /data/fillsms
+  echo
+  adb_sql ".read /data/fillsms"
+  echo
+  add_sql "PRAGMA trusted_schema=1;"
+  echo
+  adb_sql_with_quotes "select count(*) from canonical_addresses where _id>=$TABLE_CANONICAL_ADDRESSES_START_ID;"
+  echo
+  adb_sql_with_quotes "select count(*) from threads where _id>=$TABLE_THREADS_START_ID;"
+  echo
+  if [ $sms_per_thread -gt "0" ]; then
+    adb_sql_with_quotes "select count(*) from sms where _id>=$TABLE_SMS_START_ID;"
+    echo
+  fi
+  if [ $mms_per_thread -gt "0" ]; then
+    adb_sql_with_quotes "select count(*) from pdu where _id>=$TABLE_SMS_START_ID;"
+    echo
+    adb_sql_with_quotes "select count(*) from part where _id>=$TABLE_SMS_START_ID;"
+    echo
+    adb_sql_with_quotes "select count(*) from addr where _id>=$TABLE_SMS_START_ID;"
+    echo
+  fi
+fi
diff --git a/tools/messagegen/listimages b/tools/messagegen/listimages
new file mode 100755
index 0000000..9c50072
--- /dev/null
+++ b/tools/messagegen/listimages
@@ -0,0 +1,21 @@
+#!/bin/bash
+#  Copyright (C) 2015 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.
+
+for file in `ls *.jpg *.gif`;
+do
+  dimension=`identify -format "%w %h" $file`
+  size=`stat -c%s $file`
+  echo "$file $dimension $size"
+done
diff --git a/tools/mmssql b/tools/mmssql
new file mode 100755
index 0000000..1643dbb
--- /dev/null
+++ b/tools/mmssql
@@ -0,0 +1,43 @@
+#!/bin/bash
+#  Copyright (C) 2015 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.
+
+usage='mmssql [-c] [-r] sql
+  -c display in columns with headers (default)
+  -r display as records'
+
+opts='-column -header'
+
+while test $# -gt 0
+do
+    case $1 in
+        -c)
+            opts='-column -header'
+            shift
+            ;;
+        -r)
+            opts='-line'
+            shift
+            ;;
+        *)
+            break;
+    esac
+done
+
+if [ $# -lt 1 ]; then
+    echo "$usage"
+    exit 1
+fi
+
+adb shell su -c sqlite3 $opts data/data/com.android.providers.telephony/databases/mmssms.db "$1"